/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.foundation.dm; import java.io.File; import java.lang.reflect.TypeVariable; import java.text.Collator; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import java.util.Vector; import java.util.logging.Logger; import org.openflexo.foundation.FlexoModelObject; import org.openflexo.foundation.TemporaryFlexoModelObject; import org.openflexo.foundation.dm.DMSet.PackageReference.ClassReference; import org.openflexo.foundation.rm.FlexoProject; import org.openflexo.foundation.utils.FlexoProgress; import org.openflexo.localization.FlexoLocalization; public class DMSet extends TemporaryFlexoModelObject { private static final Logger logger = Logger.getLogger(DMSet.class.getPackage().getName()); private File _jarFile; protected Hashtable<String, PackageReference> _packages; private boolean _importGetOnlyProperties = false; private boolean _importMethods = false; protected Vector<FlexoModelObject> _selectedObjects; protected String _unlocalizedName; public FlexoProject _project; private ExternalRepository _externalRepository; protected DMSet(FlexoProject project) { super(); _project = project; _selectedObjects = new Vector<FlexoModelObject>(); _packages = new Hashtable<String, PackageReference>(); _justResolvedEntities = new Hashtable<ClassReference, DMEntity>(); } public DMSet(FlexoProject project, File jarFile, boolean parseMethodsAndProperties, FlexoProgress progress) { this(project); _jarFile = jarFile; Iterator<Class<?>> i = ExternalRepository.getContainedClasses(jarFile, null, project, progress); while (i.hasNext()) { Class<?> aClass = i.next(); String packageName = packageNameForClass(aClass); if (_packages.get(packageName) == null) { _packages.put(packageName, new PackageReference(packageName)); } _packages.get(packageName).add(aClass, parseMethodsAndProperties, (LoadableDMEntity) null); } } public DMSet(FlexoProject project, ExternalRepository externalRepository, boolean parseMethodsAndProperties, FlexoProgress progress) { this(project); _externalRepository = externalRepository; for (Class<?> aClass : externalRepository.getJarLoader().getContainedClasses().values()) { String packageName = packageNameForClass(aClass); if (_packages.get(packageName) == null) { _packages.put(packageName, new PackageReference(packageName)); } _packages.get(packageName).add(aClass, parseMethodsAndProperties, externalRepository); } for (DMEntity e : externalRepository.getEntities().values()) { LoadableDMEntity entity = (LoadableDMEntity) e; if (entity.getType() != null && entity.getJavaType() != null) { ClassReference aClassReference = getClassReference(entity.getJavaType()); addToSelectedObjects(aClassReference.getPackageReference()); addToSelectedObjects(aClassReference); } else { logger.warning("Could not find class for " + entity); } } addToSelectedObjects(this); } public DMSet(FlexoProject project, String unlocalizedName, LoadableDMEntity entity, boolean parseMethodsAndProperties, FlexoProgress progress) { this(project, unlocalizedName, makeUniqueElementVector(entity), parseMethodsAndProperties, progress); } private static Vector<LoadableDMEntity> makeUniqueElementVector(LoadableDMEntity e) { Vector<LoadableDMEntity> returned = new Vector<LoadableDMEntity>(); returned.add(e); return returned; } public DMSet(FlexoProject project, String unlocalizedName, List<LoadableDMEntity> entities, boolean parseMethodsAndProperties, FlexoProgress progress) { this(project); _unlocalizedName = unlocalizedName; if (progress != null) { progress.setProgress(FlexoLocalization.localizedForKey("analysing_classes")); progress.resetSecondaryProgress(entities.size()); } for (LoadableDMEntity entity : entities) { Class<?> aClass = entity.retrieveJavaType(); if (aClass != null) { if (progress != null) { progress.setSecondaryProgress(FlexoLocalization.localizedForKey("analysing") + " " + aClass.getName()); } String packageName = packageNameForClass(aClass); if (_packages.get(packageName) == null) { PackageReference newPackageReference = new PackageReference(packageName); _packages.put(packageName, newPackageReference); addToSelectedObjects(newPackageReference); } ClassReference aClassReference = _packages.get(packageName).add(aClass, parseMethodsAndProperties, entity); addToSelectedObjects(aClassReference); } else { logger.warning("Could not find class for " + entity); } } addToSelectedObjects(this); } public Vector<FlexoModelObject> getSelectedObjects() { return _selectedObjects; } public void setSelectedObjects(Vector<? extends FlexoModelObject> someSelectedObjects) { _selectedObjects.clear(); _selectedObjects.addAll(someSelectedObjects); } public void addToSelectedObjects(FlexoModelObject obj) { if (!_selectedObjects.contains(obj)) { _selectedObjects.add(obj); } } public void removeFromSelectedObjects(FlexoModelObject obj) { if (_selectedObjects.contains(obj)) { _selectedObjects.remove(obj); } } protected static String packageNameForClass(Class<?> aClass) { return packageNameForClassName(aClass.getName()); } protected static String packageNameForClassName(String className) { String packageName = null; StringTokenizer st = new StringTokenizer(className, "."); while (st.hasMoreTokens()) { String nextToken = st.nextToken(); if (st.hasMoreTokens()) { if (packageName == null) { packageName = nextToken; } else { packageName += "." + nextToken; } } } if (packageName == null) { return DMPackage.DEFAULT_PACKAGE_NAME; } return packageName; } protected static String classNameForClass(Class<?> aClass) { String className = null; StringTokenizer st = new StringTokenizer(aClass.getName(), "."); while (st.hasMoreTokens()) { String nextToken = st.nextToken(); if (!st.hasMoreTokens()) { className = nextToken; } } if (aClass.getTypeParameters().length > 0) { className += "<"; boolean isFirst = true; for (TypeVariable<?> tv : aClass.getTypeParameters()) { className += (isFirst ? "" : ",") + tv.getName(); isFirst = false; } className += ">"; } return className; } @Override public String getName() { if (_jarFile != null) { return _jarFile.getName(); } if (_externalRepository != null) { return _externalRepository.getName(); } if (_unlocalizedName != null) { return FlexoLocalization.localizedForKey(_unlocalizedName); } return FlexoLocalization.localizedForKey("unnamed_set"); } @Override public boolean equals(Object anObject) { if (anObject instanceof DMSet) { return ((DMSet) anObject).getName().equals(getName()); } return super.equals(anObject); } @Override public int hashCode() { return getName() == null ? 0 : getName().hashCode(); } public Enumeration<PackageReference> getPackages() { Vector<PackageReference> orderedPackages = new Vector<PackageReference>(_packages.values()); Collections.sort(orderedPackages, new Comparator<PackageReference>() { @Override public int compare(PackageReference o1, PackageReference o2) { return Collator.getInstance().compare(o1.getName(), o2.getName()); } }); return orderedPackages.elements(); } public class PackageReference extends TemporaryFlexoModelObject { protected String _packageName; protected Vector<ClassReference> _classes; public PackageReference(String packageName) { super(); _packageName = packageName; _classes = new Vector<ClassReference>(); } public ClassReference getClassReference(String className) { for (ClassReference next : _classes) { if (next.getName().equals(className)) { return next; } if (next.getName().equals(_packageName + "." + className)) { return next; } if ((_packageName + "." + next.getName()).equals(className)) { return next; } } return null; } public Enumeration<ClassReference> getClassesEnumeration() { Collections.sort(_classes, new Comparator<ClassReference>() { @Override public int compare(ClassReference o1, ClassReference o2) { return Collator.getInstance().compare(o1.getName(), o2.getName()); } }); return _classes.elements(); } @Override public String getName() { return _packageName; } public String getLocalizedName() { if (_packageName.equals(DMPackage.DEFAULT_PACKAGE_NAME)) { return FlexoLocalization.localizedForKey(DMPackage.DEFAULT_PACKAGE_NAME); } return _packageName; } @Override public String toString() { return "PackageReference:" + getName(); } @Override public boolean equals(Object anObject) { if (anObject instanceof PackageReference) { return ((PackageReference) anObject).getName().equals(getName()); } return super.equals(anObject); } @Override public int hashCode() { return getName() == null ? 0 : getName().hashCode(); } public ClassReference add(Class<?> aClass, boolean parseMethodsAndProperties, DMRepository repository) { ClassReference aClassReference = new ClassReference(aClass, parseMethodsAndProperties, repository); _classes.add(aClassReference); return aClassReference; } public ClassReference add(Class<?> aClass, boolean parseMethodsAndProperties, LoadableDMEntity entity) { ClassReference aClassReference = new ClassReference(aClass, parseMethodsAndProperties, entity); _classes.add(aClassReference); return aClassReference; } public class ClassReference extends TemporaryFlexoModelObject { private String _className; protected Vector<PropertyReference> _properties; protected Vector<MethodReference> _methods; private Class<?> _referencedClass; public ClassReference(Class<?> aClass, boolean parseMethodsAndProperties, LoadableDMEntity entity) { this(aClass, parseMethodsAndProperties, entity, entity != null ? entity.getRepository() : null); } public ClassReference(Class<?> aClass, boolean parseMethodsAndProperties, DMRepository repository) { this(aClass, parseMethodsAndProperties, null, repository); } private ClassReference(Class<?> aClass, boolean parseMethodsAndProperties, LoadableDMEntity entity, DMRepository repository) { this(classNameForClass(aClass)); _referencedClass = aClass; if (parseMethodsAndProperties && repository != null) { List<String> excludedSignatures = new ArrayList<String>(); List<DMProperty> properties = LoadableDMEntity.searchForProperties(aClass, _project.getDataModel(), repository, true,/*true,*/ false, excludedSignatures); for (DMProperty next : properties) { PropertyReference propertyReference = new PropertyReference(next.getName(), next.getIsSettable(), next.getCardinality(), // (next.getType()!=null?next.getType().getName():next.getUnresolvedTypeName()+"<unloaded>")); next.getType().getStringRepresentation(), next.getType().getSimplifiedStringRepresentation() + (next.getType().isResolved() ? "" : "<unloaded>")); _properties.add(propertyReference); if (entity != null && entity.getDMProperty(next.getName()) != null) { addToSelectedObjects(propertyReference); } } List<DMMethod> methods = LoadableDMEntity.searchForMethods(aClass, _project.getDataModel(), repository,/*true,true,*/ false, excludedSignatures); for (DMMethod next : methods) { MethodReference methodReference = new MethodReference(next.getSignature(), next.getSimplifiedSignature(), // (next.getReturnType()!=null?next.getReturnType().getName():next.getUnresolvedReturnType().getValue()+"<unloaded>")); next.getReturnType().getStringRepresentation(), next.getReturnType().getSimplifiedStringRepresentation() + (next.getType().isResolved() ? "" : "<unloaded>")); _methods.add(methodReference); if (entity != null && entity.getDeclaredMethod(next.getSignature()) != null) { addToSelectedObjects(methodReference); } } } } public ClassReference(String className) { super(); _className = className; _properties = new Vector<PropertyReference>(); _methods = new Vector<MethodReference>(); } public Class<?> getReferencedClass() { return _referencedClass; } @Override public String getName() { return _className; } public String getPackageName() { return _packageName; } public PackageReference getPackageReference() { return PackageReference.this; } @Override public String toString() { return "ClassReference:" + getName(); } @Override public boolean equals(Object anObject) { if (anObject instanceof ClassReference) { return ((ClassReference) anObject).getName().equals(getName()); } return super.equals(anObject); } @Override public int hashCode() { return getName() == null ? 0 : getName().hashCode(); } public boolean isSelected() { return _selectedObjects.contains(ClassReference.this); } public Enumeration<MethodReference> getMethodsEnumeration() { Collections.sort(_methods, new Comparator<MethodReference>() { @Override public int compare(MethodReference o1, MethodReference o2) { return Collator.getInstance().compare(o1.getSignature(), o2.getSignature()); } }); return _methods.elements(); } public Enumeration<PropertyReference> getPropertiesEnumeration() { Collections.sort(_properties, new Comparator<PropertyReference>() { @Override public int compare(PropertyReference o1, PropertyReference o2) { return Collator.getInstance().compare(o1.getName(), o2.getName()); } }); return _properties.elements(); } public Vector<MethodReference> getMethods() { return _methods; } public Vector<PropertyReference> getProperties() { return _properties; } public class PropertyReference extends TemporaryFlexoModelObject { private String _propertyName; private String _simplifiedTypeName; private boolean _isSettable; private DMCardinality _cardinality; private String _typeName; private boolean _newlyDiscovered = false; private boolean _isToBeIgnored = false; public PropertyReference(String propertyName, boolean isSettable, DMCardinality cardinality, String typeName, String simplifiedTypeName) { super(); _propertyName = propertyName; _simplifiedTypeName = simplifiedTypeName; _isSettable = isSettable; _cardinality = cardinality; _typeName = typeName; } @Override public String getName() { return _propertyName; } @Override public String toString() { return "PropertyReference:" + getName(); } @Override public boolean equals(Object anObject) { if (anObject instanceof PropertyReference) { return ((PropertyReference) anObject).getName().equals(getName()); } return super.equals(anObject); } @Override public int hashCode() { return getName().hashCode(); } public boolean isSelected() { return _selectedObjects.contains(PropertyReference.this); } public DMCardinality getCardinality() { return _cardinality; } public boolean isSettable() { return _isSettable; } public String getTypeName() { return _typeName; } public String getSimplifiedTypeName() { return _simplifiedTypeName; } private boolean _isResolvable = true; public boolean isResolvable() { return _isResolvable; } public void setResolvable(boolean isResolvable) { _isResolvable = isResolvable; } public boolean isNewlyDiscovered() { return _newlyDiscovered; } public void setNewlyDiscovered(boolean newlyDiscovered) { _newlyDiscovered = newlyDiscovered; } public boolean isToBeIgnored() { return _isToBeIgnored; } public void setToBeIgnored(boolean isToBeIgnored) { _isToBeIgnored = isToBeIgnored; } } public class MethodReference extends TemporaryFlexoModelObject { private String _signature; private String _returnTypeName; private String _simplifiedSignature; private String _simplifiedReturnTypeName; private boolean _newlyDiscovered = false; private boolean _isToBeIgnored = false; public MethodReference(String signature, String simplifiedSignature, String returnTypeName, String simplifiedReturnTypeName) { super(); _signature = signature; _returnTypeName = returnTypeName; _simplifiedSignature = simplifiedSignature; _simplifiedReturnTypeName = simplifiedReturnTypeName; } public String getSignature() { return _signature; } public String getSimplifiedSignature() { return _simplifiedSignature; } @Override public String toString() { return "MethodReference:" + getName(); } @Override public boolean equals(Object anObject) { if (anObject instanceof MethodReference) { return ((MethodReference) anObject).getSignature().equals(getSignature()); } return super.equals(anObject); } @Override public int hashCode() { return getSignature().hashCode(); } public boolean isSelected() { return _selectedObjects.contains(MethodReference.this); } public String getReturnTypeName() { return _returnTypeName; } public String getSimplifiedReturnTypeName() { return _simplifiedReturnTypeName; } private boolean _isResolvable = true; public boolean isResolvable() { return _isResolvable; } public void setResolvable(boolean isResolvable) { _isResolvable = isResolvable; } public boolean isNewlyDiscovered() { return _newlyDiscovered; } public void setNewlyDiscovered(boolean newlyDiscovered) { _newlyDiscovered = newlyDiscovered; } public boolean isToBeIgnored() { return _isToBeIgnored; } public void setToBeIgnored(boolean isToBeIgnored) { _isToBeIgnored = isToBeIgnored; } } } public boolean contains(ClassReference searchedClass) { return _classes.contains(searchedClass); } public boolean containsSelected(ClassReference searchedClass) { return contains(searchedClass) && searchedClass.isSelected(); } public boolean isSelected() { return _selectedObjects.contains(PackageReference.this); } public Vector<ClassReference> getClasses() { return _classes; } } public ClassReference getClassReference(Class<?> aClass) { String packageName = packageNameForClass(aClass); String className = classNameForClass(aClass); PackageReference aPackage = _packages.get(packageName); if (aPackage != null) { return aPackage.getClassReference(className); } return null; } public boolean containsSelectedClass(Class<?> aClass) { ClassReference searchedClass = getClassReference(aClass); return searchedClass != null && searchedClass.isSelected(); } public ClassReference getClassReference(String fullQualifiedName) { PackageReference aPackage = _packages.get(DMSet.packageNameForClassName(fullQualifiedName)); if (aPackage != null) { return aPackage.getClassReference(fullQualifiedName); } return null; } public boolean getImportGetOnlyProperties() { return _importGetOnlyProperties; } public void setImportGetOnlyProperties(boolean importGetOnlyProperties) { _importGetOnlyProperties = importGetOnlyProperties; } public boolean getImportMethods() { return _importMethods; } public void setImportMethods(boolean importMethods) { _importMethods = importMethods; } protected Hashtable<ClassReference, DMEntity> _justResolvedEntities; public DMEntity justResolvedEntity(ClassReference classRef) { return _justResolvedEntities.get(classRef); } }