/*******************************************************************************
 * Copyright (c) quickfixengine.org  All rights reserved. 
 * 
 * This file is part of the QuickFIX FIX Engine 
 * 
 * This file may be distributed under the terms of the quickfixengine.org 
 * license as defined by quickfixengine.org and appearing in the file 
 * LICENSE included in the packaging of this file. 
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING 
 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A 
 * PARTICULAR PURPOSE. 
 * 
 * See http://www.quickfixengine.org/LICENSE for licensing information. 
 * 
 * Contact ask@quickfixengine.org if any conditions of this licensing 
 * are not clear to you.
 ******************************************************************************/

package quickfix;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The default factory for creating FIX message instances. Create subclasses of this factory for generating custom messages using nonstandard message types.
 */
public class DefaultMessageFactory implements quickfix.MessageFactory {

	private static final Logger log = LoggerFactory.getLogger(DefaultMessageFactory.class);
	
	private static final String QUICKFIX_FIX40_MESSAGE_FACTORY = "quickfix.fix40.MessageFactory";
	private static final String QUICKFIX_FIX41_MESSAGE_FACTORY = "quickfix.fix41.MessageFactory";
	private static final String QUICKFIX_FIX42_MESSAGE_FACTORY = "quickfix.fix42.MessageFactory";
	private static final String QUICKFIX_FIX43_MESSAGE_FACTORY = "quickfix.fix43.MessageFactory";
	private static final String QUICKFIX_FIX44_MESSAGE_FACTORY = "quickfix.fix44.MessageFactory";

	private static Class<?> fix40FactoryClass;
	private static Class<?> fix41FactoryClass;
	private static Class<?> fix42FactoryClass;
	private static Class<?> fix43FactoryClass;
	private static Class<?> fix44FactoryClass;	
	
	private quickfix.MessageFactory fix40Factory;
	private quickfix.MessageFactory fix41Factory;
	private quickfix.MessageFactory fix42Factory;
	private quickfix.MessageFactory fix43Factory;
	private quickfix.MessageFactory fix44Factory;

	static {
		try {
			fix40FactoryClass = Class.forName(QUICKFIX_FIX40_MESSAGE_FACTORY);
		} catch (Exception e) {
			log.debug("MessageFactory class " + QUICKFIX_FIX40_MESSAGE_FACTORY + " cannot be loaded", e);
		}
		try {
			fix41FactoryClass = Class.forName(QUICKFIX_FIX41_MESSAGE_FACTORY);
		} catch (Exception e) {
			log.debug("MessageFactory class " + QUICKFIX_FIX41_MESSAGE_FACTORY + " cannot be loaded", e);
		}
		try {
			fix42FactoryClass = Class.forName(QUICKFIX_FIX42_MESSAGE_FACTORY);
		} catch (Exception e) {
			log.debug("MessageFactory class " + QUICKFIX_FIX42_MESSAGE_FACTORY + " cannot be loaded", e);
		}
		try {
			fix43FactoryClass = Class.forName(QUICKFIX_FIX43_MESSAGE_FACTORY);
		} catch (Exception e) {
			log.debug("MessageFactory class " + QUICKFIX_FIX43_MESSAGE_FACTORY + " cannot be loaded", e);
		}
		try {
			fix44FactoryClass = Class.forName(QUICKFIX_FIX44_MESSAGE_FACTORY);
		} catch (Exception e) {
			log.debug("MessageFactory class " + QUICKFIX_FIX44_MESSAGE_FACTORY + " cannot be loaded", e);
		}		
	}
	
	public DefaultMessageFactory() {
		try {
			if (fix40FactoryClass != null)
				fix40Factory = (quickfix.MessageFactory)fix40FactoryClass.newInstance();
		} catch (Exception e) {
			log.warn("MessageFactory class " + fix40FactoryClass + " cannot be instantiated", e);
		}
		try {
			if (fix41FactoryClass != null)
				fix41Factory = (quickfix.MessageFactory)fix41FactoryClass.newInstance();
		} catch (Exception e) {
			log.warn("MessageFactory class " + fix41FactoryClass + " cannot be instantiated", e);
		}
		try {
			if (fix42FactoryClass != null)
				fix42Factory = (quickfix.MessageFactory)fix42FactoryClass.newInstance();
		} catch (Exception e) {
			log.warn("MessageFactory class " + fix42FactoryClass + " cannot be instantiated", e);
		}
		try {
			if (fix43FactoryClass != null)
				fix43Factory = (quickfix.MessageFactory)fix43FactoryClass.newInstance();
		} catch (Exception e) {
			log.warn("MessageFactory class " + fix43FactoryClass + " cannot be instantiated", e);
		}
		try {
			if (fix44FactoryClass != null)
				fix44Factory = (quickfix.MessageFactory)fix44FactoryClass.newInstance();
		} catch (Exception e) {
			log.warn("MessageFactory class " + fix44FactoryClass + " cannot be instantiated", e);
		}
	}
	
	public Message create(String beginString, String msgType) {
		if (FixVersions.BEGINSTRING_FIX40.equals(beginString)) {
			if (fix40Factory != null) 
				return fix40Factory.create(beginString, msgType);
			else
				throw new RuntimeException("No message factory for " + beginString);
		}
		if (FixVersions.BEGINSTRING_FIX41.equals(beginString)) {
			if (fix41Factory != null) 
				return fix41Factory.create(beginString, msgType);
			else
				throw new RuntimeException("No message factory for " + beginString);
		}
		if (FixVersions.BEGINSTRING_FIX42.equals(beginString)) {
			if (fix42Factory != null) 
				return fix42Factory.create(beginString, msgType);
			else
				throw new RuntimeException("No message factory for " + beginString);
		}
		if (FixVersions.BEGINSTRING_FIX43.equals(beginString)) {
			if (fix43Factory != null) 
				return fix43Factory.create(beginString, msgType);
			else
				throw new RuntimeException("No message factory for " + beginString);
		}
		if (FixVersions.BEGINSTRING_FIX44.equals(beginString)) {
			if (fix44Factory != null) 
				return fix44Factory.create(beginString, msgType);
			else
				throw new RuntimeException("No message factory for " + beginString);
		}
		return new Message();
	}

	public Group create(String beginString, String msgType, int correspondingFieldID) {
		if (FixVersions.BEGINSTRING_FIX40.equals(beginString)) {
			if (fix40Factory != null) 
				return fix40Factory.create(beginString, msgType, correspondingFieldID);
			else
				throw new RuntimeException("No message factory for " + beginString);
		}
		if (FixVersions.BEGINSTRING_FIX41.equals(beginString)) {
			if (fix41Factory != null) 
				return fix41Factory.create(beginString, msgType, correspondingFieldID);
			else
				throw new RuntimeException("No message factory for " + beginString);
		}
		if (FixVersions.BEGINSTRING_FIX42.equals(beginString)) {
			if (fix42Factory != null) 
				return fix42Factory.create(beginString, msgType, correspondingFieldID);
			else
				throw new RuntimeException("No message factory for " + beginString);
		}
		if (FixVersions.BEGINSTRING_FIX43.equals(beginString)) {
			if (fix43Factory != null) 
				return fix43Factory.create(beginString, msgType, correspondingFieldID);
			else
				throw new RuntimeException("No message factory for " + beginString);
		}
		if (FixVersions.BEGINSTRING_FIX44.equals(beginString)) {
			if (fix44Factory != null) 
				return fix44Factory.create(beginString, msgType, correspondingFieldID);
			else
				throw new RuntimeException("No message factory for " + beginString);
		}
		throw new IllegalArgumentException("Unsupported FIX version: " + beginString);
	}
}

