Ptidej-v5.2-master/PADL Creator JavaFile (Eclipse)/src/padl/creator/javafile/eclipse/util/PadlParserUtil.java
/*******************************************************************************
 * Copyright (c) 2001-2014 Yann-Gal Guhneuc and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Yann-Gal Guhneuc and others, see in file; API and its implementation
 ******************************************************************************/
package padl.creator.javafile.eclipse.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.commons.lang.ArrayUtils;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import padl.kernel.Constants;
import padl.kernel.IAbstractLevelModel;
import padl.kernel.ICodeLevelModel;
import padl.kernel.IConstituent;
import padl.kernel.IConstituentOfEntity;
import padl.kernel.IEntity;
import padl.kernel.IFirstClassEntity;
import padl.kernel.IPackage;
import padl.kernel.IParameter;
import padl.kernel.impl.Factory;

public class PadlParserUtil {

	private static final String DEFAULT_PACKAGE_NAME_STRING =
		"(Default Package)";
	private static final char[] DEFAULT_PACKAGE_NAME =
		PadlParserUtil.DEFAULT_PACKAGE_NAME_STRING.toCharArray();

	/**
	 * 
	 */
	public static char[] computeMethodNodeSignature(
		final MethodDeclaration node,
		final ICodeLevelModel model,
		final IPackage packag) {
		final String name = node.getName().toString();
		String returnTypeName = null;
		final int modifier = node.getModifiers();
		final List<IParameter> listOfParameters =
			PadlParserUtil
				.getListOfParameters(node.parameters(), packag, model);
		// compute method's signature
		if (!node.isConstructor()) {
			if (node.getReturnType2() != null) {
				final ITypeBinding typeBinding =
					node.getReturnType2().resolveBinding();
				if (typeBinding != null) {
					returnTypeName =
						PadlParserUtil.getTypeName(typeBinding, false);
				}
			}
		}

		char[] operationID = null;
		if (node.isConstructor()) {
			operationID =
				PadlParserUtil.computeSignature(
					"<init>",
					listOfParameters,
					returnTypeName,
					modifier);
		}
		else {
			operationID =
				PadlParserUtil.computeSignature(
					name,
					listOfParameters,
					returnTypeName,
					modifier);
		}

		return operationID;

	}

	/**
	 * Compute method or constructor's signature
	 * 
	 * @param methodName
	 * @param parametersList
	 * @param returnType
	 * @param modifier
	 * @return
	 */
	public static char[] computeSignature(
		final String methodName,
		final List<IParameter> parametersList,
		final String returnType,
		final int modifier) {
		final StringBuffer methodSignature = new StringBuffer();

		// signature= methodName(param1, param2,...,paramn)
		methodSignature.append(methodName);
		methodSignature.append("(");

		Iterator<IParameter> iter;
		if (!parametersList.isEmpty()) {
			iter = parametersList.iterator();
			IParameter parameter = iter.next();
			methodSignature.append(parameter.getDisplayTypeName());
			// to take into account multiple dimensions arrays as I saw in padl
			// .class
			int arrayDim = Integer.parseInt(parameter.getComment());
			for (int i = 1; i < arrayDim; i++) {
				methodSignature.append("[]");
			}
			// clear this field
			parameter.setComment("");
			while (iter.hasNext()) {
				methodSignature.append(", ");
				parameter = iter.next();
				methodSignature.append(parameter.getDisplayTypeName());
				arrayDim = Integer.parseInt(parameter.getComment());
				for (int i = 1; i < arrayDim; i++) {
					methodSignature.append("[]");
				}
				parameter.setComment("");

			}
		}
		methodSignature.append(")");

		return methodSignature.toString().toCharArray();
	}

	/**
	 * Compute a simple name (the term after the last .) from a qualified name
	 * 
	 * @param aFullyQualifiedName
	 * @return
	 */
	public static char[] computeSimpleName(final char[] aFullyQualifiedName) {
		//	final String fullyQualifiedName =
		//		ArrayUtils.toString(aFullyQualifiedName);
		final int index = ArrayUtils.lastIndexOf(aFullyQualifiedName, '.');

		final char[] name =
			ArrayUtils.subarray(
				aFullyQualifiedName,
				index + 1,
				aFullyQualifiedName.length);

		return name;
	}

