Java tutorial
/******************************************************************************* * Copyright (c) 2006-2013 * Software Technology Group, Dresden University of Technology * DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026 * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Software Technology Group - TU Dresden, Germany; * DevBoost GmbH - Berlin, Germany * - initial API and implementation ******************************************************************************/ package de.devboost.emfcustomize; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.apache.commons.lang.StringUtils; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.emf.codegen.ecore.genmodel.GenClass; import org.eclipse.emf.codegen.ecore.genmodel.GenPackage; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EParameter; import org.eclipse.emf.ecore.EcoreFactory; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; import org.emftext.language.java.classifiers.Class; import org.emftext.language.java.classifiers.ConcreteClassifier; import org.emftext.language.java.containers.CompilationUnit; import org.emftext.language.java.generics.QualifiedTypeArgument; import org.emftext.language.java.members.Method; import org.emftext.language.java.modifiers.AnnotationInstanceOrModifier; import org.emftext.language.java.modifiers.Public; import org.emftext.language.java.parameters.Parameter; import org.emftext.language.java.resource.java.mopp.JavaResource; import org.emftext.language.java.types.NamespaceClassifierReference; import org.emftext.language.java.types.PrimitiveType; import org.emftext.language.java.types.Type; import org.emftext.language.java.types.TypeReference; public class EcoreModelRefactorer { public static final String MODEL_ANNOTATION = "@model"; private static final char[] VALID_PREFIX_CHARACTERS = new char[] { '*' }; public void propagateEOperations(JavaResource resource, GenClass genClass) { GenPackage genPackage = genClass.getGenPackage(); EPackage ePackage = genPackage.getEcorePackage(); if (resource.getContents().isEmpty() || !(resource.getContents().get(0) instanceof CompilationUnit)) { return; } CompilationUnit cu = (CompilationUnit) resource.getContents().get(0); Class customClass = (Class) cu.getClassifiers().get(0); EClass eClass = genClass.getEcoreClass(); if (eClass == null) { return; } Set<Method> annotatedMethods = getAnnotatedMethods(customClass); for (Method method : annotatedMethods) { for (AnnotationInstanceOrModifier modifier : method.getAnnotationsAndModifiers()) { if (modifier instanceof Public) { EOperation newEOperation = EcoreFactory.eINSTANCE.createEOperation(); newEOperation.setName(method.getName()); Type opType = method.getTypeReference().getTarget(); newEOperation.setEType(eClassifierForCustomClass(opType, method.getTypeReference(), ePackage)); if (isMulti(opType)) { newEOperation.setUpperBound(-1); } for (Parameter parameter : method.getParameters()) { EParameter newEParameter = EcoreFactory.eINSTANCE.createEParameter(); newEParameter.setName(parameter.getName()); Type paramType = parameter.getTypeReference().getTarget(); newEParameter.setEType( eClassifierForCustomClass(paramType, parameter.getTypeReference(), ePackage)); //TODO generics, ... newEOperation.getEParameters().add(newEParameter); } // TODO @jendrik: why is that needed? // for (AnnotationInstanceOrModifier annotationInstance : method.getAnnotationsAndModifiers()) { // if (annotationInstance instanceof AnnotationInstance) { // Classifier javaAnnotation = ((AnnotationInstance) annotationInstance).getAnnotation(); // if (javaAnnotation.eIsProxy()) { // continue; // } // EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation(); // eAnnotation.setSource(javaAnnotation.getContainingCompilationUnit( // ).getNamespacesAsString() + javaAnnotation.getName()); // newEOperation.getEAnnotations().add(eAnnotation); // } // } boolean operationAlreadyExists = false; List<EOperation> operations = eClass.getEOperations(); List<EOperation> existingOperations = new ArrayList<EOperation>(operations); // must be done here already for ensuring that compared operations have the same parent eClass.getEOperations().add(newEOperation); for (EOperation existingOperation : existingOperations) { boolean removed = removeAnnotation(existingOperation); if (EcoreUtil.equals(existingOperation, newEOperation)) { operationAlreadyExists = true; removeAnnotation(existingOperation); annotateAsGenerated(existingOperation); break; } if (removed) { annotateAsGenerated(existingOperation); } } if (!operationAlreadyExists) { annotateAsGenerated(newEOperation); } else { eClass.getEOperations().remove(newEOperation); } break; } } } try { Resource ecoreResource = ePackage.eResource(); URI originalURI = ecoreResource.getURI(); if (originalURI.isFile()) { String workspacePath = ResourcesPlugin.getWorkspace().getRoot().getLocation().toString(); URI platformURI = URI.createPlatformResourceURI( originalURI.toFileString().substring(workspacePath.length()), true); ecoreResource.setURI(platformURI); } new ResourceSaver().saveResource(ecoreResource); ecoreResource.setURI(originalURI); } catch (IOException e) { e.printStackTrace(); } } private boolean removeAnnotation(EOperation existingOperation) { List<EAnnotation> annotations = existingOperation.getEAnnotations(); EAnnotation annotationToRemove = null; for (EAnnotation annotation : annotations) { if (annotation.getSource().equals(EcoreModelRefactorer.class.getName())) { annotationToRemove = annotation; } } if (annotationToRemove != null) { return annotations.remove(annotationToRemove); } return false; } public Set<Method> getAnnotatedMethods(Class customClass) { Set<Method> annotatedMethods = new HashSet<Method>(); List<Method> methods = customClass.getMethods(); for (Method method : methods) { List<String> comments = method.getComments(); if (comments != null && comments.size() > 0) { for (String comment : comments) { String[] lines = comment.split("[\\r\\n]+"); for (String line : lines) { String deleteWhitespace = StringUtils.deleteWhitespace(line); if (StringUtils.endsWith(deleteWhitespace, MODEL_ANNOTATION)) { String difference = StringUtils.removeEnd(deleteWhitespace, MODEL_ANNOTATION); if (StringUtils.containsOnly(difference, VALID_PREFIX_CHARACTERS) || difference.isEmpty()) { annotatedMethods.add(method); } } } } } } return annotatedMethods; } // private void clearExistingOperations(EClass eClass) { // for (Iterator<EOperation> i = eClass.getEOperations().iterator(); i.hasNext();) { // if (i.next().getEAnnotation(EcoreModelRefactorer.class.getName()) != null) { // i.remove(); // } // } // } private void annotateAsGenerated(EOperation newEOperation) { EAnnotation eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation(); eAnnotation.setSource(EcoreModelRefactorer.class.getName()); newEOperation.getEAnnotations().add(eAnnotation); } private EClassifier eClassifierForCustomClass(Type type, TypeReference typeReference, EPackage startEPackage) { Set<EPackage> allEPackages = new LinkedHashSet<EPackage>(); collectAllEPackages(startEPackage, allEPackages); for (EPackage ePackage : allEPackages) { if (type instanceof ConcreteClassifier) { if (((ConcreteClassifier) type).getName().equals("EList")) { QualifiedTypeArgument typeArgument = (QualifiedTypeArgument) ((NamespaceClassifierReference) typeReference) .getClassifierReferences().get(0).getTypeArguments().get(0); type = typeArgument.getTypeReference().getTarget(); } String className = eClassNameForCustomClassName(((ConcreteClassifier) type).getName()); for (EClassifier eClassifier : ePackage.getEClassifiers()) { if (eClassifier.getName().equals(className)) { return eClassifier; } } if (className.equals("Class")) { className = "JavaClass"; //TODO type parameters } for (EClassifier typeFromEcore : EcorePackage.eINSTANCE.getEClassifiers()) { // so that not only String is mapped to EString but also EObject to EObject if (typeFromEcore.getName().equals(className) || typeFromEcore.getName().equals("E" + className)) { return typeFromEcore; } } } else if (type instanceof PrimitiveType) { String primitiveTypeName = "E" + type.eClass().getName(); for (EClassifier typeFromEcore : EcorePackage.eINSTANCE.getEClassifiers()) { if (typeFromEcore.getName().equals(primitiveTypeName)) { return typeFromEcore; } } } } return null; } private boolean isMulti(Type type) { if (type instanceof ConcreteClassifier) { String className = ((ConcreteClassifier) type).getName(); if (className.equals("EList")) { return true; } } return false; } private void collectAllEPackages(EPackage startEPackage, Set<EPackage> allEPackages) { if (allEPackages.contains(startEPackage)) { return; } allEPackages.add(startEPackage); for (EClassifier eClassifier : startEPackage.getEClassifiers()) { if (eClassifier instanceof EClass) { for (EClass superType : ((EClass) eClassifier).getESuperTypes()) { if (!superType.eIsProxy()) { collectAllEPackages(superType.getEPackage(), allEPackages); } } } } } private String eClassNameForCustomClassName(String name) { int idx = name.indexOf(GeneratedFactoryRefactorer.CUSTOM_CLASS_SUFFIX); if (idx != -1) { return name.substring(0, idx); } return name; } }