All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.nakeduml.emf.reverse.AbstractUmlGenerator Maven / Gradle / Ivy

The newest version!
package net.sf.nakeduml.emf.reverse;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.io.File;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.DataType;
import org.eclipse.uml2.uml.Enumeration;
import org.eclipse.uml2.uml.EnumerationLiteral;
import org.eclipse.uml2.uml.Interface;
import org.eclipse.uml2.uml.LiteralUnlimitedNatural;
import org.eclipse.uml2.uml.Model;
import org.eclipse.uml2.uml.Operation;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.PackageImport;
import org.eclipse.uml2.uml.Parameter;
import org.eclipse.uml2.uml.ParameterDirectionKind;
import org.eclipse.uml2.uml.PrimitiveType;
import org.eclipse.uml2.uml.Property;
import org.eclipse.uml2.uml.Type;
import org.eclipse.uml2.uml.resource.UMLResource;

public class AbstractUmlGenerator {
	protected static PrimitiveType booleanPrimitiveType;
	protected static PrimitiveType stringPrimitiveType;
	protected static PrimitiveType integerPrimitiveType;
	protected static Properties mappedTypes = new Properties();
	private static Map primitiveTypes = new HashMap();
	private static Map classMap = new HashMap();
	private static Set selectedClasses = new HashSet();