	/**
	 * Create a ghost (this can lead the creation of ghost packages)
	 * 
	 * @param anAbstractLevelModel
	 * @param anEntityName
	 * @return
	 */
	public static IFirstClassEntity createGhost(
		final IAbstractLevelModel anAbstractLevelModel,
		final char[] aFullyQualifiedName) {

		final IPackage enclosingPackage =
			PadlParserUtil.searchForPackage(
				anAbstractLevelModel,
				aFullyQualifiedName,
				new PackageCreator() {
					public IPackage create(final char[] aName) {
						return Factory.getInstance().createPackageGhost(aName);
					}
				});

		final IFirstClassEntity firstClassEntity;
		if (enclosingPackage.doesContainConstituentWithID(aFullyQualifiedName)) {

			firstClassEntity =
				(IFirstClassEntity) enclosingPackage
					.getConstituentFromID(aFullyQualifiedName);
		}
		else {
			firstClassEntity =
				anAbstractLevelModel.getFactory().createGhost(
					aFullyQualifiedName,
					PadlParserUtil.computeSimpleName(aFullyQualifiedName));
			enclosingPackage.addConstituent(firstClassEntity);
		}
		return firstClassEntity;
	}

	/**
	 * Create a top level package
	 * 
	 * @param aPackageName
	 * @param aCodeLevelModel
	 * @return
	 */
	private static IPackage createPackage(
		final char[] aPackageName,
		final ICodeLevelModel aCodeLevelModel) {

		IPackage packaje =
			(IPackage) aCodeLevelModel.getConstituentFromName(aPackageName);

		if (packaje == null) {
			packaje = aCodeLevelModel.getFactory().createPackage(aPackageName);
			aCodeLevelModel.addConstituent(packaje);
		}

		return packaje;
	}

	/**
	 * Create a sub package
	 * 
	 * @param aPackageName
	 * @param aPackage
	 * @param aCodeLevelModel
	 * @return
	 */
	private static IPackage createPackage(
		final char[] aPackageName,
		final IPackage aPackage,
		final ICodeLevelModel aCodeLevelModel) {

		// Fix for eclipse_12-15-2009 (fixed)
		// This is for the case where the package contains another constituent
		// (class or interface) with the same name
		IConstituent packaje = aPackage.getConstituentFromName(aPackageName);

		if (packaje == null || !(packaje instanceof IPackage)) {
			packaje = aCodeLevelModel.getFactory().createPackage(aPackageName);
			aPackage.addConstituent((IPackage) packaje);
		}

		return (IPackage) packaje;

	}

	/**
	 * extract the name of a package via the name of an entity
	 * 
	 * @param aJVMClassName
	 * @return
	 */
	public static char[] extractPackageName(final char[] aJVMClassName) {
		if (ArrayUtils.indexOf(aJVMClassName, '.') == -1) {
			return PadlParserUtil.DEFAULT_PACKAGE_NAME;
		}
		else {
			return ArrayUtils.subarray(
				aJVMClassName,
				0,
				ArrayUtils.lastIndexOf(aJVMClassName, '.'));
		}
	}

	/**
	 * Return the dimension of a type
	 * 
	 * @param aTypeBinding
	 * @return
	 */
	public static int getDim(final ITypeBinding aTypeBinding) {
		if (aTypeBinding.isArray()) {
			return Constants.CARDINALITY_MANY;
		}

		ITypeBinding typeBinding = aTypeBinding;
		if (aTypeBinding.isParameterizedType()) {
			typeBinding = aTypeBinding.getErasure();
		}
		if (padl.util.Util.isArrayOrCollection(typeBinding
			.getQualifiedName()
			.toCharArray())) {
			return Constants.CARDINALITY_MANY;
		}
		else {
			return Constants.CARDINALITY_ONE;
		}
	}

