/**
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright (C) 2007 Matthias Braeuer (braeuer.matthias@web.de). *
* All rights reserved. *
* *
* This work was done as a project at the Chair for Software Technology, *
* Dresden University Of Technology, Germany (http://st.inf.tu-dresden.de). *
* It is understood that any modification not identified as such is not *
* covered by the preceding statement. *
* *
* This work 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 work 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, you can view it online at *
* http://www.fsf.org/licensing/licenses/gpl.html. *
* *
* To submit a bug report, send a comment, or get the latest news on this *
* project, please visit the website: http://dresden-ocl.sourceforge.net. *
* For more information on OCL and related projects visit the OCL Portal: *
* http://st.inf.tu-dresden.de/ocl *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* $Id$
*/
package org.dresdenocl.essentialocl.types.util;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.dresdenocl.essentialocl.EssentialOclPlugin;
import org.dresdenocl.essentialocl.types.OclLibrary;
import org.dresdenocl.model.IModel;
import org.dresdenocl.model.ModelAccessException;
import org.dresdenocl.model.TypeNotFoundException;
import org.dresdenocl.pivotmodel.Type;
/**
* <p>
* An {@link ITypeResolver} helps in finding {@link Type}s. These can either be
* located in the {@link OclLibrary} or in an associated {@link IModel}.
* </p>
*
* @author Matthias Braeuer
*/
public class TypeResolver {
/** The {@link Logger} for this class. */
private static final Logger LOGGER =
EssentialOclPlugin.getLogger(TypeResolver.class);
/** The associated {@link OclLibrary}. */
private OclLibrary oclLibrary;
/** Cache for the predefined {@link Type}s from the OCL Standard library. */
private Map<String, Type> predefinedTypes;
/**
* <p>
* Creates a new default {@link TypeResolver}.
* </p>
*
* @param oclLibrary
* The associated {@link OclLibrary}, must not be <code>null</code>.
*/
public TypeResolver(OclLibrary oclLibrary) {
/*
* Should not happen in the default implementation, but clients may create
* own type resolvers.
*/
if (oclLibrary == null) {
throw new IllegalArgumentException(
"The reference to the associated OCL standard library must not be null."); //$NON-NLS-1$
}
// no else.
this.oclLibrary = oclLibrary;
}
/**
* <p>
* Looks up a {@link Type} in the OCL library or in the associated
* {@link IModel}.
* </p>
*
* @param pathName
* The path name of the {@link Type} to look for.
*
* @return A {@link Type} instance.
*
* @throws IllegalArgumentException
* If the given pathname is either <code>null</code> or empty.
* @throws ModelAccessException
* If something goes wrong when accessing the {@link IModel}.
* @throws TypeNotFoundException
* If a {@link Type} with the given path name cannot be found.
* @throws ModelBusException
* If a general configuration error occurs.
*/
public Type findType(List<String> pathName, IModel model)
throws TypeNotFoundException, ModelAccessException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("findType(pathName=" + pathName + ") - enter"); //$NON-NLS-1$ //$NON-NLS-2$
}
// no else.
Type type = null;
if (pathName == null || pathName.isEmpty()) {
throw new IllegalArgumentException(
"The path name must not be null or empty."); //$NON-NLS-1$
}
// no else.
/* Try to look up a primitive type. */
if (pathName.size() == 1) {
type = this.getPredefinedTypes().get(pathName.get(0));
}
// no else.
/* If no primitive type found, try to look in the oclLibrary. */
if (type == null) {
type = model.findType(pathName);
}
// no else.
if (type == null) {
throw new TypeNotFoundException("Unable to find type '" + pathName + "'."); //$NON-NLS-1$//$NON-NLS-2$
}
// no else.
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("findType() - exit - return value=" + type); //$NON-NLS-1$
}
// no else.
return type;
}
/**
* <p>
* Helper method to initialize the cache with the primitive types.
* </p>
*/
protected void initializePredefinedTypes(OclLibrary oclLibrary) {
this.predefinedTypes.put(oclLibrary.getOclAny().getName(), oclLibrary
.getOclAny());
this.predefinedTypes.put(oclLibrary.getOclType().getName(), oclLibrary
.getOclType());
this.predefinedTypes.put(oclLibrary.getOclVoid().getName(), oclLibrary
.getOclVoid());
this.predefinedTypes.put(oclLibrary.getOclInvalid().getName(), oclLibrary
.getOclInvalid());
this.predefinedTypes.put(oclLibrary.getOclBoolean().getName(), oclLibrary
.getOclBoolean());
this.predefinedTypes.put(oclLibrary.getOclInteger().getName(), oclLibrary
.getOclInteger());
this.predefinedTypes.put(oclLibrary.getOclReal().getName(), oclLibrary
.getOclReal());
this.predefinedTypes.put(oclLibrary.getOclString().getName(), oclLibrary
.getOclString());
this.predefinedTypes.put(oclLibrary.getOclCollection().getName(),
oclLibrary.getOclCollection());
this.predefinedTypes.put(oclLibrary.getOclSequence().getName(), oclLibrary
.getOclSequence());
this.predefinedTypes.put(oclLibrary.getOclBag().getName(), oclLibrary
.getOclBag());
this.predefinedTypes.put(oclLibrary.getOclSet().getName(), oclLibrary
.getOclSet());
this.predefinedTypes.put(oclLibrary.getOclOrderedSet().getName(),
oclLibrary.getOclOrderedSet());
}
/**
* <p>
* A helper method to lazily get the OCL standard {@link Type}s.
* </p>
*/
private Map<String, Type> getPredefinedTypes() {
if (this.predefinedTypes == null) {
/* Instantiate the map for the primitive types and initialize it. */
this.predefinedTypes = new HashMap<String, Type>();
this.initializePredefinedTypes(oclLibrary);
}
return this.predefinedTypes;
}
}