/** * <copyright> * * Copyright (c) 2009, 2010 Springsite BV (The Netherlands) and others * 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: * Martin Taal - Initial API and implementation * * </copyright> * * $Id: AnnotationModelGenerator.java,v 1.9 2011/08/25 12:34:30 mtaal Exp $ */ package org.eclipse.emf.texo.generator; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EEnum; import org.eclipse.emf.ecore.EEnumLiteral; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.plugin.EcorePlugin; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.emf.texo.annotations.AnnotationModelSuffixHandler; import org.eclipse.emf.texo.annotations.annotationsmodel.AnnotatedEAttribute; import org.eclipse.emf.texo.annotations.annotationsmodel.AnnotatedEClass; import org.eclipse.emf.texo.annotations.annotationsmodel.AnnotatedEDataType; import org.eclipse.emf.texo.annotations.annotationsmodel.AnnotatedEEnum; import org.eclipse.emf.texo.annotations.annotationsmodel.AnnotatedEPackage; import org.eclipse.emf.texo.annotations.annotationsmodel.AnnotatedEReference; import org.eclipse.emf.texo.annotations.annotationsmodel.AnnotatedModel; import org.eclipse.emf.texo.annotations.annotationsmodel.AnnotationsmodelFactory; import org.eclipse.emf.texo.annotations.annotationsmodel.ENamedElementAnnotation; /** * Generates an AnnotationModel for an epackage and its subpackages. This class can generate an empty annotation model * or a completely annotated model. * * @author <a href="mtaal@elver.org">Martin Taal</a> */ public class AnnotationModelGenerator { private List<ModelAnnotator> modelAnnotators = null; private boolean createOnlyInitialModel = false; private AnnotatedModel aModel; public void createStoreAnnotationModel(EPackage ePackage, String suffix, EPackage annotationEPackage, IFile modelFile) { try { final ResourceSet resourceSet = ePackage.eResource().getResourceSet(); final org.eclipse.emf.common.util.URI fileUri = org.eclipse.emf.common.util.URI.createFileURI(modelFile .getLocation().toOSString()); final org.eclipse.emf.common.util.URI fileAnnotationModelUri = AnnotationModelSuffixHandler .createAnnotationsModelURIWithSuffix(fileUri, suffix); resourceSet.getURIConverter().getURIMap().putAll(EcorePlugin.computePlatformURIMap(true)); final File file = new File(fileAnnotationModelUri.toFileString()); final Resource resource; if (file.exists()) { resource = resourceSet.getResource(fileAnnotationModelUri, true); } else { resource = resourceSet.createResource(fileAnnotationModelUri); if (ePackage.eResource() instanceof XMLResource) { final String encoding = ((XMLResource) ePackage.eResource()).getEncoding(); ((XMLResource) resource).setEncoding(encoding); } } if (!resource.getContents().isEmpty() && resource.getContents().get(0) instanceof AnnotatedModel) { aModel = (AnnotatedModel) resource.getContents().get(0); } else { resource.getContents().clear(); aModel = AnnotationsmodelFactory.eINSTANCE.createAnnotatedModel(); resource.getContents().add(aModel); } fillAnnotatedModel(ePackage); if (annotationEPackage != null) { filterAnnotations(annotationEPackage); } resource.save(Collections.emptyMap()); } catch (Exception e) { throw new IllegalStateException( "Exception (" + e.getMessage() + ") for modelFile: " + modelFile.getFullPath().toString() + " epackage " //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + ePackage.getName() + " epackage uri : " + ePackage.eResource().getURI(), e); //$NON-NLS-1$ } } private void filterAnnotations(EPackage annotationEPackage) { // iterate over all the content, copy to a list to prevent issues later final Iterator<EObject> iterator = aModel.eAllContents(); final List<EObject> allContents = new ArrayList<EObject>(); while (iterator.hasNext()) { allContents.add(iterator.next()); } for (Object obj : allContents) { if (obj instanceof AnnotatedEPackage) { filterAnnotations(((AnnotatedEPackage) obj).getEPackageAnnotations(), annotationEPackage); } else if (obj instanceof AnnotatedEClass) { filterAnnotations(((AnnotatedEClass) obj).getEClassAnnotations(), annotationEPackage); } else if (obj instanceof AnnotatedEEnum) { filterAnnotations(((AnnotatedEEnum) obj).getEEnumAnnotations(), annotationEPackage); } else if (obj instanceof AnnotatedEDataType) { filterAnnotations(((AnnotatedEDataType) obj).getEDataTypeAnnotations(), annotationEPackage); } else if (obj instanceof AnnotatedEAttribute) { filterAnnotations(((AnnotatedEAttribute) obj).getEAttributeAnnotations(), annotationEPackage); } else if (obj instanceof AnnotatedEReference) { filterAnnotations(((AnnotatedEReference) obj).getEReferenceAnnotations(), annotationEPackage); } } } private void filterAnnotations(List<? extends ENamedElementAnnotation> annotations, EPackage annotationEPackage) { final List<ENamedElementAnnotation> toRemove = new ArrayList<ENamedElementAnnotation>(); for (ENamedElementAnnotation annotation : annotations) { if (annotation.eClass().getEPackage() != annotationEPackage) { toRemove.add(annotation); } } annotations.removeAll(toRemove); } public void setModelAnnotators(List<ModelAnnotator> modelAnnotators) { this.modelAnnotators = modelAnnotators; } public void fillAnnotatedModel(EPackage ePackage) { final List<EPackage> ePackages = new ArrayList<EPackage>(); collectEPackages(ePackage, ePackages); if (modelAnnotators != null && modelAnnotators.size() > 0) { final ModelController modelController = new ModelController(); modelController.setEPackages(ePackages); modelController.getAnnotationManager().setAnnotatedModel(aModel); modelController.annotate(modelAnnotators); } // walk over the whole model and ask the aModel for an annotated version // this automatically creates it and adds it to the model for (EPackage collectedEPackage : ePackages) { final AnnotatedEPackage aPackage = aModel.getAnnotatedEPackage(collectedEPackage, true); // if only the initial model stop at the EPackage level if (isCreateOnlyInitialModel()) { aPackage.getAllAnnotations().clear(); aPackage.getAnnotatedEClassifiers().clear(); aPackage.getEPackageAnnotations().clear(); } else { for (EClassifier eClassifier : collectedEPackage.getEClassifiers()) { aModel.getAnnotatedEClassifier(eClassifier, true); if (eClassifier instanceof EClass) { final EClass eClass = (EClass) eClassifier; // on purpose not getting efeatures of super types! for (EAttribute eAttribute : eClass.getEAttributes()) { aModel.getAnnotatedEAttribute(eAttribute, true); } for (EReference eReference : eClass.getEReferences()) { aModel.getAnnotatedEReference(eReference, true); } } else if (eClassifier instanceof EEnum) { final EEnum eEnum = (EEnum) eClassifier; aModel.getAnnotatedEEnum(eEnum, true); for (EEnumLiteral literal : eEnum.getELiterals()) { aModel.getAnnotatedEEnumLiteral(literal, true); } } else if (eClassifier instanceof EDataType) { final EDataType eDataType = (EDataType) eClassifier; aModel.getAnnotatedEDataType(eDataType, true); } } } } // other epackages may have been added during the annotation activities // remove those again from the annotated model final List<AnnotatedEPackage> toRemove = new ArrayList<AnnotatedEPackage>(); for (AnnotatedEPackage aPackage : aModel.getAnnotatedEPackages()) { if (!ePackages.contains(aPackage.getEPackage())) { toRemove.add(aPackage); } } aModel.getAnnotatedEPackages().removeAll(toRemove); } private void collectEPackages(EPackage ePackage, List<EPackage> ePackages) { ePackages.add(ePackage); for (EPackage subEPackage : ePackage.getESubpackages()) { collectEPackages(subEPackage, ePackages); } } public boolean isCreateOnlyInitialModel() { return createOnlyInitialModel; } public void setCreateOnlyInitialModel(boolean createOnlyInitialModel) { this.createOnlyInitialModel = createOnlyInitialModel; } }