	/**
	 * get an existing entity or get or create a ghost
	 * 
	 * @param anEntityTypeBinding
	 * @return
	 */
	public static IEntity getEntityOrGetOrCreateGhost(
		final boolean isDealingWithExtend,
		final ITypeBinding anEntityTypeBinding,
		final ICodeLevelModel aPadlModel,
		final String aCurrentPackageName) {

		ITypeBinding entityBinding = anEntityTypeBinding;

		if (entityBinding.isArray()) {
			entityBinding = entityBinding.getElementType();

		}

		if (entityBinding.isParameterizedType()) {
			entityBinding = entityBinding.getErasure();
		}

		if (entityBinding.isPrimitive()) {
			return aPadlModel.getFactory().createPrimitiveEntity(
				entityBinding.getName().toCharArray());
		}

		if (entityBinding.isFromSource()
				&& !entityBinding.isTypeVariable()// case of templates
				&& (entityBinding.isClass() || entityBinding.isInterface() || entityBinding
					.isMember())) {
			// It is not a ghost and it is a class or an interface or a member
			// class or interface and it is not a isTypeVariable
			// get it from the existing padl model or create a ghost if it is
			// not there
			return PadlParserUtil.getExistingEntity(
				isDealingWithExtend,
				entityBinding,
				aPadlModel,
				aCurrentPackageName);
		}
		else {
			// It is a ghost --- see perhaps there are others considerations
			// to take into account; for the moment generic types (templates)
			// are created as ghosts
			return PadlParserUtil.getOrCreateGhostEntity(
				isDealingWithExtend,
				entityBinding,
				aPadlModel,
				aCurrentPackageName);
		}
	}

	/**
	 * get concrete entity : Only get because, now we create all the entities in
	 * the first parse so no need to create them before discovering them in the
	 * code
	 * 
	 * @param anEntityTypeBinding
	 * @return
	 */
	private static IFirstClassEntity getExistingEntity(
		final boolean isDealingWithExtend,
		final ITypeBinding anEntityTypeBinding,
		final ICodeLevelModel aPadlModel,
		final String aCurrentPackageName) {

		final String entityQualifiedName =
			anEntityTypeBinding.getQualifiedName();

		final String packagePath;

		// if (anEntityTypeBinding.getPackage() == null: Fix for
		// eclipse_12-15-2009 (fixed)
		// it is leaded by typeVariable binding which are now stopped at
		// previous level
		//TODO rename this variable packageId and current package name is package current path (to be checked)
		packagePath = anEntityTypeBinding.getPackage().getName();

		StringTokenizer tokenizer;

		final String searchedEntityID =
			PadlParserUtil.renameWith$(entityQualifiedName, packagePath);

		int nbTokens;

		tokenizer = new StringTokenizer(searchedEntityID, "$");

		nbTokens = tokenizer.countTokens();

		IPackage searchedPackage;

		IFirstClassEntity currentEntity = null;
		String currentEntityID;
		//	String currentEntityName;

		IFirstClassEntity currentMemberEntity;
		String currentMemberEntityID;
		String currentMemberEntityName;

		// Get the package

		if (packagePath.length() == 0) {// default package
			searchedPackage =
				(IPackage) aPadlModel
					.getConstituentFromID(Constants.DEFAULT_PACKAGE_ID);
		}
		else {
			searchedPackage =
				PadlParserUtil.getPackage(packagePath, aPadlModel);
		}
		if (searchedPackage == null) {
			// Source class but not existing in the current model
			return PadlParserUtil.getOrCreateGhostEntity(
				isDealingWithExtend,
				anEntityTypeBinding,
				aPadlModel,
				aCurrentPackageName);
		}

		if (nbTokens > 0) {
			// Hierarchy... 1st entity (top entity), 1st token
			currentEntityID = tokenizer.nextToken();
			//	currentEntityName =
			//		currentEntityID.substring(currentEntityID.lastIndexOf('.') + 1);

			// get entity
			currentEntity =
				(IFirstClassEntity) searchedPackage
					.getConstituentFromID(currentEntityID.toCharArray());
			if (currentEntity == null) {
				// Source class but not existing in the current model
				return PadlParserUtil.getOrCreateGhostEntity(
					false,
					anEntityTypeBinding,
					aPadlModel,
					aCurrentPackageName);
			}
			// The members classes which don't exist in their classes are not
			// deal in this part;
			// this kind of ITypeBinding is like not from source

			// Get member entity
			// I assume that all member entities are created because when a
			// class member does not exist, exemple, A exists but
			// A.B does not exist, the system does not recognize A.B as from
			// source so we will go directly in the ghost handler
			// see the code before 04/11 to see the recursive creation of member
			// entities (I delete this part here because no need to create them)
			// If this member is not a class but an enum, we are in the trouble,
			// it will return null so we put a check for that; in this case we
			// will send the request to the ghost handler

			while (tokenizer.hasMoreTokens()) {
				currentMemberEntityName = tokenizer.nextToken();
				currentMemberEntityID =
					currentEntity.getDisplayID() + '$'
							+ currentMemberEntityName;

				currentMemberEntity =
					(IFirstClassEntity) currentEntity
						.getConstituentFromID(currentMemberEntityID
							.toCharArray());

				currentEntity = currentMemberEntity;
				// case of subclasses declared in enum or in a class not visited
				// perhaps because another class same id has been parsed first
				// This is when we search parameters types
				// we will create in this case a ghost

				if (currentEntity == null) {
					return PadlParserUtil.getOrCreateGhostEntity(
						isDealingWithExtend,
						anEntityTypeBinding,
						aPadlModel,
						aCurrentPackageName);
				}

			}
			// The last entity got in the padl model is which
			// is searched for
		}

		return currentEntity;
	}

