Package hermes.fix.quickfix

Source Code of hermes.fix.quickfix.AbstractQuickFIXMessage$MyDecoderOutput

/*
* Copyright 2003,2004,2005 Colin Crist
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package hermes.fix.quickfix;

import hermes.HermesRuntimeException;
import hermes.fix.FIXMessage;
import hermes.fix.NoSuchFieldException;

import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.log4j.Logger;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import quickfix.DataDictionary;
import quickfix.Field;
import quickfix.FieldNotFound;
import quickfix.InvalidMessage;
import quickfix.Message;
import quickfix.field.MsgSeqNum;
import quickfix.field.MsgType;
import quickfix.field.OnBehalfOfCompID;
import quickfix.field.OnBehalfOfSubID;
import quickfix.field.SenderCompID;
import quickfix.field.SendingTime;
import quickfix.field.TargetCompID;
import quickfix.mina.message.FIXMessageDecoder;

/**
* This abstract FIX message uses a cache to hold all releated Java objects once
* the message has been marshalled. When the marshalled message is evicted from
* the cache, the reset() method is called letting this message perform
* additional cleanup.
*
* @author colincrist@hermesjms.com
* @version $Id: AbstractQuickFIXMessage.java,v 1.5 2007/02/28 10:47:27
*          colincrist Exp $
*/

public abstract class AbstractQuickFIXMessage implements FIXMessage {

  private static Set<Integer> retainedFields;
  private Lock lock = new ReentrantLock();

  static {
    retainedFields = new HashSet<Integer>();

    retainedFields.add(SenderCompID.FIELD);
    retainedFields.add(TargetCompID.FIELD);
    retainedFields.add(SendingTime.FIELD);
    retainedFields.add(MsgSeqNum.FIELD);
    retainedFields.add(MsgType.FIELD);
    retainedFields.add(OnBehalfOfCompID.FIELD);
    retainedFields.add(OnBehalfOfSubID.FIELD);
  }

  private static final Logger log = Logger.getLogger(AbstractQuickFIXMessage.class);

  class MyDecoderOutput implements ProtocolDecoderOutput {
    public void write(Object object) {
      try {
        getCache().put(AbstractQuickFIXMessage.this, new Message((String) object));
      } catch (Exception ex) {
        log.error(ex.getMessage(), ex);

        throw new HermesRuntimeException(ex);
      }
    }

    public void flush() {
      // TODO Auto-generated method stub

    }
  }

  public AbstractQuickFIXMessage(QuickFIXMessageCache cache) {
    this.cache = cache;
  }

  public QuickFIXMessageCache getCache() {
    return cache;
  }

  private volatile Map<Integer, Field> allFields;
  private volatile Map<Integer, Field> cachedFields = new HashMap<Integer, Field>();
  private DataDictionary dictionary;
  private QuickFIXMessageCache cache;

  private FIXMessageDecoder getDecoder() throws UnsupportedEncodingException {
    return cache.getDecoder();
  }

  public String getMsgType() {
    return getString(MsgType.FIELD);
  }

  public synchronized Set<Integer> getFieldOrder() {
    return getAllFields().keySet();
  }

  public boolean fieldExists(int tag) {
    if (cachedFields.containsKey(tag)) {
      return true;
    }

    return getAllFields().containsKey(tag);
  }

  public Map<Integer, Field> getAllFields() {
    if (allFields == null) {
      try {
       

        final Message message = getMessage();

        lock.lock();
        allFields = new LinkedHashMap<Integer, Field>();

        if (message == null) {
          return new HashMap<Integer, Field>();
        }

        for (final Iterator iterator = message.getHeader().iterator(); iterator.hasNext();) {
          Field field = (Field) iterator.next();
          allFields.put(field.getTag(), field);

          if (retainedFields.contains(field.getTag())) {
            cachedFields.put(field.getTag(), field);
          }
        }

        for (final Iterator iterator = message.iterator(); iterator.hasNext();) {
          Field field = (Field) iterator.next();
          int tag = field.getTag();

          if (!allFields.containsKey(tag)) {
            allFields.put(tag, field);

            if (retainedFields.contains(field.getTag())) {
              cachedFields.put(field.getTag(), field);
            }
          }
        }

        for (Iterator groupsKeys = message.groupKeyIterator(); groupsKeys.hasNext();) {
          int groupCountTag = ((Integer) groupsKeys.next()).intValue();
        }

        for (final Iterator iterator = message.getTrailer().iterator(); iterator.hasNext();) {
          Field field = (Field) iterator.next();
          allFields.put(field.getTag(), field);

          if (retainedFields.contains(field.getTag())) {
            cachedFields.put(field.getTag(), field);
          }
        }
      } finally {
        lock.unlock();
      }
    }
    return allFields;

  }

  public void reset() {
    lock.lock();

    try {
      if (allFields != null) {
        allFields.clear();
      }
      allFields = null;
    } finally {
      lock.unlock();
    }
  }

  public Object getObject(Field field) {
    if (cachedFields.containsKey(field)) {
      return cachedFields.get(field).getObject();
    }

    Field cached = getAllFields().get(field.getTag());

    if (cached != null) {
      return cached.getObject();
    } else {
      return null;
    }
  }

  public Object getObject(int tag) throws NoSuchFieldException {
    if (cachedFields.containsKey(tag)) {
      return getObject(cachedFields.get(tag));
    }

    if (getAllFields().containsKey(tag)) {
      return getObject(getAllFields().get(tag));
    } else {
      throw new NoSuchFieldException(tag);
    }

  }

  public String getString(int field) {
    try {
      if (cachedFields.containsKey(field)) {
        return cachedFields.get(field).getObject().toString();
      }

      if (getAllFields().containsKey(field)) {
        return getAllFields().get(field).getObject().toString();
      } else {
        throw new FieldNotFound("No such field " + field);
      }
    } catch (FieldNotFound e) {
      throw new HermesRuntimeException(e);
    }
  }

  public DataDictionary getDictionary() {
    return dictionary;
  }

  protected void setDictionary(DataDictionary dictionary) {
    this.dictionary = dictionary;
  }

  public String toString() {
    return new String(getBytes());
  }

  public Message getMessage() {
    getCache().lock();

    try {
      if (!getCache().contains(AbstractQuickFIXMessage.this)) {
        try {
          Message message = new Message(new String(getBytes()), dictionary, false);

          getCache().put(this, message);

          if (getDictionary() == null) {
            setDictionary(QuickFIXUtils.getDictionary(message));
          }

          return message;
        } catch (InvalidMessage e) {
          log.error("Ignoring invalid message: " + e.getMessage(), e);
          return null;
        } catch (Exception e) {
          throw new HermesRuntimeException(e);
        }
      } else {
        return getCache().get(this);
      }
    } finally {
      getCache().unlock();
    }
  }
}
TOP

Related Classes of hermes.fix.quickfix.AbstractQuickFIXMessage$MyDecoderOutput

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.