//Source file: H:\\temp\\generated\\modTransf\\model\\jmi\\JmiModelHelper.java
package modTransf.model.jmi;
import modTransf.model.ModelHelperBase;
import modTransf.model.ModelHelper;
import modTransf.model.ModelException;
import modTransf.model.NotFoundException;
import modTransf.model.factory.ModelFactory;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import javax.jmi.reflect.RefPackage;
import javax.jmi.reflect.RefObject;
import javax.jmi.reflect.RefBaseObject;
import javax.jmi.reflect.RefClass;
import javax.jmi.reflect.RefAssociation;
import javax.jmi.reflect.RefEnum;
import javax.jmi.reflect.RefStruct;
import javax.jmi.reflect.JmiException;
import javax.jmi.reflect.InvalidNameException;
import org.apache.commons.beanutils.PropertyUtils;
import java.lang.reflect.Method;
import javax.jmi.model.EnumerationType;
public class JmiModelHelper extends ModelHelperBase implements ModelHelper
{
public static final String[] EMPTY_STRING_ARRAY = new String[]{};
/** The outermost RefPackage containing the current model */
protected RefPackage outermostRefPackage;
/** The name of the outermost RefPackage containing the current model */
protected String outermostRefPackageName;
/**
* Constructor.
* @param factory ModelFactory
* @param refPackage RefPackage
*/
public JmiModelHelper(RefPackage refPackage)
{
super( (Object)refPackage);
outermostRefPackage = refPackage;
}
/**
* Constructor.
* @param factory ModelFactory
* @param refPackage RefPackage
*/
public JmiModelHelper(Object nativeModel)
{
super(nativeModel);
outermostRefPackage = (RefPackage)nativeModel;
}
/**
* @param object
* @param name
* @param args
* @return Object
* @throws IllegalArgumentException
* @throws IllegalAccessException
* @throws InvocationTargetException
*/
public Object invokeMethod(Object object, String name, Object[] args)
throws ModelException
{
throw new UnsupportedOperationException("Not yet implemented.");
}
/**
* @param conceptType
* @return java.util.Collection
*/
public Collection getAllOfType(String conceptType)
{
return getRefClassByConceptName(conceptType).refAllOfType();
}
/**
* @param conceptType
* @return java.util.Collection
*/
public Collection getAllOfClass(String conceptType)
{
return getRefClassByConceptName(conceptType).refAllOfClass();
}
/**
* Set the property.
* Take into account Enumeration properties.
* Try to set the property as a regular property. If IllegalArgumentException
* is raise, catch it and check if this is an enumeration type.
* @todo Find another way to detect enum and struct, in order to avoid the
* error msg.
* @param bean
* @param name
* @param value
* @throws modTransf.model.ModelException
* @throws java.lang.IllegalAccessException
* @throws java.lang.reflect.InvocationTargetException
* @throws java.lang.NoSuchMethodException
*/
public void setProperty(Object bean, String name, Object value)
throws ModelException
{
try
{
PropertyUtils.setProperty(bean, name, value);
}
catch(NoSuchMethodException ex)
{
throw new ModelException(ex);
}
catch(java.lang.IllegalArgumentException ex)
{ // Check if this is an enumeration
try {
setEnumProperty(bean, name, value.toString());
}
catch(ModelException ex2 )
{ // Throw surrounding exception
//System.out.println("Fail to set '"+ bean.getClass().getName() +"." +name + "'='"+value+"' as enum:" + ex2);
//ex2.printStackTrace();
throw new ModelException(ex);
}
catch(InvalidNameException ex2 )
{ // Throw this exception
//System.out.println("Fail to set '"+ bean.getClass().getName() +"." +name + "'='"+value+"' as enum:" + ex2);
//ex2.printStackTrace();
//throw new Error(ex2);
throw new ModelException(ex2);
}
}
catch(InvocationTargetException ex)
{
throw new ModelException(ex);
}
catch(IllegalAccessException ex)
{
throw new ModelException(ex);
}
}
/**
* Is this ModelUtil owner of the specified object ?
* If a model is owner of an object, it means that the methods of the
* model can called on the object.
* This method return true if this ModelUtil implementation can manage the
* specified object (method of this class can be called on the object).
* @param object The object to test.
* @return true if the associated model is owner of the object, false otherwise.
*/
public boolean isOwnerOf(Object object)
{
if( (object instanceof RefBaseObject))
{
return( (RefBaseObject)object).refOutermostPackage()==outermostRefPackage;
}
else if(object instanceof RefStruct)
{
return getOutermostRefPackageName().equals( ( (RefStruct)object).refTypeName().get(0));
}
else if(object instanceof RefEnum)
{
return getOutermostRefPackageName().equals( ( (RefEnum)object).refTypeName().get(0));
}
else
{
return false;
}
}
/**
* Is the object instance of the specified type ?
* @param object
* @param instanceName
* @return boolean
*/
public boolean isInstanceOf(Object object, String instanceName)
{
//System.out.println("isInstanceOf(Object=" + object.getClass().getName() + ")" );
if(object instanceof RefObject)
{
RefClass conceptClass = getRefClassByConceptName(instanceName);
return conceptClass.refAllOfType().contains(object);
//return ((RefObject)object).refIsInstanceOf( conceptClass.refMetaObject(), true );
//return ((RefObject)object).refClass() == conceptClass;
}
else if(object instanceof RefStruct)
{
// TODO: Check also for subclasses !!
//System.out.println( "check " + ((RefStruct)object).refTypeName() + ".isIntanceof("
// + instanceName + ")" );
return pathnameToList(instanceName).equals( ( (RefStruct)object).refTypeName());
}
else if(object instanceof RefAssociation)
{
throw new UnsupportedOperationException(
"JMI Helper Method 'isInstanceOf()' not yet implemented for RefAssociation (object.type="
+object.getClass().getName()+").");
}
else if(object instanceof RefEnum)
{
return pathnameToList(instanceName).equals( ( (RefEnum)object).refTypeName());
}
else
{
return false;
}
}
/**
* Is the object of the specified class ?
* @param object
* @param instanceName
* @return boolean
*/
public boolean isOfClass(Object modelElement, String instanceName)
{
//
RefClass conceptClass = getRefClassByConceptName(instanceName);
//System.out.println("isInstanceOf(Object=" + object.getClass().getName() + ")" );
if(modelElement instanceof RefObject)
{
//return conceptClass.refAllOfClass().contains(modelElement);
//return ((RefObject)object).refIsInstanceOf( conceptClass.refMetaObject(), true );
return( (RefObject)modelElement).refClass()==conceptClass;
}
else if(modelElement instanceof RefStruct)
{
return pathnameToList(instanceName).equals( ( (RefStruct)modelElement).refTypeName());
}
else if(modelElement instanceof RefAssociation)
{
throw new UnsupportedOperationException(
"JMI Helper Method 'isOfClass()' not yet implemented for RefAssociation (object.type="
+modelElement.getClass().getName()+").");
}
else if(modelElement instanceof RefEnum)
{
return pathnameToList(instanceName).equals( ( (RefEnum)modelElement).refTypeName());
}
else
{
return false;
}
}
/**
* Create an instance of specified model element.
* @param instanceName Name of the instance to create.
* @return
* @throws InstantiationException If the model element can't be created.
*/
public Object createInstance(String conceptName)
throws InstantiationException
{
//System.out.println( "Create Instance " + conceptName );
try
{
return getRefClassByConceptName(conceptName).refCreateInstance(Collections.EMPTY_LIST);
}
catch(JmiException ex)
{ // This exception can come from getRefClassByConceptName or refCreateInstance
throw new InstantiationException("Can't instanciate '"+conceptName
+"' : "+ex.getClass().getName()
+ (ex.getMessage()!=null?" : "+ex.getMessage():"")
+".");
}
}
/**
* @param instance
*/
public void deleteInstance(Object instance)
{
throw new UnsupportedOperationException("Not yet implemented.");
}
/**
* getModelRoots
*
* @return Collection
*/
public Collection getModelRoots()
{
return getRoots(getOutermostRefPackage());
}
/**
* Get the JMI RefPackage (outermost extent) object.
* @return RefPackage The JMI RefPackage outermost extent.
*/
public RefPackage getOutermostRefPackage()
{
// For debug. To be removed
// if( outermostRefPackage == null )
// throw new IllegalArgumentException("outermostRefPackage is null !!!" );
return outermostRefPackage;
}
/**
* Get the JMI RefPackage (outermost extent) object.
* @return RefPackage The JMI RefPackage outermost extent.
*/
protected String getOutermostRefPackageName()
{
if(outermostRefPackageName!=null)
{
return outermostRefPackageName;
}
outermostRefPackageName = (String)outermostRefPackage.refMetaObject().refGetValue("name");
return outermostRefPackageName;
}
/**
* Get the JMI RefPackage (outermost extent) object.
* @return RefPackage The JMI RefPackage outermost extent.
*/
public void setOutermostRefPackage(RefPackage outermostRefPackage)
{
this.outermostRefPackage = outermostRefPackage;
}
/**
* Convert a pathname to a list of name. A pathname is made of names
* separated with "."
* @todo add "::" as separator.
* @param pathname String
* @return List
*/
protected List pathnameToList(String pathname)
{
return Arrays.asList(pathname.split("\\."));
}
/**
* Get the refClass by its concept name.
* @param conceptName
* @return
* @throws InvalidNameException
*/
protected RefClass getRefClassByConceptName(String conceptName)
throws InvalidNameException
{
RefPackage extent = getOutermostRefPackage();
String[] names = conceptName.split("\\.");
int i = 0;
try
{
for(i = 0; i<names.length-1; i++)
{
extent = (RefPackage)extent.refPackage(names[i]);
} // end loop
return extent.refClass(names[i]);
}
catch(IndexOutOfBoundsException ex)
{
throw new InvalidNameException("Bad concept name '"+conceptName
+"': Can't split name in subnames.");
}
catch(JmiException ex)
{
if(i>0)
{
System.out.println("Can't create class '"+conceptName+"', name '"
+names[i]
+"' not found in '"+names[i-1]+"'.");
throw new InvalidNameException("Bad concept name '"+conceptName
+"': name '"+names[i]
+"' not found in '"+names[i-1]+"'.");
}
else
{
System.out.println("Can't create class '"+conceptName+"', name '"
+names[i]
+"' not found in outermost package.");
throw new InvalidNameException("Bad concept name '"+conceptName
+"': name '"+names[i]
+"' not found in outermost package.");
}
}
catch(RuntimeException ex)
{
//System.out.println( "error while getting concept class '" + conceptName + "',. i=" + i );
throw new InvalidNameException("Bad concept name '"+conceptName
+"'");
}
}
/**
* Get the refPackage by its concept name. The concept name is a "."
* separated name. Each name denote a package name, except the last name
* which is not use.
* @param conceptName
* @return
* @throws InvalidNameException
*/
protected RefPackage getRefPackageByConceptName(String conceptName)
throws InvalidNameException
{
RefPackage extent = getOutermostRefPackage();
String[] names = conceptName.split("\\.");
int i = 0;
try
{
for(i = 0; i<names.length-1; i++)
{
extent = (RefPackage)extent.refPackage(names[i]);
} // end loop
return extent;
}
catch(IndexOutOfBoundsException ex)
{
throw new InvalidNameException("Bad concept name '"+conceptName
+"': Can't split name in subnames.");
}
catch(JmiException ex)
{
if(i>0)
{
System.out.println("Can't create class '"+conceptName+"', name '"
+names[i]
+"' not found in '"+names[i-1]+"'.");
throw new InvalidNameException("Bad concept name '"+conceptName
+"': name '"+names[i]
+"' not found in '"+names[i-1]+"'.");
}
else
{
System.out.println("Can't create class '"+conceptName+"', name '"
+names[i]
+"' not found in outermost package.");
throw new InvalidNameException("Bad concept name '"+conceptName
+"': name '"+names[i]
+"' not found in outermost package.");
}
}
catch(RuntimeException ex)
{
//System.out.println( "error while getting concept class '" + conceptName + "',. i=" + i );
throw new InvalidNameException("Bad concept name '"+conceptName
+"'");
}
}
/**
* Get the refAssocaition by its association name. The concept name is a "."
* separated name. Each name denote a package name, except the last name
* which is not use.
* @param conceptName
* @return
* @throws InvalidNameException
*/
protected RefAssociation getRefAssociationByConceptName(String conceptName)
throws InvalidNameException
{
RefPackage extent = getOutermostRefPackage();
String[] names = conceptName.split("\\.");
int i = 0;
try
{
for(i = 0; i<names.length-1; i++)
{
extent = (RefPackage)extent.refPackage(names[i]);
} // end loop
return extent.refAssociation(names[i]);
}
catch(IndexOutOfBoundsException ex)
{
throw new InvalidNameException("Bad concept name '"+conceptName
+"': Can't split name in subnames.");
}
catch(JmiException ex)
{
if(i>0)
{
System.out.println("Can't find class '"+conceptName+"', name '"
+names[i]
+"' not found in '"+names[i-1]+"'. (was: "
+ex.getMessage()+").");
ex.printStackTrace();
throw new InvalidNameException("Bad concept name '"+conceptName
+"': name '"+names[i]
+"' not found in '"+names[i-1]+"'.");
}
else
{
System.out.println("Can't find class '"+conceptName+"', name '"
+names[i]
+"' not found in outermost package.(was: "
+ex.getMessage()+").");
throw new InvalidNameException("Bad concept name '"+conceptName
+"': name '"+names[i]
+"' not found in outermost package.");
}
}
catch(RuntimeException ex)
{
//System.out.println( "error while getting concept class '" + conceptName + "',. i=" + i );
throw new InvalidNameException("Bad concept name '"+conceptName
+"'");
}
}
/**
* Get all roots from model.
* @param elementName
* @return
*/
protected Collection getRoots(RefPackage extent)
{
//System.out.println("Get roots from " + extent.refMetaObject().refGetValue("name") );
Collection roots = new ArrayList();
addRoots(roots, extent);
System.out.println(" Found "+roots.size()+" roots.");
return roots;
}
/**
* Add roots contained in the package
* @param roots
* @param extent
*/
protected void addRoots(Collection roots, RefPackage extent)
{
//System.out.println(" check package'" + extent + "'.");
// First, walk all containers
Collection containers = extent.refAllClasses();
Iterator iter = containers.iterator();
while(iter.hasNext())
{
addRoots(roots, (RefClass)iter.next());
} // end loop
// Now, , walk all nested packages
Collection packages = extent.refAllPackages();
iter = packages.iterator();
while(iter.hasNext())
{
addRoots(roots, (RefPackage)iter.next());
} // end loop
}
/**
* Add roots contained in the package
* @param roots
* @param extent
*/
protected void addRoots(Collection roots, RefClass container)
{
//System.out.println(" check class'" + container + "'.");
// Get the object owned by the container
Collection objects = container.refAllOfType();
// Get only objects wich aren't component of another object
Iterator iter = objects.iterator();
while(iter.hasNext())
{
RefObject object = (RefObject)iter.next();
//System.out.println(" check '" + object + "'.");
if(object.refImmediateComposite()==null)
{
//System.out.println(" ---> added " + object.refMetaObject().refGetValue("name") );
// Add if not already found
if(!roots.contains(object))
{
roots.add(object);
}
}
} // end loop
}
/**
* Get the type of the specified property on the specified object.
* Throw NotFoundException if the property doesn't exist on the bean.
* @param bean Object
* @param propertyName String
* @return List
*/
protected String[] getPropertyType( Object bean, String propertyName )
throws NotFoundException
{
RefObject propDesc = getPropertyMetaClass(bean, propertyName);
return getFullTypeFromMetaClass( propDesc );
}
/**
* Get the Enumerationtype of the specified property on the specified object.
* Throw NotFoundException if the property doesn't exist on the bean.
*
* @param bean Object
* @param propertyName String
* @return EnumType or null if this is not an enumeration
* @throws NotFoundException if the property doesn't exist on the bean.
*/
protected String[] getEnumType( Object bean, String propertyName )
throws NotFoundException
{
RefObject propDesc = getPropertyMetaClass(bean, propertyName);
if(! (propDesc instanceof EnumerationType) )
return null;
return getFullTypeFromMetaClass( propDesc );
}
/**
* Get the metaObject for the specified property of the specified bean.
* @param bean Object
* @param propertyName String
* @throws NotFoundException
* @return RefObject
*/
protected RefObject getPropertyMetaClass( Object bean, String propertyName )
throws NotFoundException
{
if( propertyName == null )
throw new IllegalArgumentException("propertyName should be set.");
RefObject ref = (RefObject)bean;
RefObject descriptor = ref.refMetaObject();
// Lookup the property descriptor.
// Lookup the attribute with the requested name,
// return the type pointed by the attribute.
Iterator propertyIter = ((Collection)descriptor.refGetValue("contents")).iterator();
while(propertyIter.hasNext())
{
RefObject attribute = (RefObject)propertyIter.next();
if( propertyName.equals( attribute.refGetValue( "name" ) ) )
{
return (RefObject)attribute.refGetValue("type");
}
}
throw new NotFoundException("No property '" + propertyName + "' in '" + descriptor.getClass().getName() + "'.");
}
/**
* Get the full type associated to the metaclass.
* The outermost package name is not part of the returned names.
* @param metaclass RefObject
* @return List
*/
protected String[] getFullTypeFromMetaClass( RefObject metaclass )
{
List res = new ArrayList();
res.add( metaclass.refGetValue("name") );
RefObject parent = (RefObject)metaclass.refGetValue("container" );
//System.out.println("metaclass.refOutermostPackage()='" + metaclass.refOutermostPackage().getClass().getName() + "'." );
while( parent !=null )
{
//System.out.println("metaclass.refOutermostPackage()='" + metaclass.refOutermostPackage().getClass().getName() + "'." );
//System.out.println("parent='" + parent.getClass().getName() + "'." );
String name = (String)parent.refGetValue("name");
// Don't put the last one
parent = (RefObject)parent.refGetValue("container" );
if( parent == null )
break;
//System.out.println("add '" + name + "'." );
res.add( name );
}
// Remove the last one: this is the mainExtent.
// if( res.size() > 1 )
// res.remove(res.size()-1);
// Revert list
Collections.reverse(res);
return (String[])res.toArray(EMPTY_STRING_ARRAY);
}
/**
* Check if the specified property denote an enumeration.
*
* @param bean Object
* @param property String
* @param value String
* @throws NotFoundException
* @throws javax.jmi.reflect.InvalidNameException If the literal value doesn't match the enum.
*/
protected void setEnumProperty( Object bean, String property, String value )
throws NotFoundException, InvalidNameException
{
// Skip null and empty string: they can't be converted !!
if(value==null || value.length() == 0 )
return;
// Get the enum type
String[] proptype = getEnumType( bean, property);
if( proptype == null )
throw new NotFoundException("Not an enumeration.");
String enumTypeName = (String)proptype[proptype.length-1];
RefPackage pack = getRefPackageByType( proptype );
RefEnum enumValue = null;
// next one throw InvalidNameException
enumValue = pack.refGetEnum(enumTypeName, value);
RefObject obj = (RefObject)bean;
obj.refSetValue( property, enumValue);
}
/**
* getRefPackageByType
*
* @param proptype List
* @return RefPackage
*/
protected RefPackage getRefPackageByType(String[] names)
{
RefPackage extent = getOutermostRefPackage();
int i=0;
try
{
for(i = 0; i<names.length-1; i++)
{
extent = (RefPackage)extent.refPackage(names[i]);
}
}
catch(InvalidNameException ex)
{
if(i>0)
{
throw new InvalidNameException("Can't found package '" +names[i]
+"' in '"+names[i-1]+"'.");
}
else
{
System.out.println("Can't found package '" +names[i]
+"' in outermost package.");
throw new InvalidNameException("Can't found package '" +names[i]
+"' in outermost package.");
}
}
return extent;
}
}