/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the License).  You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the license at
 * https://glassfish.dev.java.net/public/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Copyright (c) Ericsson AB, 2004-2007. All rights reserved.
 */
package com.ericsson.ssa.sip.wrapper;

import javax.servlet.http.HttpSession;
import javax.servlet.sip.B2buaHelper;
import javax.servlet.sip.ConvergedHttpSession;
import javax.servlet.sip.ServletTimer;
import javax.servlet.sip.SipApplicationSession;
import javax.servlet.sip.SipServletRequest;
import javax.servlet.sip.SipServletResponse;
import javax.servlet.sip.SipSession;

import com.ericsson.ssa.sip.persistence.OnModificationReplicatedApplicationSession;
import com.ericsson.ssa.sip.persistence.OnModificationReplicatedHttpSession;
import com.ericsson.ssa.sip.persistence.OnModificationReplicatedServletTimer;
import com.ericsson.ssa.sip.persistence.OnModificationReplicatedSession;
import com.ericsson.ssa.utils.objectwrapping.ObjectWrapper;
import com.ericsson.ssa.utils.objectwrapping.WrapperContext;
import com.ericsson.ssa.utils.objectwrapping.WrapperUtil;

/**
 * A factory set keeping all the ObjectWrapper factories within one class.  
 * There are also factory method for entities such as B2BuaHelper which are never iterator, 
 * why no factory instance is needed to be returned.
 * 
 * @author epkadsz
 * @since 2007 nov 20
 *
 */
public class WrapperFactorySet extends WrapperUtil {
	
	private static SipRequestWrapperFactory _sipRequestRequestFactory = new SipRequestWrapperFactory();
	private static SipResponseWrapperFactory _sipResponseWrapperFactory = new SipResponseWrapperFactory();
	private static ServletTimerWrapperFactory _servletTimerWrapperFactory = new ServletTimerWrapperFactory();
	private static SipApplicationSessionWrapperFactory _sipApplicationSessionWrapperFactory = new SipApplicationSessionWrapperFactory();
	private static HttpSessionWrapperFactory _httpSessionWrapperFactory = new HttpSessionWrapperFactory();
	private static SipSessionWrapperFactory _sipSessionWrapperFactory = new SipSessionWrapperFactory();
	private static ConvergedSessionWrapperFactory<?> _convergedSessionWrappedFactory = new ConvergedSessionWrapperFactory<Object>();
	
	public static ObjectWrapper<SipApplicationSession> getSASFactory() {
		return _sipApplicationSessionWrapperFactory;
	}
	
	public static ObjectWrapper<ConvergedHttpSession> getHttpSessionFactory() {
		return _httpSessionWrapperFactory;
	}	

	public static ObjectWrapper<SipSession> getSipSessionFactory() {
		return _sipSessionWrapperFactory;
	}
	
	public static ObjectWrapper<?> getConvergedSessionFactory() {
		return _convergedSessionWrappedFactory;
	}	

	public static ObjectWrapper<SipServletRequest> getSipRequestFactory() {
		return _sipRequestRequestFactory;
	}
	
	public static ObjectWrapper<SipServletResponse> getSipResponseFactory() {
		return _sipResponseWrapperFactory;
	}
	
	public static ObjectWrapper<ServletTimer> getServletTimerFactory() {
		return _servletTimerWrapperFactory;
	}	
	
	public static SipServletRequest wrap(SipServletRequest object, WrapperContext context) {
		return getSipRequestFactory().wrap(object, context);
	}
	
	public static SipServletResponse wrap(SipServletResponse object, WrapperContext context) {
		return getSipResponseFactory().wrap(object, context);
	}
	
	public static B2buaHelper wrap(B2buaHelper object, WrapperContext context) {
		return new WrappedB2BUAHelper(object, context);
	}
	