	public static List<IParameter> getListOfParameters(
		final List<?> aListOfVars,
		final IPackage packag,
		final ICodeLevelModel model) {
		// get the list of parameters

		final List<IParameter> listOfParameters = new ArrayList<IParameter>();
		final Iterator<?> iterator = aListOfVars.iterator();
		while (iterator.hasNext()) {
			final SingleVariableDeclaration var =
				(SingleVariableDeclaration) iterator.next();
			if (var.resolveBinding() != null) {
				final ITypeBinding type = var.resolveBinding().getType();
				final IEntity entity =
					PadlParserUtil.getEntityOrGetOrCreateGhost(
						false,
						type,
						model,
						packag.getDisplayPath());

				// Yann: May be null when parsing Foutse's Eclipse data!
				// TODO: Understand why it could be null...
				if (entity != null) {
					// Yann 2015/04/15: Dimensions!
					// I don't forget to add +1 because
					//	int 	has for cardinality 1
					//	int[]	has for cardinality 2
					//	int[][]	has for cardniality 3
					//	...
					final int dim = PadlParserUtil.getDim(type) + 1;
					final IParameter parameter =
						model.getFactory().createParameter(
							entity,
							var.getName().toString().toCharArray(),
							dim);

					parameter.setVisibility(var.getModifiers());
					// I will use the field comment of param to register the
					// dimension of this param if it is an array
					// After using this information during method signature
					// computation, I will delete it
					// This for having the same information with padl .class
					// Aminata 05/05/11
					parameter.setComment(Integer.toString(dim));
					listOfParameters.add(parameter);
				}
			}
		}
		return listOfParameters;
	}

