Java tutorial
/******************************************************************************* * Copyright (c) 2015 IBM Corporation 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package metabest.transformations; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Random; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.lang.StringUtils; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.util.EcoreUtil; import org.xml.sax.SAXException; import fragments.BooleanValue; import fragments.Fragment; import fragments.IntegerValue; import fragments.PrimitiveValue; import fragments.StringValue; import test.ComplementaryBlock; import test.ExtensionAssertion; import test.ExtensionAssertionSet; import test.FragmentObjectExtensionAssertion; import test.MetaClassExtensionAssertion; import test.TestableFragment; import test.extensions.AndQualifier; import test.extensions.AttributeValue; import test.extensions.Contains; import test.extensions.FragmentObjectQualifier; import test.extensions.FragmentObjectSelector; import test.extensions.MetaClassQualifier; import test.extensions.MetaClassSelector; import test.extensions.OrQualifier; import test.extensions.Qualifier; import test.extensions.Reach; import test.extensions.Selector; import metabup.annotations.IAnnotation; import metabup.annotations.IAnnotationFactory; import metabup.annotations.IConstraintAnnotation; import metabup.annotations.catalog.design.Composition; import metabup.metamodel.AnnotatedElement; import metabup.metamodel.Annotation; import metabup.metamodel.AnnotationParam; import metabup.metamodel.Attribute; import metabup.metamodel.ElementValue; import metabup.metamodel.MetaClass; import metabup.metamodel.MetaModel; import metabup.metamodel.Reference; import metabup.metamodel.impl.ReferenceImpl; import metabup.sketches.Sketch; import metabup.sketches.Sketch2Legend; import metabup.sketches.XMLBasedImporter; import metabup.sketches.importers.yed.YedImporter; import metabup.sketches.legend.Legend; import metabup.sketches.legend.LegendElement; import metamodeltest.Every; import metamodeltest.None; import metamodeltest.Quantifier; public class MetaModel2Use { private MetaModel mm = null; private File useFile = null; private HashMap<String, String> nameSwitch = new HashMap<String, String>(); private IAnnotationFactory af = null; public static String DUMMY_CLASS_NAME = "DummyMetaBestClass"; public static String DUMMY_OBJECT_NAME = "DummyMetaBestObject"; public static String useWords[] = { "model", "constraints", "enum", "abstract", "class", "attributes", "operations", "end", "association", "composition", "aggregation", "between", "role", "ordered", "associationclass", "context", "inv", "pre", "post", "Set", "Bag", "Sequence", "Integer", "Real", "Boolean", "String", "from", "min", "max" }; private List<Reference> serialized = new ArrayList<Reference>(); public MetaModel2Use(MetaModel mm, IProject project, IAnnotationFactory factory, File legendFile) { this.mm = mm; this.af = factory; useFile = new File(project.getFile(mm.getName().substring(0, mm.getName().indexOf(".") - 1) + ".use") .getLocation().toString()); if (useFile != null && useFile.exists()) { useFile.delete(); try { useFile.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } nameSwitch = new HashMap<String, String>(); } public HashMap<String, String> getNameSwitch() { return nameSwitch; } /*public void removeUseFile(){ if(useFile != null && useFile.exists()){ useFile.delete(); } }*/ public File execute(Fragment baseFragment, int minDefaultRefs, int maxDefaultRefs, boolean addAttributes, boolean addReferences, boolean addContainees, boolean makeUnreachable) throws IOException { if (mm == null || useFile == null) return null; FileWriter fw = new FileWriter(useFile.getAbsoluteFile()); BufferedWriter bw = new BufferedWriter(fw); bw.write("model " + mm.getName().subSequence(0, mm.getName().indexOf(".")) + "\n"); if (baseFragment != null) serializeDummyClass(bw); for (MetaClass mc : mm.getClasses()) serializeClass(bw, mc); for (MetaClass mc : mm.getClasses()) serializeClassReferences(bw, mc, ReferenceImpl.CONTAINMENT); for (MetaClass mc : mm.getClasses()) serializeClassReferences(bw, mc, ReferenceImpl.ASSOCIATION); List<AnnotatedElement> elements = new ArrayList<AnnotatedElement>(); elements.addAll(mm.getClasses()); elements.addAll(mm.getReferences()); serializeConstraints(bw, elements, baseFragment, minDefaultRefs, maxDefaultRefs, addAttributes, addReferences, addContainees, makeUnreachable); bw.close(); return useFile; } private void serializeDummyClass(BufferedWriter bw) throws IOException { bw.write("\n\nclass " + this.DUMMY_CLASS_NAME + "\nend"); } private void serializeConstraints(BufferedWriter bw, List<AnnotatedElement> aes, Fragment baseFragment, int minDefaultRefs, int maxDefaultRefs, boolean addAttributes, boolean addReferences, boolean addContainees, boolean makeUnreachable) throws IOException { bw.write("\n\nconstraints\n"); // serialize class constraints for (AnnotatedElement ae : aes) { try { this.serializeElementConstraints(bw, ae); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } // serialize default USE containment logics preventive constraints //serializeSelfReferenceConstraints(bw, mm.getClasses()); serializeClassContainmentConstraints(bw, mm.getClasses()); //serializeRefBoundsConstraints(bw, mm.getClasses(), minDefaultRefs, maxDefaultRefs); if (baseFragment != null) { //System.out.println("yo"); serializeBaseFragmentConstraint(bw, baseFragment, addAttributes, addReferences, addContainees, makeUnreachable); } //serializeGeometryConstraints(bw, mm.getClasses()); } private void serializeSelfReferenceConstraints(BufferedWriter bw, EList<MetaClass> classes) throws IOException { if (classes == null || classes.isEmpty()) return; for (MetaClass mc : classes) { if (mc.getReferences() == null || mc.getReferences().isEmpty()) continue; String className = nameSwitch.get(mc.getName()); for (Reference r : mc.getReferences()) { if (mc.equals(r.getReference()) || mc.isSuperTo(r.getReference())) { String refName = nameSwitch.get(r.getName()); bw.write("\ncontext " + className + " inv " + className + "_" + refName + "_selfReference : "); bw.write("\n\tnot self." + refName + " -> includes(self)"); } } } } private void serializeRefBoundsConstraints(BufferedWriter bw, EList<MetaClass> classes, int min, int max) throws IOException { for (MetaClass mc : classes) { String className = nameSwitch.get(mc.getName()); for (metabup.metamodel.Reference r : mc.getReferences()) { String refName = nameSwitch.get(r.getName()); if (refName == null) { refName = r.getName(); nameSwitch.put(r.getName(), r.getName()); } int fixedMin = min, fixedMax = max; if (min < r.getMin()) fixedMin = r.getMin(); if (r.getMax() != -1 && r.getMax() < max) fixedMax = r.getMax(); bw.write("\ncontext " + className + " inv " + className + "_" + refName + "_bounds : "); //context Coding inv bound : Coding.allInstances() -> forAll (c : Coding | c.nextPhase -> size() = 1) bw.write("\n\t" + className + ".allInstances() -> forAll (o : " + className + " | o." + refName + " -> size() >= " + min); bw.write("\n\t\t and o." + refName + " -> size() <= " + max + ")"); } } } private void serializeBaseFragmentConstraint(BufferedWriter bw, Fragment baseFragment, boolean addAttributes, boolean addReferences, boolean addContainees, boolean makeUnreachable) throws IOException { /* * NONE OF THIS IS NECESSARY ANYMORE (because of the change from line 401) * * boolean someFeature = false; for(metabup.fragments.Object o : baseFragment.getObjects()){ if(o.getFeatures() != null && !o.getFeatures().isEmpty()){ someFeature = true; break; } } // IN CASE THE BASE FRAGMENT FEATURES MERELY CLASES (WITH NO FEATURES) if(!someFeature){ List<String> types = new ArrayList<String>(); for(metabup.fragments.Object o : baseFragment.getObjects()){ if(!types.contains(nameSwitch.get(o.getType()))){ bw.write("\n\ncontext " + nameSwitch.get(o.getType()) + " inv BaseFragment_" + nameSwitch.get(o.getType()) + ":\n\t"); bw.write(nameSwitch.get(o.getType()) + ".allInstances() -> size() >= " + baseFragment.getObjects(nameSwitch.get(o.getType())).size()); types.add(nameSwitch.get(o.getType())); } } //return; }*/ // IN CASE THE BASE FRAGMENT HAS FEATURES //bw.write("\n\ncontext " + this.DUMMY_CLASS_NAME + " inv DummyClassMinEvaluation : "+ this.DUMMY_CLASS_NAME + ".allInstances()->size() = 1\n"); bw.write("\n\ncontext " + this.DUMMY_CLASS_NAME + " inv BaseFragment:\n\t"); for (fragments.Object o : baseFragment.getObjects()) { bw.write(nameSwitch.get(o.getType()) + ".allInstances() -> exists(" + o.getName()); //if(!baseFragment.getObjects().get(baseFragment.getObjects().size()-1).equals(o)) bw.write("|"); bw.write(" | "); bw.write("\n\t"); } boolean first = true; for (fragments.Object o : baseFragment.getObjects()) { for (fragments.Feature f : o.getFeatures()) { if (f instanceof fragments.Attribute) { fragments.Attribute a = (fragments.Attribute) f; if (first) first = false; else bw.write(" and "); bw.write("\n" + o.getName() + "." + nameSwitch.get(f.getName()) + " = "); PrimitiveValue pv = a.getValues().get(0); // only single multiplicity attributes for now if (pv instanceof StringValue) { /*StringValue sv = (StringValue)pv; bw.write("\'" + sv.getValue() + "\'");*/ } else if (pv instanceof IntegerValue) { IntegerValue iv = (IntegerValue) pv; //System.out.println("here's your integer: " + iv.getValue()); bw.write(iv.getValue().toString()); } else if (pv instanceof BooleanValue) { BooleanValue bv = (BooleanValue) pv; bw.write(bv.getValue().toString()); } } else if (f instanceof fragments.Reference) { fragments.Reference r = (fragments.Reference) f; //System.out.println("yo"); //if(r.getReference().size() > 1){ if (first) first = false; else bw.write(" and "); bw.write("\n" + o.getName() + "." + nameSwitch.get(f.getName())); bw.write(" -> includesAll(Set{"); for (fragments.Object to : r.getReference()) { bw.write(to.getName()); if (!r.getReference().get(r.getReference().size() - 1).equals(to)) bw.write(", "); } bw.write("})"); /*}else{ if(first) first = false; else bw.write(" and "); bw.write("\n" + o.getName() + "." + nameSwitch.get(f.getName())); bw.write(" = " + r.getReference().get(0).getName()); }*/ } } if (!addAttributes) { MetaClass mc = mm.getClassByName(nameSwitch.get(o.getType())); for (Attribute a : mc.getAttributes(true)) { boolean found = false; for (fragments.Feature of : o.getFeatures()) if (of.getName().equals(nameSwitch.get(a.getName()))) found = true; /* if the object does not account certain feature and the user has selected not to augment * objects with undefined attributes, then USE is forbidden to do so */ if (!found) { if (first) first = false; else bw.write(" and "); bw.write("\n" + o.getName() + "." + nameSwitch.get(a.getName()) + " -> oclIsUndefined()"); } else { // if cardinality is to be considered with attributes... } } } if (!addReferences) { MetaClass mc = mm.getClassByName(nameSwitch.get(o.getType())); for (Reference r : mc.getReferences(true, ReferenceImpl.ASSOCIATION)) { boolean found = false; fragments.Reference thisOne = null; for (fragments.Feature of : o.getFeatures()) { if (of instanceof fragments.Reference && of.getName().equals(nameSwitch.get(r.getName()))) { found = true; thisOne = (fragments.Reference) of; } } /* if the object does not account certain feature and the user has selected not to augment * objects with undefined references, then USE is forbidden to do so */ if (!found) { if (first) first = false; else bw.write(" and "); bw.write("\n" + o.getName() + "." + nameSwitch.get(r.getName()) + " -> oclIsUndefined()"); } else { if (first) first = false; else bw.write(" and "); bw.write("\n" + o.getName() + "." + nameSwitch.get(r.getName()) + " -> size() = " + thisOne.getReference().size()); } } } if (!addContainees) { MetaClass mc = mm.getClassByName(nameSwitch.get(o.getType())); for (Reference r : mc.getReferences(true, ReferenceImpl.CONTAINMENT)) { boolean found = false; fragments.Reference thisOne = null; for (fragments.Feature of : o.getFeatures()) { if (of instanceof fragments.Reference && of.getName().equals(nameSwitch.get(r.getName()))) { found = true; thisOne = (fragments.Reference) of; } } if (!found) { if (first) first = false; else bw.write(" and "); bw.write("\n" + o.getName() + "." + nameSwitch.get(r.getName()) + " -> oclIsUndefined()"); } else { if (first) first = false; else bw.write(" and "); bw.write("\n" + o.getName() + "." + nameSwitch.get(r.getName()) + " -> size() = " + thisOne.getReference().size()); } } } } /* * if the user doesn't wish the base fragment to be reached by new objects, then we armour them */ if (makeUnreachable) { List<metabup.metamodel.Reference> refs = new ArrayList<metabup.metamodel.Reference>(); int i = 0; jump: for (metabup.metamodel.Reference r : mm.getReferences()) { String srcclass = nameSwitch.get(((MetaClass) r.eContainer()).getName()); String tarclass = nameSwitch.get(r.getReference().getName()); List<MetaClass> tarSubs = r.getReference().getAllSubs(); List<fragments.Object> tarObs = new ArrayList<fragments.Object>(); tarObs.addAll(baseFragment.getObjects(tarclass)); for (MetaClass sub : tarSubs) tarObs.addAll(baseFragment.getObjects(nameSwitch.get(sub.getName()))); if (tarObs.isEmpty()) continue jump; List<MetaClass> srcSubs = mm.getClassByName(srcclass).getAllSubs(); List<fragments.Object> srcObs = new ArrayList<fragments.Object>(); srcObs.addAll(baseFragment.getObjects(srcclass)); for (MetaClass sub : srcSubs) srcObs.addAll(baseFragment.getObjects(nameSwitch.get(sub.getName()))); if (first) first = false; else bw.write(" and "); bw.write("\n" + srcclass + ".allInstances() -> excludesAll( " + srcclass + ".allInstances() -> select (" + this.DUMMY_OBJECT_NAME + i + " | "); boolean thisFirst = true; for (fragments.Object o : srcObs) { if (thisFirst) thisFirst = false; else bw.write(" and "); bw.write("\n\t\t" + this.DUMMY_OBJECT_NAME + i + " <> " + o.getName() + " "); } boolean oneMoreBracket = false; if (thisFirst) thisFirst = false; else { bw.write(" and ("); oneMoreBracket = true; } boolean orFirst = true; for (fragments.Object o : tarObs) { if (orFirst) orFirst = false; else bw.write(" or "); bw.write("\n\t\t\t" + this.DUMMY_OBJECT_NAME + i + "." + nameSwitch.get(nameSwitch.get(r.getName())) + "->includes(" + o.getName() + ")"); } bw.write("))"); if (oneMoreBracket) bw.write(")"); i++; } } if (baseFragment.getObjects().size() > 1) { for (fragments.Object o1 : baseFragment.getObjects()) { for (fragments.Object o2 : baseFragment.getObjects()) { if (!o1.equals(o2) && o1.getType().equals(o2.getType())) { if (first) first = false; else bw.write(" and "); bw.write("\n" + o1.getName() + " <> " + o2.getName()); } } } } //System.out.println("CLASS: " + baseFragment.getClass()); if (baseFragment instanceof TestableFragment) { TestableFragment tf = (TestableFragment) baseFragment; ComplementaryBlock cb = tf.getAssertionSet(); System.out.println("yo again"); // in case there are extension conditions if (cb != null && cb instanceof ExtensionAssertionSet) { ExtensionAssertionSet eas = (ExtensionAssertionSet) cb; for (ExtensionAssertion ea : eas.getAssertions()) { if (first) first = false; else bw.write(" and "); serializeExtensionAssertion(bw, ea, baseFragment); } } bw.write("\n"); } if (first) bw.write("true"); for (fragments.Object o : baseFragment.getObjects()) bw.write(")"); } private void serializeExtensionAssertion(BufferedWriter bw, ExtensionAssertion ea, Fragment baseFragment) throws IOException { // assertion 'bout a metaclass if (ea instanceof MetaClassExtensionAssertion) serializeMetaClassExtensionAssertion(bw, (MetaClassExtensionAssertion) ea, baseFragment); else if (ea instanceof FragmentObjectExtensionAssertion) serializeFragmentObjectExtensionAssertion(bw, (FragmentObjectExtensionAssertion) ea, baseFragment); } private void serializeMetaClassExtensionAssertion(BufferedWriter bw, MetaClassExtensionAssertion ea, Fragment baseFragment) throws IOException { MetaClassSelector selector = ((MetaClassExtensionAssertion) ea).getSelector(); String className = selector.getMetaclassName(); boolean onlyNewElements = selector.isOnlyNewElements(); MetaClass metaclass = mm.getClassByName(className); if (metaclass == null) { // Class not found. Report error return; } bw.write("\n" + className + ".allInstances() "); if (onlyNewElements) { List<MetaClass> subs = metaclass.getAllSubs(); //System.out.println("HERE: " + subs.size()); List<String> subNames = new ArrayList<String>(); for (MetaClass mc : subs) subNames.add(mc.getName()); subNames.add(metaclass.getName()); for (String classname : subNames) for (fragments.Object o : baseFragment.getObjects(classname)) bw.write(" -> excluding(" + o.getName() + ")"); } serializeMetaClassExtensionAssertionFilter(true, bw, mm.getClassByName(className), selector.getFilter(), baseFragment); Quantifier q = selector.getQuantifier(); if (q instanceof Every) { bw.write(" -> size()"); if (!((Every) q).isNot()) bw.write(" = "); else bw.write(" > "); bw.write(className + ".allInstances() "); if (onlyNewElements) { List<MetaClass> subs = metaclass.getAllSubs(); //System.out.println("HERE: " + subs.size()); List<String> subNames = new ArrayList<String>(); for (MetaClass mc : subs) subNames.add(mc.getName()); subNames.add(metaclass.getName()); for (String classname : subNames) for (fragments.Object o : baseFragment.getObjects(classname)) bw.write(" -> excluding(" + o.getName() + ")"); } serializeMetaClassExtensionAssertionFilter(true, bw, mm.getClassByName(className), selector.getFilter(), baseFragment); serializeMetaClassExtensionAssertionFilter(true, bw, mm.getClassByName(className), ((MetaClassExtensionAssertion) ea).getCondition(), baseFragment); bw.write(" -> size()"); } else { int minmax[] = q.getQuantity(Integer.MAX_VALUE); int min = minmax[0]; int max = minmax[1]; serializeMetaClassExtensionAssertionFilter(true, bw, mm.getClassByName(className), ((MetaClassExtensionAssertion) ea).getCondition(), baseFragment); if (min == max) bw.write(" -> size() = " + min); else { bw.write("-> size() >= " + min); if (max < Integer.MAX_VALUE) bw.write(" and size() <= " + max); } } } private void serializeFragmentObjectExtensionAssertion(BufferedWriter bw, FragmentObjectExtensionAssertion ea, Fragment baseFragment) throws IOException { FragmentObjectSelector fos = ((FragmentObjectExtensionAssertion) ea).getSelector(); String className = fos.getObject().getType(); if (mm.getClassByName(className) == null) { // Class not found. Report error return; } bw.write("\n"); serializeFragmentObjectExtensionAssertionFilter(bw, fos.getObject(), ((FragmentObjectExtensionAssertion) ea).getCondition(), baseFragment); } private void serializeFragmentObjectExtensionAssertionFilter(BufferedWriter bw, fragments.Object object, FragmentObjectQualifier filter, Fragment baseFragment) throws IOException { MetaClass metaclass = mm.getClassByName(object.getType()); if (filter instanceof AndQualifier) { boolean firstAnd = true; bw.write("("); for (Qualifier mcq : ((AndQualifier) filter).getQualifiers()) { if (firstAnd) firstAnd = false; else bw.write(" and "); serializeFragmentObjectExtensionAssertionFilter(bw, object, (FragmentObjectQualifier) mcq, baseFragment); } bw.write(")"); return; } if (filter instanceof OrQualifier) { boolean firstOr = true; bw.write("("); for (Qualifier mcq : ((OrQualifier) filter).getQualifiers()) { if (firstOr) firstOr = false; else bw.write(" or "); serializeFragmentObjectExtensionAssertionFilter(bw, object, (FragmentObjectQualifier) mcq, baseFragment); } bw.write(")"); return; } if (filter instanceof AttributeValue) { AttributeValue av = (AttributeValue) filter; if (metaclass.getAttributes() == null) { // Attribute not found. Report error return; } bw.write(object.getName() + "." + av.getAttributeName() + " = " + av.getValueAsString()); return; } if (filter instanceof Reach) { Reach reach = (Reach) filter; Selector sel = reach.getReachSelector(); if (sel instanceof MetaClassSelector) { MetaClassSelector mcs = (MetaClassSelector) sel; boolean onlyNewElements = mcs.isOnlyNewElements(); String tgtclassName = mcs.getMetaclassName(); if (mm.getClassByName(tgtclassName) == null) { // Class not found. Report error return; } Quantifier q = mcs.getQuantifier(); int minmax[] = q.getQuantity(Integer.MAX_VALUE); int min = minmax[0]; int max = minmax[1]; // find the reference(s) which point to the target metaclass(es) List<Reference> refs = new ArrayList<Reference>(); int refSort = ReferenceImpl.IRRELEVANT; if (filter instanceof Contains) refSort = ReferenceImpl.CONTAINMENT; if (((Reach) filter).getRefName() == null) { for (Reference r : metaclass.getReferences(true, refSort)) if (r.getReference().getName().equals(tgtclassName)) refs.add(r); } else refs.add(metaclass.getReferenceByName(((Reach) filter).getRefName(), true)); if (refs.isEmpty()) { // reference not found return; } // no more filters if (mcs.getFilter() == null) { boolean firstOr = true; bw.write("("); for (Reference r : refs) { if (firstOr) firstOr = false; else bw.write(" or "); bw.write(object.getName() + "." + r.getName() + "-> asSet()"); if (onlyNewElements) { for (fragments.Object o : baseFragment.getObjects(tgtclassName)) bw.write(" -> excluding(" + o.getName() + ")"); MetaClass tarClass = ((MetaModel) metaclass.eContainer()).getClassByName(tgtclassName); List<MetaClass> subs = tarClass.getAllSubs(); List<String> subNames = new ArrayList<String>(); for (MetaClass mc : subs) subNames.add(mc.getName()); for (String classname : subNames) for (fragments.Object o : baseFragment.getObjects(classname)) bw.write(" -> excluding(" + o.getName() + ")"); } if (min == max) bw.write("-> size() = " + min); else { bw.write("-> size() >= " + min); if (max < Integer.MAX_VALUE) { bw.write(" and " + r.getName() + "-> asSet()"); if (onlyNewElements) { for (fragments.Object o : baseFragment.getObjects(tgtclassName)) bw.write(" -> excluding(" + o.getName() + ")"); MetaClass tarClass = ((MetaModel) metaclass.eContainer()) .getClassByName(tgtclassName); List<MetaClass> subs = tarClass.getAllSubs(); List<String> subNames = new ArrayList<String>(); for (MetaClass mc : subs) subNames.add(mc.getName()); for (String classname : subNames) for (fragments.Object o : baseFragment.getObjects(classname)) bw.write(" -> excluding(" + o.getName() + ")"); } bw.write(" -> size() <= " + max); } } } bw.write(")"); } else { boolean firstOr = true; bw.write("("); for (Reference r : refs) { if (firstOr) firstOr = false; else bw.write(" or "); bw.write(object.getName() + "." + r.getName() + " -> asSet()"); if (onlyNewElements) { for (fragments.Object o : baseFragment.getObjects(tgtclassName)) bw.write(" -> excluding(" + o.getName() + ")"); MetaClass tarClass = ((MetaModel) metaclass.eContainer()).getClassByName(tgtclassName); List<MetaClass> subs = tarClass.getAllSubs(); List<String> subNames = new ArrayList<String>(); for (MetaClass mc : subs) subNames.add(mc.getName()); for (String classname : subNames) for (fragments.Object o : baseFragment.getObjects(classname)) bw.write(" -> excluding(" + o.getName() + ")"); } serializeMetaClassExtensionAssertionFilter(true, bw, mm.getClassByName(tgtclassName), mcs.getFilter(), baseFragment); if (min == max) bw.write("-> size() = " + min); else { bw.write("-> size() >= " + min); if (max < Integer.MAX_VALUE) { bw.write(" and " + r.getName() + " -> asSet()"); if (onlyNewElements) { for (fragments.Object o : baseFragment.getObjects(tgtclassName)) bw.write(" -> excluding(" + o.getName() + ")"); } bw.write(" -> size() <= " + max); } } } bw.write(")"); } } if (sel instanceof FragmentObjectSelector) { FragmentObjectSelector fos = (FragmentObjectSelector) sel; //bw.write(" -> select(" + fos.getObject().getName() + ")"); List<Reference> refs = new ArrayList<Reference>(); int refSort = ReferenceImpl.IRRELEVANT; if (filter instanceof Contains) refSort = ReferenceImpl.CONTAINMENT; if (((Reach) filter).getRefName() == null) { for (Reference r : metaclass.getReferences(true, refSort)) { MetaClass tarClass = ((MetaModel) metaclass.eContainer()) .getClassByName(r.getReference().getName()); List<MetaClass> subs = tarClass.getAllSubs(); List<String> subNames = new ArrayList<String>(); for (MetaClass mc : subs) subNames.add(mc.getName()); if (r.getReference().getName().equals(fos.getObject().getType()) || subNames.contains(fos.getObject().getType())) refs.add(r); } } else refs.add(metaclass.getReferenceByName(((Reach) filter).getRefName(), true)); if (refs.isEmpty()) { // reference not found return; } //System.out.println("... and I get here"); boolean firstOr = true; bw.write("("); for (Reference r : refs) { if (firstOr) firstOr = false; else bw.write(" or "); bw.write(object.getName() + "." + r.getName() + "-> asSet()"); bw.write(" -> includes(" + fos.getObject().getName() + ")"); } bw.write(")"); } } } private void serializeMetaClassExtensionAssertionFilter(boolean start, BufferedWriter bw, MetaClass metaclass, MetaClassQualifier filter, Fragment baseFragment) throws IOException { if (filter instanceof AndQualifier) { for (Qualifier mcq : ((AndQualifier) filter).getQualifiers()) serializeMetaClassExtensionAssertionFilter(true, bw, metaclass, (MetaClassQualifier) mcq, baseFragment); return; } if (filter instanceof OrQualifier) { bw.write(" -> select("); boolean firstOr = true; for (Qualifier mcq : ((OrQualifier) filter).getQualifiers()) { if (firstOr) firstOr = false; else bw.write(" or "); serializeMetaClassExtensionAssertionFilter(false, bw, metaclass, (MetaClassQualifier) mcq, baseFragment); } bw.write(")"); return; } if (filter instanceof AttributeValue) { AttributeValue av = (AttributeValue) filter; if (metaclass.getAttributes() == null) { // Attribute not found. Report error return; } /*if(av.getBooleanValue() != null){ if(av.getBooleanValue().equals("true")) bw.write("-> select(" + av.getAttributeName() + ") "); else bw.write("-> select(not " + av.getAttributeName() + ") "); }else*/ if (start) bw.write("-> select("); bw.write(av.getAttributeName() + " = " + av.getValueAsString()); if (start) bw.write(") "); return; } if (filter instanceof Reach) { Reach reach = (Reach) filter; Selector sel = reach.getReachSelector(); if (sel instanceof MetaClassSelector) { MetaClassSelector mcs = (MetaClassSelector) sel; boolean onlyNewElements = mcs.isOnlyNewElements(); String tgtclassName = mcs.getMetaclassName(); if (mm.getClassByName(tgtclassName) == null) { // Class not found. Report error return; } Quantifier q = mcs.getQuantifier(); int minmax[] = q.getQuantity(Integer.MAX_VALUE); int min = minmax[0]; int max = minmax[1]; // find the reference(s) which point to the target metaclass(es) List<Reference> refs = new ArrayList<Reference>(); int refSort = ReferenceImpl.IRRELEVANT; if (filter instanceof Contains) refSort = ReferenceImpl.CONTAINMENT; if (((Reach) filter).getRefName() == null) { for (Reference r : metaclass.getReferences(true, refSort)) { MetaClass tarClass = ((MetaModel) metaclass.eContainer()) .getClassByName(r.getReference().getName()); List<MetaClass> subs = tarClass.getAllSubs(); List<String> subNames = new ArrayList<String>(); for (MetaClass mc : subs) subNames.add(mc.getName()); if (r.getReference().getName().equals(tgtclassName) || subNames.contains(tgtclassName)) refs.add(r); } } else refs.add(metaclass.getReferenceByName(((Reach) filter).getRefName(), true)); if (refs.isEmpty()) { // reference not found return; } // no more filters if (mcs.getFilter() == null) { if (start) bw.write("-> select("); boolean firstOr = true; for (Reference r : refs) { if (firstOr) firstOr = false; else bw.write(" -> union "); bw.write("(" + r.getName() + "-> asSet() "); if (onlyNewElements) { for (fragments.Object o : baseFragment.getObjects(tgtclassName)) bw.write(" -> excluding(" + o.getName() + ")"); } bw.write(")"); } bw.write(" -> select(oclIsKindOf(" + tgtclassName + "))"); if (min == max) bw.write("-> size() = " + min); else { bw.write("-> size() >= " + min); if (max < Integer.MAX_VALUE) { bw.write(" and "); for (Reference r : refs) { if (firstOr) firstOr = false; else bw.write(" -> union "); bw.write("(" + r.getName() + "-> asSet() "); if (onlyNewElements) { for (fragments.Object o : baseFragment.getObjects(tgtclassName)) bw.write(" -> excluding(" + o.getName() + ")"); } bw.write(")"); } bw.write(" -> select(oclIsKindOf(" + tgtclassName + "))"); bw.write(" -> size() <= " + max); } } if (start) bw.write(") "); } else { if (start) bw.write("-> select("); boolean firstOr = true; for (Reference r : refs) { if (firstOr) firstOr = false; else bw.write(" or "); bw.write("(" + r.getName() + " -> asSet()"); if (onlyNewElements) { for (fragments.Object o : baseFragment.getObjects(tgtclassName)) bw.write(" -> excluding(" + o.getName() + ")"); } serializeMetaClassExtensionAssertionFilter(true, bw, mm.getClassByName(tgtclassName), mcs.getFilter(), baseFragment); if (min == max) bw.write("-> size() = " + min); else { bw.write("-> size() >= " + min); if (max < Integer.MAX_VALUE) { bw.write(" and " + r.getName() + " -> asSet()"); if (onlyNewElements) { for (fragments.Object o : baseFragment.getObjects(tgtclassName)) bw.write(" -> excluding(" + o.getName() + ")"); } bw.write(" -> size() <= " + max); } } bw.write(")"); } if (start) bw.write(") "); } } if (sel instanceof FragmentObjectSelector) { System.out.println("be here"); FragmentObjectSelector fos = (FragmentObjectSelector) sel; //bw.write(" -> select(" + fos.getObject().getName() + ")"); List<Reference> refs = new ArrayList<Reference>(); int refSort = ReferenceImpl.IRRELEVANT; if (filter instanceof Contains) refSort = ReferenceImpl.CONTAINMENT; if (((Reach) filter).getRefName() == null) { for (Reference r : metaclass.getReferences(true, refSort)) { if (r.getReference().getName().equals(fos.getObject().getType())) refs.add(r); else { MetaClass tarClass = ((MetaModel) metaclass.eContainer()) .getClassByName(r.getReference().getName()); List<MetaClass> subs = tarClass.getAllSubs(); List<String> subNames = new ArrayList<String>(); for (MetaClass mc : subs) subNames.add(mc.getName()); if (subNames.contains(fos.getObject().getType())) refs.add(r); } } } else refs.add(metaclass.getReferenceByName(((Reach) filter).getRefName(), true)); if (refs.isEmpty()) { // reference not found return; } if (start) bw.write("-> select("); boolean firstOr = true; for (Reference r : refs) { if (firstOr) firstOr = false; else bw.write(" -> union "); bw.write("(" + r.getName() + "-> asSet())"); } if (start) bw.write(") "); bw.write(" -> select(o | o =" + fos.getObject().getName() + ")"); } } } private void serializeClassContainmentConstraints(BufferedWriter bw, List<MetaClass> mcs) throws IOException { for (MetaClass mc : mcs) for (Reference r : mc.getReferences(false, ReferenceImpl.CONTAINMENT)) bw.write(selfCompositionConstraint(r)); List<Reference> conts = new ArrayList<Reference>(); for (MetaClass mc : mcs) for (Reference r : mc.getReferences(false, ReferenceImpl.CONTAINMENT)) conts.add(r); System.out.println("here!!! " + conts.size()); bw.write(simultaneousCompositionConstraint(conts)); } // constraint: an object cannot be contained itself through a composition relation, directly or indirectly // [NOTE: we do this because the USE Validator does not take into account the semantics of composition] private String selfCompositionConstraint(Reference ref) { String constraint = ""; MetaClass container = (MetaClass) ref.eContainer(); MetaClass containee = ref.getReference(); if (ref != null && ref.isAnnotated(Composition.NAME) && (container.equals(containee) || container.getSupers().contains(containee))) { List<String> terms = new ArrayList<String>(); int num_terms = 4; String type = container.getName(); String setOpen = ref.getMax() == 1 ? "Set{" : ""; // add monovalued features to a set String setClose = ref.getMax() == 1 ? "}" : ""; for (int term = 1; term <= num_terms; term++) { String expression = ""; for (int index = 1; index <= term; index++) { if (index == 1) { expression = setOpen + (index < term ? ref.getName() + index : "self") + ".oclAsType(" + type + ")." + ref.getName() + setClose + "->includes(self)"; } else { String select1 = "", select2 = ""; if (index > 1) { select1 = setOpen + (index < term ? ref.getName() + index : "self") + ".oclAsType(" + type + ")." + ref.getName() + setClose + "->exists(" + ref.getName() + (index - 1) + " |\n"; select2 = ")"; } expression = select1 + "if " + ref.getName() + (index - 1) + ".oclIsTypeOf(" + type + ") then\n" + "\t" + expression + "\n" + "\t else false endif" + select2; } } terms.add("not " + expression); } constraint = "\n\ncontext " + container.getName() + " inv non_contains_itself_" + ref.getName() + ":\n"; for (String term : terms) constraint += term + "\nand\n"; constraint = constraint.substring(0, constraint.lastIndexOf("and")) + "\n"; } return constraint; } // constraint: an object cannot be contained in two containers // [NOTE: we do this because the USE Validator does not take into account the semantics of composition] private String simultaneousCompositionConstraint(List<Reference> references) { String constraints = ""; // obtain the containment references that can contain each class Hashtable<String, List<Reference>> containers = new Hashtable<String, List<Reference>>(); for (Reference ref : references) { if (ref.isAnnotated(Composition.NAME)) { String classname = ref.getReference().getName(); if (!containers.containsKey(classname)) containers.put(classname, new ArrayList<Reference>()); containers.get(classname).add(ref); } if (ref.getOpposite() != null && ref.getOpposite().isAnnotated(Composition.NAME)) { String classname = ref.getOpposite().getReference().getName(); if (!containers.containsKey(classname)) containers.put(classname, new ArrayList<Reference>()); containers.get(classname).add(ref.getOpposite()); } } // if a class can potentially be in more than two containers, add a constraint for (Entry<String, List<Reference>> entry : containers.entrySet()) { if (entry.getValue().size() > 1) { constraints += "\n\ncontext " + entry.getKey() + "\n\tinv single_container: "; constraints += "\n"; for (Reference ref : entry.getValue()) constraints += "\t" + ((MetaClass) ref.eContainer()).getName() + ".allInstances()->collect(o | o." + ref.getName() + ")->count(self) +\n"; constraints = constraints.substring(0, constraints.lastIndexOf("+")) + "<= 1"; } } if (!constraints.isEmpty()) constraints += "\n"; return constraints; } private void serializeClass(BufferedWriter bw, MetaClass mc) throws IOException { bw.write("\n\n"); if (mc.getIsAbstract()) bw.write("abstract "); bw.write("class "); bw.write(getNameSwitch(mc.getName())); if (mc.getSupers() != null && !mc.getSupers().isEmpty()) { bw.write(" < "); for (int i = 0; i < mc.getSupers().size(); i++) { bw.write(getNameSwitch(mc.getSupers().get(i).getName())); if (i < mc.getSupers().size() - 1) bw.write(" , "); } } serializeClassAttributes(bw, mc); /*if(mc.getAnnotations() != null && !mc.getAnnotations().isEmpty()){ try { serializeElementConstraints(bw, mc); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } }*/ bw.write("\nend"); } private void serializeElementConstraints(BufferedWriter bw, AnnotatedElement ae) throws IOException, InstantiationException, IllegalAccessException { for (Annotation a : ae.getAnnotations()) { Class<? extends IConstraintAnnotation> annotationClass = af.getConstraintAnnotation(a.getName()); if (annotationClass != null) { System.out.println("annotation to serialize: " + a.getName()); IConstraintAnnotation annotation = annotationClass.newInstance(); annotation.setElement(ae); Iterator it = annotation.getConstraints().entrySet().iterator(); while (it.hasNext()) { Map.Entry e = (Map.Entry) it.next(); //if(!constraint.startsWith("context")) constraint = "context " + mc.getName() + " " + constraint; bw.write("\n\n"); bw.write(e.getValue().toString()); System.out.println(e.getValue().toString()); } } } } private void serializeClassAttributes(BufferedWriter bw, MetaClass mc) throws IOException { if (!mc.getAttributes().isEmpty()) bw.write("\n\tattributes"); List<String> atts = new ArrayList<String>(); for (Attribute a : mc.getAttributes()) { if (!atts.contains(a.getName())) { // repeated attributes are removed bw.write("\n\t\t" + getNameSwitch(a.getName())); bw.write(" : "); if (a.getPrimitiveType().equals("StringType")) bw.write("String"); else if (a.getPrimitiveType().equals("IntType")) bw.write("Integer"); else if (a.getPrimitiveType().equals("BooleanType")) bw.write("Boolean"); else bw.write("String"); atts.add(a.getName()); } } } private void serializeClassReferences(BufferedWriter bw, MetaClass mc, int refSort) throws IOException { List<Reference> refs = mc.getReferences(false, refSort); for (Reference r : refs) { System.out.println(serialized); if (serialized.contains(r)) continue; //System.out.println(r.getName() + " annotated: " + r.getAnnotations()); if (r.isAnnotated(Composition.NAME)) bw.write("\n\ncomposition "); else bw.write("\n\nassociation "); String name = mc.getName() + "_" + r.getName(); Reference opp = null; if (r.isAnnotated("opposite")) { for (Annotation a : r.getAnnotations()) if (a.getName().equals("opposite")) for (AnnotationParam ap : a.getParams()) if (ap.getName().equals("opp")) { ElementValue ev = (ElementValue) ap.getValue(); opp = (Reference) ev.getValue(); break; } } //System.out.println("here"); if (opp != null) name += "_" + opp.getName(); bw.write(getNameSwitch(name)); bw.write(" between"); bw.write("\n\t" + getNameSwitch(mc.getName()) + "["); if (opp != null) { bw.write(Integer.toString(opp.getMin()) + ".."); if (opp.getMax() < 0) bw.write("*"); else bw.write(Integer.toString(opp.getMax())); } else bw.write("1..1"); bw.write("]"); if (opp != null) bw.write(" role " + getNameSwitch(opp.getName())); else bw.write(" role " + getNameSwitch(mc.getName()).toLowerCase() + "_" + getNameSwitch(r.getName())); bw.write( "\n\t" + getNameSwitch(r.getReference().getName()) + "[" + Integer.toString(r.getMin()) + ".."); if (r.getMax() < 0) bw.write("*"); else bw.write(Integer.toString(r.getMax())); bw.write("]" + " role " + getNameSwitch(r.getName())); bw.write("\nend"); serialized.add(r); if (opp != null) serialized.add(opp); } } private String getNameSwitch(String name) { if (isReserved(name)) { String fixedName = name + "_RESERVEDWORD"; nameSwitch.put(name, fixedName); return fixedName; } if (!StringUtils.isAlphanumeric(name)) { //if(name.equals("Co-author")) System.out.println("entering"); String fixedName = name; for (char c : name.toCharArray()) if (!Character.isLetterOrDigit(c) && c != '_') { //if(name.equals("Co-author")) System.out.println("true"); fixedName = fixedName.replaceAll(String.valueOf(c), "_NONALPHANUMERICCHAR_"); } //if(name.equals("Co-author")) System.out.println("here: " + fixedName); nameSwitch.put(name, fixedName); return fixedName; } nameSwitch.put(name, name); return name; } private boolean isReserved(String word) { for (String s : useWords) if (s.equals(word.toLowerCase())) return true; return false; } }