	/**
	 * Variant for using inside container code not knowing so much about the wrapping concept.
	 * This util method will select the proper wrapper factory, wrap and object and pass the wrapping context.
	 * 
	 * The object will ONLY be wrapped if the expectedWrapperObject is wrapped. otherwise the unwrapped version is returned.
	 * 
	 * @param object the object to wrap in.
	 * @param expectedWrappedObject object expected to be wrapped but not knowing how a wrapper looks like.
	 * 
	 * @return a wrapped version of the servlet timer.
	 */
	public static SipServletRequest wrap(SipServletRequest object, Object expectedWrappedObject) {
		if (isWrapped(expectedWrappedObject))
			return wrap(object, revealWrapper(expectedWrappedObject).getContext());
		else
			return object;
	}
	
	/**
	 * Variant for using inside container code not knowing so much about the wrapping concept.
	 * This util method will select the proper wrapper factory, wrap and object and pass the wrapping context.
	 * 
	 * @param object the object to wrap in.
	 * @param expectedWrappedObject object expected to be wrapped but not knowing how a wrapper looks like.
	 * 
	 * @return a wrapped version of the servlet timer.
	 */
	public static SipServletResponse wrap(SipServletResponse object, Object expectedWrappedObject) {
		if (isWrapped(expectedWrappedObject))
			return wrap(object, revealWrapper(expectedWrappedObject).getContext());
		else
			return object;
	}
	
	/**
	 * Variant for using inside container code not knowing so much about the wrapping concept.
	 * This util method will select the proper wrapper factory, wrap and object and pass the wrapping context.
	 * 
	 * @param object the object to wrap in.
	 * @param expectedWrappedObject object expected to be wrapped but not knowing how a wrapper looks like.
	 * 
	 * @return a wrapped version of the servlet timer.
	 */
	public static ServletTimer wrap(ServletTimer object, Object expectedWrappedObject) {
		if (isWrapped(expectedWrappedObject))
			return getServletTimerFactory().wrap(object, revealWrapper(expectedWrappedObject).getContext());
		
		return object;
	}
}

class SipRequestWrapperFactory implements ObjectWrapper<SipServletRequest> {
	public SipServletRequest wrap(SipServletRequest object, WrapperContext context) {
		return new WrappedSipRequest((SipServletRequest)object, context);
	}
}

class SipResponseWrapperFactory implements ObjectWrapper<SipServletResponse> {
	public SipServletResponse wrap(SipServletResponse object, WrapperContext context) {
		return new WrappedSipResponse(object, context);
	}
}

class ServletTimerWrapperFactory implements ObjectWrapper<ServletTimer> {
	public ServletTimer wrap(ServletTimer object, WrapperContext context) {
		return new OnModificationReplicatedServletTimer(object, context);
	}
}

class SipApplicationSessionWrapperFactory implements ObjectWrapper<SipApplicationSession> {
	public SipApplicationSession wrap(SipApplicationSession object, WrapperContext context) {
		if (context != null)
			return new OnModificationReplicatedApplicationSession(object, context);
		else
			return new OnModificationReplicatedApplicationSession(object);
	}
}

class HttpSessionWrapperFactory implements ObjectWrapper<ConvergedHttpSession> {
	public ConvergedHttpSession wrap(ConvergedHttpSession object, WrapperContext context) {
		return new OnModificationReplicatedHttpSession(object, context);
	}
}

class SipSessionWrapperFactory implements ObjectWrapper<SipSession> {
	public SipSession wrap(SipSession object, WrapperContext context) {
		return new OnModificationReplicatedSession(object, context);
	}
}

class ConvergedSessionWrapperFactory<T> implements ObjectWrapper<T> {
	public T wrap(T object, WrapperContext context) {
		if (object instanceof SipSession)
			return (T)WrapperFactorySet.getSipSessionFactory().wrap((SipSession)object, context);
		else
			if (object instanceof HttpSession)
				return (T)WrapperFactorySet.getHttpSessionFactory().wrap((ConvergedHttpSession)object, context);
				
		return object;
	}
}