	/**
	 * Get or create a ghost entity
	 * 
	 * @param isDealingWithExtend
	 * @param anEntityTypeBinding
	 * @param aPadlModel
	 * @param aCurrentPackagePath
	 * @return
	 */
	private static IFirstClassEntity getOrCreateGhostEntity(
		final boolean isDealingWithExtend,
		final ITypeBinding anEntityTypeBinding,
		final ICodeLevelModel aPadlModel,
		final String aCurrentPackagePath) {

		final StringBuffer tmpStringBuffer = new StringBuffer();
		String ghostName = null;
		String ghostPackagePath = null;
		String fullyQualifiedName = null;
		final String entityBindingKey = anEntityTypeBinding.getKey();
		final String prefix = "Recovered#currentType";

		if (entityBindingKey.startsWith(prefix)) {
			// ghosts in existing entities
			tmpStringBuffer.append(entityBindingKey.substring(prefix.length()));
			tmpStringBuffer.deleteCharAt(tmpStringBuffer.length() - 1);

			// Yann 2015/03/16: Symbols collision with IConstants!
			// I make sure that the name of the entity does not contain
			// any symbol used in the models, see IConstants, because
			// the entityBindingKey will be of the form:
			//	org.hibernate.envers.entities.mapper.relation.lazy.initializor.Initializor<List<U>>0<Ljava/util/List<Lorg/hibernate/envers/entities/mapper/relation/lazy/proxy/C:\Data\Java Programs\hibernate-orm-3.6.4.Final\hibernate-envers\src\main\java\org\hibernate\envers\entities\mapper\relation\lazy\proxy\ListProxy~ListProxy;:TU;>;>
			if (entityBindingKey.indexOf('/') > -1
					|| entityBindingKey.indexOf('\\') > -1) {

				ghostName =
					tmpStringBuffer.substring(0, tmpStringBuffer.indexOf("0"));
			}
			else {
				ghostName = tmpStringBuffer.toString();
			}
			ghostPackagePath = anEntityTypeBinding.getPackage().getName();
		}
		else if (isDealingWithExtend
				&& entityBindingKey.startsWith("Recovered#typeBinding")) {

			ghostName = anEntityTypeBinding.getQualifiedName();
			ghostPackagePath = anEntityTypeBinding.getPackage().getName();
		}
		else {
			// Pure ghosts
			// Fix for eclipse_12-15-2009 (fixed) case of generic types
			// (templates) (fixed)
			final String[] packageComponents;
			if (anEntityTypeBinding.getPackage() == null) {// case of templates
				packageComponents = new String[0];
				// should be deleted (only for debug purpose)
				/*
				 * Output .getInstance() .normalOutput() .println(
				 * "PadlParserUtil in getOrCreateGhostEntity anEntityTypeBinding.getPackage() == null "
				 * + anEntityTypeBinding .getQualifiedName());
				 */
			}
			else {
				packageComponents =
					anEntityTypeBinding.getPackage().getNameComponents();
			}

			final int numberOfNames = packageComponents.length;

			char firstLetter;
			int i = 0;
			boolean checkPackage = true;

			if (numberOfNames > 0) {
				firstLetter = packageComponents[0].toCharArray()[0];
				if (Character.isLowerCase(firstLetter)) {
					tmpStringBuffer.append(packageComponents[0]);
					i++;
				}
				else {
					checkPackage = false;
				}

				while (i < numberOfNames && checkPackage) {
					firstLetter = packageComponents[i].toCharArray()[0];
					if (Character.isLowerCase(firstLetter)) {
						tmpStringBuffer.append('.');
						tmpStringBuffer.append(packageComponents[i]);
						i++;
					}
					else {
						checkPackage = false;
					}
				}
			}

			ghostPackagePath = tmpStringBuffer.toString();
			// why? aCurrentPackagePath=display path, is it more than the
			// package???
			String packagePath = aCurrentPackagePath;
			if (aCurrentPackagePath.length() > 2) {
				/*
				 * Output .getInstance() .normalOutput() .println(
				 * "PadlParserUtil in getOrCreateGhostEntity aCurrentPackagePath.length() > 2 "
				 * + aCurrentPackagePath.length());
				 */
				packagePath =
					aCurrentPackagePath.substring(
						aCurrentPackagePath.indexOf('|') + 1).replace("|", ".");
			}

			// if package ghost is the same with the current package and this
			// ghost is not from source
			// this means generally that there is a probleme of resolving so we
			// put this ghost in a specific package
			// also when this ghost is a generic type, we do the same
			// These conditions are not always true but permit to handle a lot
			// of cases
			if ((ghostPackagePath.equals(packagePath) || ghostPackagePath
				.length() == 0
					&& ArrayUtils.isEquals(
						packagePath.toCharArray(),
						Constants.DEFAULT_PACKAGE_ID))
					&& !anEntityTypeBinding.isFromSource()
					|| ghostPackagePath.length() == 0
					&& anEntityTypeBinding.isFromSource()
					&& anEntityTypeBinding.isTypeVariable()) {
				ghostPackagePath = "unknown.ghost.packag";
			}

			tmpStringBuffer.setLength(0);

			while (i < numberOfNames) {
				tmpStringBuffer.append(packageComponents[i]);
				tmpStringBuffer.append('.');

				i++;
			}

			tmpStringBuffer.append(anEntityTypeBinding.getName());
			ghostName = tmpStringBuffer.toString();

		}

		tmpStringBuffer.setLength(0);
		tmpStringBuffer.append(ghostPackagePath);
		if (tmpStringBuffer.length() != 0) {
			tmpStringBuffer.append('.');
		}
		tmpStringBuffer.append(ghostName);
		fullyQualifiedName = tmpStringBuffer.toString();

		final int indexOfDot = ghostName.lastIndexOf('.');

		if (indexOfDot < 0) {
			// Case of a ghost
			IFirstClassEntity ghost =
				aPadlModel.getTopLevelEntityFromID(fullyQualifiedName
					.toCharArray());
			if (ghost == null) {
				ghost =
					PadlParserUtil.createGhost(
						aPadlModel,
						fullyQualifiedName.toCharArray());
			}
			return ghost;
		}
		else {
			// case of a ghost member
			// get or create a ghost based on the package name and the ghostName
			final String searchedGhostID =
				PadlParserUtil
					.renameWith$(fullyQualifiedName, ghostPackagePath);

			StringTokenizer tokenizer;

			//	int nbTokens = tokenizer.countTokens(); // number of entities in the
			// hierarchy=class>memberClass1>MemberClass2

			tokenizer = new StringTokenizer(searchedGhostID, "$");

			IPackage searchedPackage = null;

			IFirstClassEntity currentEntity = null;
			final String currentEntityID = tokenizer.nextToken();

			searchedPackage =
				PadlParserUtil.getPackage(ghostPackagePath, aPadlModel);

			if (searchedPackage != null) {
				currentEntity =
					aPadlModel.getTopLevelEntityFromID(currentEntityID
						.toCharArray());

				if (currentEntity == null) {
					currentEntity =
						PadlParserUtil.createGhost(
							aPadlModel,
							currentEntityID.toCharArray());
				}
			}
			else {
				currentEntity =
					PadlParserUtil.createGhost(
						aPadlModel,
						currentEntityID.toCharArray());
			}

			// create the member entities
			IFirstClassEntity currentMemberEntity;
			String currentMemberEntityID;
			String currentMemberEntityName;

			while (tokenizer.hasMoreTokens()) {
				currentMemberEntityName = tokenizer.nextToken();
				currentMemberEntityID =
					currentEntity.getDisplayID() + '$'
							+ currentMemberEntityName;

				currentMemberEntity =
					(IFirstClassEntity) currentEntity
						.getConstituentFromID(currentMemberEntityID
							.toCharArray());

				if (currentMemberEntity == null) {
					currentMemberEntity =
						aPadlModel.getFactory().createMemberGhost(
							currentMemberEntityID.toCharArray(),
							currentMemberEntityName.toCharArray());
					currentEntity
						.addConstituent((IConstituentOfEntity) currentMemberEntity);
				}
				currentEntity = currentMemberEntity;
			}
			// The last entity created or got in the padl model is which
			// is searched for
			return currentEntity;
		}
	}