	protected static void selectClasses(JarFile jarFile) {
		java.util.Enumeration entries = jarFile.entries();
		while (entries.hasMoreElements()) {
			JarEntry entry = entries.nextElement();
			String cn = entry.getName();
			cn = cn.replaceAll("/", ".");
			if (cn.endsWith(".class")) {
				Class c = null;
				try {
					c = Thread.currentThread().getContextClassLoader().loadClass(cn.substring(0, cn.length() - 6));
				} catch (ClassNotFoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				selectedClasses.add(c);
			}
		}
	}

	protected static void importPrimitiveTypes(Package modelOrProfile) {
		Package umlLibrary = getImportedPackage(modelOrProfile, UMLResource.UML_PRIMITIVE_TYPES_LIBRARY_URI);
		booleanPrimitiveType = (PrimitiveType) umlLibrary.getOwnedType("Boolean");
		primitiveTypes.put(Boolean.class, booleanPrimitiveType);
		primitiveTypes.put(boolean.class, booleanPrimitiveType);

		stringPrimitiveType = (PrimitiveType) umlLibrary.getOwnedType("String");
		primitiveTypes.put(String.class, stringPrimitiveType);
		integerPrimitiveType = (PrimitiveType) umlLibrary.getOwnedType("Integer");
		primitiveTypes.put(Integer.class, integerPrimitiveType);
		primitiveTypes.put(int.class, integerPrimitiveType);
		primitiveTypes.put(BigInteger.class, integerPrimitiveType);
		primitiveTypes.put(Long.class, integerPrimitiveType);
		primitiveTypes.put(long.class, integerPrimitiveType);
		primitiveTypes.put(Short.class, integerPrimitiveType);
		primitiveTypes.put(short.class, integerPrimitiveType);
		primitiveTypes.put(Byte.class, integerPrimitiveType);
		primitiveTypes.put(byte.class, integerPrimitiveType);

		Package ecoreLibrary =getImportedPackage(modelOrProfile, UMLResource.JAVA_PRIMITIVE_TYPES_LIBRARY_URI);
		primitiveTypes.put(BigDecimal.class, (Classifier) ecoreLibrary.getOwnedMember("double"));
		primitiveTypes.put(Double.class, (Classifier) ecoreLibrary.getOwnedMember("double"));
		primitiveTypes.put(double.class, (Classifier) ecoreLibrary.getOwnedMember("double"));
		primitiveTypes.put(Float.class, (Classifier) ecoreLibrary.getOwnedMember("double"));
		primitiveTypes.put(float.class, (Classifier) ecoreLibrary.getOwnedMember("double"));
		classMap.putAll(primitiveTypes);
	}

	public static Model getImportedPackage(Package ecoreProfile, String uriString) {
		URI uri = URI.createURI(uriString);
		for (PackageImport pi : ecoreProfile.getPackageImports()) {
			if (pi.getImportedPackage().eResource().getURI().equals(uri)) {
				return (Model) pi.getImportedPackage();
			}
		}
		Model umlLibrary = (Model) ecoreProfile.eResource().getResourceSet().getResource(uri, true).getContents().get(0);
		ecoreProfile.createPackageImport(umlLibrary);
		return umlLibrary;
	}

	protected static Classifier getClassifierFor(Package modelOrProfile, Class returnType) {
		try {
			if (returnType == null)
				return null;
			Classifier classifier;
			if (Collection.class.isAssignableFrom(returnType) && returnType.getTypeParameters().length == 1) {
				returnType = returnType.getTypeParameters()[0].getGenericDeclaration();
			} else {
				while (returnType.isArray()) {
					returnType = returnType.getComponentType();
				}
			}
			if (classMap.containsKey(returnType)) {
				classifier = classMap.get(returnType);
			} else {
				// create enum
				classifier = (Classifier) getPackageFor(returnType, modelOrProfile).getMember(returnType.getSimpleName());
				if (classifier == null) {
					classifier = createClassifier(modelOrProfile, returnType);
				}
				classMap.put(returnType, classifier);
				mappedTypes.put(classifier.getQualifiedName(), returnType.getName());
				populateClassifier(modelOrProfile, returnType, classifier);

			}
			return classifier;
		} catch (IntrospectionException e) {
			throw new RuntimeException(e);
		}
	}

	public static Classifier createClassifier(Package modelOrProfile, Class returnType) throws IntrospectionException {
		Classifier classifier = null;
		if (returnType.isEnum()) {
			classifier = createEnum(modelOrProfile, (Class) returnType);
		} else if (returnType.isInterface()) {
			Interface umlInterface = getPackageFor(returnType, modelOrProfile).createOwnedInterface(returnType.getSimpleName());
			Class[] interfaces = returnType.getInterfaces();
			for (Class intfce : interfaces) {
				umlInterface.createGeneralization(getClassifierFor(modelOrProfile, intfce));
			}
			classifier = umlInterface;
		} else if (primitiveTypes.containsKey(returnType)) {
			classifier = getPackageFor(returnType, modelOrProfile).createOwnedPrimitiveType(returnType.getSimpleName());
		} else {
			org.eclipse.uml2.uml.Class umlClass = getPackageFor(returnType, modelOrProfile).createOwnedClass(returnType.getSimpleName(),
					false);
			Class[] interfaces = returnType.getInterfaces();
			for (Class intfce : interfaces) {
				umlClass.createInterfaceRealization(intfce.getSimpleName(), (Interface) getClassifierFor(modelOrProfile, intfce));
			}
			classifier = umlClass;
		}
		if (returnType.getSuperclass() != Object.class) {
			classifier.createGeneralization(getClassifierFor(modelOrProfile, returnType.getSuperclass()));
		}
		return classifier;
	}

	private static void populateClassifier(Package modelOrProfile, Class en, Classifier intfce) throws IntrospectionException {
		if (selectedClasses.contains(en)) {
			BeanInfo beanInfo = Introspector.getBeanInfo(en, en.getSuperclass());
			populateAttributes(modelOrProfile, intfce, beanInfo);
			populateOperations(modelOrProfile, intfce, beanInfo);
		}
	}

	private static void populateOperations(Package modelOrProfile, Classifier intfce, BeanInfo beanInfo) {
		MethodDescriptor[] mds = beanInfo.getMethodDescriptors();
		for (MethodDescriptor md : mds) {

			if (!hasOperation(modelOrProfile, intfce, md) && !isAccessor(md)) {
				Operation oper = createOperation(modelOrProfile, intfce, md);
				oper.setIsStatic(Modifier.isStatic(md.getMethod().getModifiers()));
				Class returnType = md.getMethod().getReturnType();
				if (returnType != void.class) {
					Parameter result = oper.createOwnedParameter("result", getClassifierFor(modelOrProfile, returnType));
					result.setDirection(ParameterDirectionKind.RETURN_LITERAL);
					if (returnType.isArray() || Collection.class.isAssignableFrom(returnType)) {
						result.setUpper(LiteralUnlimitedNatural.UNLIMITED);
					}
				}
				Class[] parameterTypes = md.getMethod().getParameterTypes();
				for (int i = 0; i < parameterTypes.length; i++) {
					if (parameterTypes[0].isArray() || Collection.class.isAssignableFrom(parameterTypes[0])) {
						Parameter umlParameter = oper.getOwnedParameters().get(i);
						umlParameter.setUpper(LiteralUnlimitedNatural.UNLIMITED);
						umlParameter.setName("parm"+i);
						
					}
				}
			}
		}
	}

	private static boolean isAccessor(MethodDescriptor md) {
		// TODO Auto-generated method stub
		boolean returnsVoid = md.getMethod().getReturnType()==null || md.getMethod().getReturnType()==void.class;
		boolean setter = md.getName().startsWith("set") && md.getMethod().getParameterTypes().length==1 && returnsVoid;
		boolean getter = md.getName().startsWith("get") && !returnsVoid;
		return setter || getter;
	}

	public static boolean hasOperation(Package modelOrProfile, Classifier intfce, MethodDescriptor md) {
		for (Operation oper : intfce.getOperations()) {
			if (oper.getName().equals(md.getName())) {
				boolean paramsMatch = true;
				for (int i = 0; i < md.getMethod().getParameterTypes().length; i++) {
					Parameter parm = oper.getOwnedParameters().get(i);
					if (getClassifierFor(modelOrProfile, md.getMethod().getParameterTypes()[i]) != parm.getType()) {
						paramsMatch = false;
						break;
					}
				}
				if (paramsMatch) {
					return true;
				}

			}
		}

		return false;
	}

	private static void populateAttributes(Package modelOrProfile, Classifier intfce, BeanInfo beanInfo) {
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		for (PropertyDescriptor pd : pds) {
			Class propertyType = pd.getPropertyType();
			if (propertyType == null) {
				System.out.println("Property type null:" + pd.getReadMethod());
			} else {
				if (intfce.getAttribute(pd.getName(), getClassifierFor(modelOrProfile, pd.getPropertyType())) == null) {
					Property attr = createAttribute(modelOrProfile, intfce, pd);
					attr.setIsReadOnly(pd.getWriteMethod() == null);
					attr.setIsDerived(pd.getWriteMethod() == null);
					if (propertyType.isArray()) {
						attr.setUpper(-1);
					}
				}
			}
		}
	}

	private static Operation createOperation(Package modelOrProfile, Classifier intfce, MethodDescriptor md) {
		Operation oper = null;
		if (intfce instanceof Interface) {
			oper = ((Interface) intfce).createOwnedOperation(md.getName(), getArgumentNames(md), getArgumentTypes(modelOrProfile, md));
		} else if (intfce instanceof DataType) {
			oper = ((DataType) intfce).createOwnedOperation(md.getName(), getArgumentNames(md), getArgumentTypes(modelOrProfile, md));
		} else if (intfce instanceof org.eclipse.uml2.uml.Class) {
			oper = ((org.eclipse.uml2.uml.Class) intfce).createOwnedOperation(md.getName(), getArgumentNames(md),
					getArgumentTypes(modelOrProfile, md));
		}
		return oper;
	}

	private static Property createAttribute(Package modelOrProfile, Classifier intfce, PropertyDescriptor pd) {
		Property attr = null;
		if (intfce instanceof Interface) {
			attr = ((Interface) intfce).createOwnedAttribute(pd.getName(), getClassifierFor(modelOrProfile, pd.getPropertyType()));
		} else if (intfce instanceof org.eclipse.uml2.uml.Class) {
			attr = ((org.eclipse.uml2.uml.Class) intfce).createOwnedAttribute(pd.getName(),
					getClassifierFor(modelOrProfile, pd.getPropertyType()));
		} else if (intfce instanceof DataType) {
			attr = ((DataType) intfce).createOwnedAttribute(pd.getName(), getClassifierFor(modelOrProfile, pd.getPropertyType()));
		}
		return attr;
	}

	private static EList getArgumentNames(MethodDescriptor md) {
		BasicEList results = new BasicEList();
			for (int i=0; i  getArgumentTypes(Package modelOrProfile, MethodDescriptor md) {
		BasicEList results = new BasicEList();
		Class[] pds = md.getMethod().getParameterTypes();
		for (@SuppressWarnings("rawtypes")
		Class pd : pds) {
			results.add(getClassifierFor(modelOrProfile, pd));
		}
		return results;
	}

	@SuppressWarnings("rawtypes")
	private static Classifier createEnum(Package modelOrProfile, Class en) throws IntrospectionException {
		Enumeration enumeration = getPackageFor(en, modelOrProfile).createOwnedEnumeration(en.getSimpleName());
		Enum[] enumConstants = en.getEnumConstants();
		for (Enum e : enumConstants) {
			if (enumeration.getMember(e.name()) == null) {
				EnumerationLiteral enumerationLiteral = ((Enumeration) enumeration).createOwnedLiteral(e.name());
				// TODO implement instancespecifications
			}
		}
		return enumeration;
	}

	private static Package getPackageFor(@SuppressWarnings("rawtypes") Class javaClass, Package ecoreModelOrProfile) {
		StringTokenizer st = new StringTokenizer(javaClass.getPackage().getName(), ".");
		Package currentPackage = ecoreModelOrProfile;
		while (st.hasMoreTokens()) {
			String name = st.nextToken();
			Package childPackage = (Package) currentPackage.getMember(name);
			if (childPackage == null) {
				childPackage = currentPackage.createNestedPackage(name);
			}
			currentPackage = childPackage;

		}
		return currentPackage;
	}

	protected static String findUml2ResourceJar() throws Exception {
		URLClassLoader s = (URLClassLoader) Thread.currentThread().getContextClassLoader();
		URL[] urls = s.getURLs();
		String UML2JAR = null;
		for (URL url : urls) {
			if (url.getFile().contains("org.eclipse.uml2.uml.resources")) {
				File file = new File(url.getFile());
				UML2JAR = "jar:file:///" + file.getAbsolutePath().replace('\\', '/') + "!/";
				System.out.println(UML2JAR);
				break;
			}
		}
		return UML2JAR;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy