package jacorb.poa.util;

/*
 *        JacORB - a free Java ORB
 *
 *   Copyright (C) 1997-98  Gerald Brose.
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Library General Public
 *   License as published by the Free Software Foundation; either
 *   version 2 of the License, or (at your option) any later version.
 *
 *   This library is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *   Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public
 *   License along with this library; if not, write to the Free
 *   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

import jacorb.poa.*;
import jacorb.poa.except.*;
import org.omg.PortableServer.*;

import java.util.Calendar;

/**
 * This class collects some useful routines for the POA.
 *
 * @author Reimo Tiedemann, FU Berlin
 * @version 1.03, 10/07/99, RT
 */
public final class POAUtil {
	/**
	 * converts an oid into a string, if the inHex flag is set
	 * the string contains an hex dump
	 */
	public static String convert(byte[] objectId, boolean inHex) {
		if (inHex) {
			String result = "";
			for (int i=0; i<objectId.length; i++) {
				int n1 = (objectId[i] & 0xff) / 16;
				int n2 = (objectId[i] & 0xff) % 16;
				char c1 = (char)(n1>9 ? ('A'+(n1-10)) : ('0'+n1));
				char c2 = (char)(n2>9 ? ('A'+(n2-10)) : ('0'+n2));
				result = result + ( c1 + (c2 + " "));
			}
			return result;
			
		} else {
			return objectId_to_string(objectId).replace('\n', ' ');
		}
	}
	/**
	 * reads the policy value from the specified policy and
	 * converts it into a string
	 */
	public static String convert(org.omg.CORBA.Policy policy, int policy_type) {
		
		switch (policy_type) {
			
			case THREAD_POLICY_ID.value:
				if (policy == null || ((ThreadPolicy) policy).value() == ThreadPolicyValue.ORB_CTRL_MODEL) return "ORB_CTRL_MODEL";
				else if (((ThreadPolicy) policy).value() == ThreadPolicyValue.SINGLE_THREAD_MODEL) return "SINGLE_THREAD_MODEL";
				break;

			case LIFESPAN_POLICY_ID.value:
				if (policy == null || ((LifespanPolicy) policy).value() == LifespanPolicyValue.TRANSIENT) return "TRANSIENT";
				else if (((LifespanPolicy) policy).value() == LifespanPolicyValue.PERSISTENT) return "PERSISTENT";
				break;
				
			case ID_UNIQUENESS_POLICY_ID.value:
				if (policy == null || ((IdUniquenessPolicy) policy).value() == IdUniquenessPolicyValue.UNIQUE_ID) return "UNIQUE_ID";
				else if (((IdUniquenessPolicy) policy).value() == IdUniquenessPolicyValue.MULTIPLE_ID) return "MULTIPLE_ID";
				break;

			case ID_ASSIGNMENT_POLICY_ID.value:
				if (policy == null || ((IdAssignmentPolicy) policy).value() == IdAssignmentPolicyValue.SYSTEM_ID) return "SYSTEM_ID";
				else if (((IdAssignmentPolicy) policy).value() == IdAssignmentPolicyValue.USER_ID) return "USER_ID";
				break;
				
			case SERVANT_RETENTION_POLICY_ID.value:
				if (policy == null || ((ServantRetentionPolicy) policy).value() == ServantRetentionPolicyValue.RETAIN) return "RETAIN";
				else if (((ServantRetentionPolicy) policy).value() == ServantRetentionPolicyValue.NON_RETAIN) return "NON_RETAIN";
				break;

			case REQUEST_PROCESSING_POLICY_ID.value:
				if (policy == null || ((RequestProcessingPolicy) policy).value() == RequestProcessingPolicyValue.USE_ACTIVE_OBJECT_MAP_ONLY) return "USE_ACTIVE_OBJECT_MAP_ONLY";
				else if (((RequestProcessingPolicy) policy).value() == RequestProcessingPolicyValue.USE_SERVANT_MANAGER) return "USE_SERVANT_MANAGER";
				else if (((RequestProcessingPolicy) policy).value() == RequestProcessingPolicyValue.USE_DEFAULT_SERVANT) return "USE_DEFAULT_SERVANT";
				break;

			case IMPLICIT_ACTIVATION_POLICY_ID.value:
				if (policy == null || ((ImplicitActivationPolicy) policy).value() == ImplicitActivationPolicyValue.NO_IMPLICIT_ACTIVATION) return "NO_IMPLICIT_ACTIVATION";
				else if (((ImplicitActivationPolicy) policy).value() == ImplicitActivationPolicyValue.IMPLICIT_ACTIVATION) return "IMPLICIT_ACTIVATION";
				break;				
		}
		return "unknown";
	}
	/**
	 * converts the state into a string
	 */
	public static String convert(org.omg.PortableServer.POAManagerPackage.State state) {
		if (state.value() == org.omg.PortableServer.POAManagerPackage.State._ACTIVE)
			return "active";
		if (state.value() == org.omg.PortableServer.POAManagerPackage.State._HOLDING)
			return "holding";
		if (state.value() == org.omg.PortableServer.POAManagerPackage.State._DISCARDING)
			return "discarding";
		if (state.value() == org.omg.PortableServer.POAManagerPackage.State._INACTIVE)
			return "inactive";
		
		return "unknown";
	}
	/**
	 * extracts the impl name from a specified object key
	 */
	public static String extractImplName(byte[] object_key) {
		for (int i=0; i<object_key.length; i++) {
			if (object_key[i] == POAConstants.OBJECT_KEY_SEP_BYTE) {
				byte[] result = IdUtil.extract(object_key, 0, i);
				return unmaskStr(new String(result));
			}
		}
		throw new POAInternalError("error extracting impl name from object_key: "+convert(object_key, false));
	}
	/**
	 * extracts the oid from a specified object key
	 */
	public static byte[] extractOID(byte[] object_key) {
		for (int i=object_key.length-1; i>=0; i--) {
			if (object_key[i] == POAConstants.OBJECT_KEY_SEP_BYTE) {
				i++;
				byte[] result = IdUtil.extract(object_key, i, object_key.length - i);
//				jacorb.orb.Environment.output(6, "extractOID, \t\tObject-Key: " + convert(object_key, false) + " \tOID: "+convert(result, true));
				return unmaskId(result);
			}
		}
		throw new POAInternalError("error extracting oid from object_key: "+convert(object_key, false));
	}
	/**
	 * extracts the oid from a specified object reference
	 */
	public static byte[] extractOID(org.omg.CORBA.Object reference) {
		return ((jacorb.orb.Delegate) ((org.omg.CORBA.portable.ObjectImpl) reference)._get_delegate()).getObjectId();
	}
	/**
	 * extracts the poa name from a specified object key
	 */
	public static String extractPOAName(byte[] object_key) {
		int begin = object_key.length;
		int end = 0;
		for (int i=0; i<object_key.length; i++) {
			if (object_key[i] == POAConstants.OBJECT_KEY_SEP_BYTE) {
				begin = i;
				break;
			}
		}
		for (int i=object_key.length-1; i>=0; i--) {
			if (object_key[i] == POAConstants.OBJECT_KEY_SEP_BYTE) {
				end = i;
				break;
			}
		}
		if (begin > end) {
			throw new POAInternalError("error extracting poa name from object_key: "+convert(object_key, false));
		}
		if (begin == end) {
			return "";
		} else {
			begin++;
			return new String(IdUtil.extract(object_key, begin, end-begin));
		}
	}
	/**
	 * returns the policy with the specified policy_type from a policy list  
	 */
	public static org.omg.CORBA.Policy getPolicy(org.omg.CORBA.Policy[] policies, int policy_type) {
		if (policies != null) {
			for (int i = 0; i < policies.length; i++) {
				if (policies[i].policy_type() == policy_type) {
					return policies[i];
				}
			}
		}
		return null;
	}
	public static boolean isActive(org.omg.PortableServer.POAManagerPackage.State state) {
		return state.value() == org.omg.PortableServer.POAManagerPackage.State._ACTIVE ? true : false;
	}
	public static boolean isDiscarding(org.omg.PortableServer.POAManagerPackage.State state) {
		return state.value() == org.omg.PortableServer.POAManagerPackage.State._DISCARDING ? true : false;
	}
	public static boolean isHolding(org.omg.PortableServer.POAManagerPackage.State state) {
		return state.value() == org.omg.PortableServer.POAManagerPackage.State._HOLDING ? true : false;
	}
	public static boolean isInactive(org.omg.PortableServer.POAManagerPackage.State state) {
		return state.value() == org.omg.PortableServer.POAManagerPackage.State._INACTIVE ? true : false;
	}
	/**
	 * masks the object key separator bytes 
	 */
	public static byte[] maskId(byte[] id) {
		int altered = id.length;
		for (int i=0; i<id.length; i++) {
			if (id[i] == POAConstants.OBJECT_KEY_SEP_BYTE) {
				altered++;
			} else if (id[i] == POAConstants.MASK_BYTE) {
				altered++;
			}
		}
		if (altered == id.length) return id;
		
		byte[] result = new byte[altered];

		altered = 0;
		for (int i=0; i<id.length; i++) {
			if (id[i] == POAConstants.OBJECT_KEY_SEP_BYTE) {
				result[altered] = POAConstants.MASK_BYTE;
				result[altered+1] = POAConstants.SEPA_MASK_BYTE;
				altered += 2;
				
			} else if (id[i] == POAConstants.MASK_BYTE) {
				result[altered] = POAConstants.MASK_BYTE;
				result[altered+1] = POAConstants.MASK_MASK_BYTE;
				altered += 2;
				
			} else {
				result[altered] = id[i];
				altered ++;
			}			
		}
		return result;
	}
	/**
	 * masks the object key separator chars
	 */
	public static String maskStr(String str) {
		return new String(maskId(str.getBytes()));
	}
	/**
	 * converts an iod into a string
	 */
	public static String objectId_to_string(byte[] oid) {
		return new String(oid);
	}
	/**
	 * converts a string into an oid
	 */
	public static byte[] string_to_objectId(String str) {	
		return str.getBytes();
	}
	/**
	 * unmasks the object key separator bytes 
	 */
	public static byte[] unmaskId(byte[] id) {
		int altered = id.length;
		for (int i=0; i<id.length; i++) {
			if (id[i] == POAConstants.MASK_BYTE) {
				altered--;
				i++;
			}
		}
		if (altered == id.length) return id;
		
		byte[] result = new byte[altered];

		altered = 0;
		for (int i=0; i<id.length; i++) {
			
			if (id[i] == POAConstants.MASK_BYTE) {
				if (id[i+1] == POAConstants.MASK_MASK_BYTE) {
					result[altered] = POAConstants.MASK_BYTE;
					
				} else if (id[i+1] == POAConstants.SEPA_MASK_BYTE) {
					result[altered] = POAConstants.OBJECT_KEY_SEP_BYTE;
					
				} else {
					throw new POAInternalError("error: forbidden byte sequence \""
						+POAConstants.MASK_BYTE+id[i+1]+"\" (unmaskId)");
				}
				i++;
				
			} else {
				result[altered] = id[i];
			}
			altered++;
		}
		return result;
	}
	/**
	 * unmasks the object key separator chars
	 */
	public static String unmaskStr(String str) {
		return new String(unmaskId(str.getBytes()));
	}
}