	/**
	 * Create possibly recursively packages
	 * 
	 * @param aPackageName
	 * @param aCodeLevelModel
	 * @return
	 */
	public static IPackage getOrCreatePackage(
		final char[] aPackageName,
		final ICodeLevelModel aCodeLevelModel) {

		IPackage currentPackage = null;
		int startIndexInclusive = 0;
		do {
			int endIndexExclusive =
				ArrayUtils.indexOf(aPackageName, '.', startIndexInclusive);
			if (endIndexExclusive == -1) {
				endIndexExclusive = aPackageName.length;
			}
			final char[] tempName =
				ArrayUtils.subarray(
					aPackageName,
					startIndexInclusive,
					endIndexExclusive);
			if (currentPackage == null) {
				currentPackage =
					PadlParserUtil.createPackage(tempName, aCodeLevelModel);
			}
			else {
				currentPackage =
					PadlParserUtil.createPackage(
						tempName,
						currentPackage,
						aCodeLevelModel);
			}
			startIndexInclusive = endIndexExclusive + 1;
		}
		while (startIndexInclusive < aPackageName.length);

		return currentPackage;
	}

	/**
	 * return the package from its path
	 * 
	 * @param aPackagePath
	 * @param aModel
	 * @return
	 */
	public static IPackage getPackage(
		final String aPackagePath,
		final ICodeLevelModel aModel) {

		if (aPackagePath.length() == 0) {
			// default package
			return (IPackage) aModel
				.getConstituentFromID(Constants.DEFAULT_PACKAGE_ID);

		}

		final StringTokenizer tokenizer =
			new StringTokenizer(aPackagePath, ".");

		IPackage currentPackage =
			(IPackage) aModel.getConstituentFromID(tokenizer.nextToken());
		if (currentPackage != null) {

			while (tokenizer.hasMoreTokens()) {
				final IPackage packaje =
					(IPackage) currentPackage.getConstituentFromID(tokenizer
						.nextToken());
				if (packaje == null) {
					return packaje;
				}
				else {
					currentPackage = packaje;
				}
			}

		}
		return currentPackage;
	}

