/**
 * Copyright © 2008-2009 DRIVER PROJECT (ICM UW)
 *
 * 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 eu.dnetlib.resultset.impl.builder;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.log4j.Logger;

import eu.dnetlib.enabling.resultset.rmi.ResultSetService;

/**
 * ResultSet service builder. Creates ResultSetPortType instances according to the rsLocation.
 * May return embedded IndexResultSet service instance if rsLocation proves to be 
 * local IndexResultSet service address.
 * TODO implement caching mechanizm if needed.
 * @author Marek Horst
 * @version 0.01
 *
 */
public class ResultSetBuilder implements IResultSetBuilder {

	protected static final Logger log = Logger.getLogger(ResultSetBuilder.class);
	
	/**
	 * PortTypes registry.
	 */
	private Map<String, ResultSetService> portTypesRegistry;
	
	/**
	 * Facade to the embedded IndexResultSet instance.
	 */
	private ResultSetService indexResultSetFacade;
	
	/**
	 * Embedded IndexResultSet service address.
	 * Can be used to provide IndexResultSet directly via indexResultSetFacade without having to
	 * go round the SOAP transportation layer.
	 */
	private String embeddedResultSetAddress;
	
	/**
	 * Default constructor.
	 */
	public ResultSetBuilder() {
		this.portTypesRegistry = Collections.synchronizedMap(
				new HashMap<String, ResultSetService>());
	}
	
	/* (non-Javadoc)
	 * @see eu.dnetlib.resultset.impl.builder.IResultSetBuilder#build(java.lang.String)
	 */
	public ResultSetService build(String rsLocation) {
		if (rsLocation==null)
			return null;
		ResultSetService storedPortType = portTypesRegistry.get(rsLocation);
		if (storedPortType!=null) {
			log.debug("Retruning stored ResultSetPortType for rsLocation: "+rsLocation);
			return storedPortType;
		}
		if (embeddedResultSetAddress!=null && embeddedResultSetAddress.equals(rsLocation)) {
			return indexResultSetFacade;
		} else {
//			there might be a good place to introduce caching mechanism (<rsLocation, rsPortType>map)
			return buildPortType(rsLocation);
		}
	}

	/**
	 * Builds {@link ResultSetPortType} object for given resultset location.
	 * @param rsLocation
	 * @return ResultSetPortType object for given resultset location
	 */
	private ResultSetService buildPortType(String rsLocation) {
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
		factory.setServiceClass(ResultSetService.class);
		factory.setAddress(rsLocation);
		return (ResultSetService) factory.create();
	}
	
	/* (non-Javadoc)
	 * @see eu.dnetlib.resultset.impl.builder.IResultSetBuilder#registerService(java.lang.String, org.driver.resultset.ResultSetPortType)
	 */
	public void registerService(String rsLocation, ResultSetService portType) {
		if (rsLocation==null || portType==null) {
			log.warn("Neither rsLocation nor portType can be null");
			return;
		} else {
			portTypesRegistry.put(rsLocation, portType);
		}
	}
	
	/* (non-Javadoc)
	 * @see eu.dnetlib.resultset.impl.builder.IResultSetBuilder#unregisterService(java.lang.String)
	 */
	public ResultSetService unregisterService(String rsLocation) {
		if (rsLocation==null) {
			return null;
		} else {
			return portTypesRegistry.remove(rsLocation);
		}
	}
	
	/**
	 * Returns Facade to the embedded IndexResultSet instance.
	 * @return Facade to the embedded IndexResultSet instance
	 */
	public ResultSetService getIndexResultSetFacade() {
		return indexResultSetFacade;
	}

	/**
	 * Sets Facade to the embedded IndexResultSet instance.
	 * @param indexResultSetFacade
	 */
	public void setIndexResultSetFacade(ResultSetService indexResultSetFacade) {
		this.indexResultSetFacade = indexResultSetFacade;
	}

	/**
	 * Returns Embedded IndexResultSet service address.
	 * @return Embedded IndexResultSet service address
	 */
	public String getEmbeddedResultSetAddress() {
		return embeddedResultSetAddress;
	}

	/**
	 * Sets Embedded IndexResultSet service address.
	 * @param embeddedResultSetAddress
	 */
	public void setEmbeddedResultSetAddress(String embeddedResultSetAddress) {
		this.embeddedResultSetAddress = embeddedResultSetAddress;
	}

	/**
	 * Sets initial port types registry. Allows preregistering services for given locations.
	 * @param portTypesRegistry
	 */
	public void setPortTypesRegistry(Map<String, ResultSetService> portTypesRegistry) {
		this.portTypesRegistry = portTypesRegistry;
	}


}