	/**
	 * return the name of a type
	 * 
	 * @param type
	 * @return
	 */
	public static String getTypeName(
		final ITypeBinding aTypeBinding,
		final boolean isField) {

		String typeName = null;
		ITypeBinding typeBinding = aTypeBinding;

		if (aTypeBinding.isArray()) {

			typeBinding = typeBinding.getElementType();

		}
		if (typeBinding.isParameterizedType()) {
			typeBinding = typeBinding.getErasure();
		}

		if (aTypeBinding.isPrimitive()) {
			typeName = aTypeBinding.getName();

		}
		else if (typeBinding.isFromSource() && !typeBinding.isTypeVariable()) {
			// previous condition - Fix for Eclipse JDT v3.4(
			// case of templates) (fixed)
			if (typeBinding.getPackage() != null) {
				typeName =
					PadlParserUtil.renameWith$(
						typeBinding.getQualifiedName(),
						typeBinding.getPackage().getName());
			}
			else {
				typeName = typeBinding.getQualifiedName();
			}
		}
		else {
			typeName = typeBinding.getQualifiedName();
			// here, it can be wrong if the resolving is not good, and it can
			// be with the current package name!!!
		}

		if (!isField) {
			for (int i = 0; i < aTypeBinding.getDimensions(); i++) {

				typeName = typeName.concat("[]");
			}
		}
		return typeName;
	}

	/**
	 * Rewrite the IDs of members by replacing . by $
	 * 
	 * @param entityQualifiedName
	 * @param packageName
	 * @return
	 */
	public static String renameWith$(
		final String entityQualifiedName,
		final String packageName) {

		// default package
		String partToRename = entityQualifiedName;

		final StringBuffer tmpNewName = new StringBuffer();

		if (entityQualifiedName.length() <= packageName.length()) {
			// which case?
			/*
			 * Output .getInstance() .normalOutput() .println(
			 * "PadlParserUtil in renameWith$ entityQualifiedName.length() <= packageName.length() "
			 * + entityQualifiedName + " " + packageName.length());
			 */
		}
		// not default package
		if (packageName.length() != 0
		// TODO: Fix for eclipse_12-15-2009
				&& entityQualifiedName.length() > packageName.length()) {

			partToRename =
				entityQualifiedName.substring(packageName.length() + 1);
			tmpNewName.append(packageName);
			tmpNewName.append('.');
		}
		// Replace . by $ in the string part to rename

		partToRename = partToRename.replace('.', '$');

		tmpNewName.append(partToRename);

		return tmpNewName.toString();
	}

	/**
	 * 
	 * @param anAbstractLevelModel
	 * @param anEntityName
	 * @param aPackageCreator
	 * @return
	 */

	public static IPackage searchForPackage(
		final IAbstractLevelModel anAbstractLevelModel,
		final char[] anEntityName,
		final PackageCreator aPackageCreator) {

		// Yann 2008/11/04: Packages can be ghost, too!
		// Now that I handle packages, I must also create
		// appropriate ghost packages...
		final char[] packageName =
			PadlParserUtil.extractPackageName(anEntityName);
		final StringTokenizer packageNameTokenizer =
			new StringTokenizer(String.valueOf(packageName), ".");
		IPackage enclosingPackage = null;

		if (!packageNameTokenizer.hasMoreTokens()) {
			enclosingPackage =
				aPackageCreator.create(PadlParserUtil.DEFAULT_PACKAGE_NAME);
		}

		while (packageNameTokenizer.hasMoreTokens()) {
			final String packagePartDisplayName =
				packageNameTokenizer.nextToken();
			final char[] packagePartName = packagePartDisplayName.toCharArray();
			if (enclosingPackage == null) {
				enclosingPackage =
					(IPackage) anAbstractLevelModel
						.getConstituentFromID(packagePartName);

				if (enclosingPackage == null) {
					enclosingPackage = aPackageCreator.create(packagePartName);
					anAbstractLevelModel.addConstituent(enclosingPackage);
				}

			}

			else {
				IPackage newEnclosingPackage =
					(IPackage) enclosingPackage
						.getConstituentFromID(packagePartName);

				if (newEnclosingPackage == null) {
					newEnclosingPackage =
						aPackageCreator.create(packagePartName);
					enclosingPackage.addConstituent(newEnclosingPackage);
				}
				enclosingPackage = newEnclosingPackage;
			}
		}
		return enclosingPackage;
	}
}
