/******************************************************************************* * Copyright (c) 2010-2015 Henshin developers. 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: * TU Berlin, University of Luxembourg, SES S.A. *******************************************************************************/ package de.tub.tfs.muvitor.ui.utils; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Writer; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.zip.ZipEntry; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.notify.NotificationChain; import org.eclipse.emf.common.util.BasicEList; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.TreeIterator; 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.EFactory; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.impl.EPackageRegistryImpl; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.URIConverter; import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.BinaryIO.Version; import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectInputStream; import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectOutputStream; import org.eclipse.emf.ecore.util.ExtendedMetaData; import org.eclipse.emf.ecore.xmi.DOMHandler; import org.eclipse.emf.ecore.xmi.DOMHelper; import org.eclipse.emf.ecore.xmi.XMIResource; import org.eclipse.emf.ecore.xmi.XMLHelper; import org.eclipse.emf.ecore.xmi.XMLLoad; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.emf.ecore.xmi.XMLSave; import org.eclipse.emf.ecore.xmi.impl.SAXXMIHandler; import org.eclipse.emf.ecore.xmi.impl.XMIHelperImpl; import org.eclipse.emf.ecore.xmi.impl.XMILoadImpl; import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl; import org.eclipse.emf.ecore.xmi.impl.XMISaveImpl; import org.eclipse.emf.ecore.xml.type.AnyType; import org.eclipse.swt.widgets.Display; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.helpers.DefaultHandler; public class EMFResource extends XMIResourceImpl { /** * */ private final EMFModelManager emfModelManager; private boolean loadTime = false;; EMFResource(EMFModelManager emfModelManager, URI uri) { super(uri); this.emfModelManager = emfModelManager; } @Override protected boolean useUUIDs() { return true; } @Override public void save(Map<?, ?> options) throws IOException { // TODO Auto-generated method stub FragmentResource fragmentResource = this.emfModelManager.requestFragmentResource(this); fragmentResource.getContents().clear(); try { super.save(options); } catch (Exception ex){ fragmentResource = this.emfModelManager.getFragmentResource(this); if (fragmentResource != null){ fragmentResource.save(null); fragmentResource.cleanUp(); } ex.printStackTrace(); throw new IOException(ex); } fragmentResource = this.emfModelManager.getFragmentResource(this); if (fragmentResource != null){ fragmentResource.save(null); fragmentResource.cleanUp(); } } @Override protected XMLHelper createXMLHelper() { return new XMIHelperImpl(this){ @Override public String getQName(EClass c) { if (EMFModelManager.replacedClasses.contains(c)){ for (EClass cl : c.getEAllSuperTypes()) { if (cl.getName().equals(EMFModelManager.replacedClassesToStringMap.get(c))) return super.getQName(cl); } } return super.getQName(c); } @Override public EClassifier getType(EFactory eFactory, String typeName) { if (eFactory != null) { EPackage ePackage = eFactory.getEPackage(); EAnnotation annotation = ePackage.getEAnnotation("EMFModelManager"); if (annotation != null){ String typeMapping = annotation.getDetails().get(typeName); if (typeMapping != null && !typeMapping.isEmpty()) typeName = typeMapping; } HashMap<String, EClassifier> map = EMFModelManager.conversionsClass.get(ePackage); if (map != null){ EClassifier cl = map.get(typeName); if (cl == null) { if (extendedMetaData != null) { return extendedMetaData.getType(ePackage, typeName); } else { return ePackage.getEClassifier(typeName); } } return cl; } if (extendedMetaData != null) { return extendedMetaData.getType(ePackage, typeName); } } return super.getType(eFactory, typeName); } }; } @Override public void load(Map options) throws IOException { loadTime = true; try { FragmentResource fragmentResource = this.emfModelManager.getFragmentResource(this); if (fragmentResource != null){ fragmentResource.cleanUp(); } options.put(XMLResource.OPTION_RECORD_UNKNOWN_FEATURE, Boolean.TRUE); super.load(options); XMIResource r = (XMIResource) this; if (!r.getEObjectToExtensionMap().isEmpty()){ for (Entry<EObject, AnyType> missingReference : r.getEObjectToExtensionMap().entrySet()) { if (!missingReference.getValue().getMixed().isEmpty()) System.err.println("Class " + missingReference.getKey().getClass().getName() + " is missing reference " + missingReference.getValue().getMixed().get(0).getEStructuralFeature().getName() ); else if (!missingReference.getValue().getAnyAttribute().isEmpty()) System.err.println("Class " + missingReference.getKey().getClass().getName() + " is missing attribute " + missingReference.getValue().getAnyAttribute().get(0).getEStructuralFeature().getName() ); else if (!missingReference.getValue().getAny().isEmpty()) System.err.println("Class " + missingReference.getKey().getClass().getName() + " is missing something " + missingReference.getValue().getAnyAttribute().get(0).getEStructuralFeature().getName() ); } } fragmentResource = this.emfModelManager.getFragmentResource(this); if (fragmentResource != null) fragmentResource.cleanUp(); } finally { loadTime = false; } } @Override protected XMLLoad createXMLLoad() { // TODO Auto-generated method stub return new XMILoadImpl(createXMLHelper()){ @Override protected DefaultHandler makeDefaultHandler() { return new SAXXMIHandler(resource, helper, options) { @Override protected void setFeatureValue( EObject object, EStructuralFeature feature, Object value, int position) { try { helper.setValue(object, feature, value, position); } catch (RuntimeException e) { System.out.println("skipped: " + object.eClass().getName() + "." + feature.getName() + "("+value+")"); //e.printStackTrace(); // ignore illegal values and skip //error //(new IllegalValueException // (object, // feature, // value, // e, // getLocation(), // getLineNumber(), // getColumnNumber())); } } @Override protected void handleProxy( InternalEObject proxy, String uriLiteral) { if (uriLiteral.contains("#")){ String name = uriLiteral.substring(uriLiteral.lastIndexOf("#")+2); String newname = name; String pkgUri = uriLiteral.substring(0,uriLiteral.lastIndexOf("#")); Object obj = EPackageRegistryImpl.INSTANCE.get(pkgUri); if (obj instanceof EPackage){ EPackage pkg = (EPackage) obj; EAnnotation annotation = pkg.getEAnnotation("EMFModelManager"); if (annotation != null){ String typeMapping = annotation.getDetails().get(name); if (typeMapping != null && !typeMapping.isEmpty()) newname = typeMapping; } uriLiteral = uriLiteral.replace(name, newname); } } super.handleProxy(proxy, uriLiteral); } @Override protected void processObject( EObject object) { super.processObject(object); if (object != null && EMFModelManager.replacedClasses.contains(object.eClass())){ EMFModelManager.loadDelegates.get(object.eClass()).doLoad(object); } if (EMFResource.this.emfModelManager.monitor != null){ int line = getLineNumber(); final int work = line - EMFResource.this.emfModelManager.lastLine; if (work < 20) return; EMFResource.this.emfModelManager.lastLine = line; Display.getDefault().asyncExec(new Runnable() { @Override public void run() { EMFResource.this.emfModelManager.monitor.worked(work); } }); if (EMFResource.this.emfModelManager.monitor.isCanceled()) throw new RuntimeException("Aborted by User!"); } } }; } }; } @Override protected XMLSave createXMLSave() { return new XMISaveImpl(createXMLHelper()){ private boolean checkForDelegates(EObject o,EStructuralFeature f){ if (EMFModelManager.replacedClasses.contains(o.eClass()) && o.eClass().getEStructuralFeatures().contains(f)){ boolean result = EMFModelManager.saveDelegates.get(o.eClass()).shouldSkipSave(o, f); return result; } return false; } @Override protected boolean saveFeatures(EObject o, boolean attributesOnly) { EClass eClass = o.eClass(); if (EMFModelManager.replacedClasses.contains(eClass)){ EMFResource.this.emfModelManager.requestFragmentResource(o.eResource()).getContents().add(o); } int contentKind = extendedMetaData == null ? ExtendedMetaData.UNSPECIFIED_CONTENT : extendedMetaData.getContentKind(eClass); if (!toDOM) { switch (contentKind) { case ExtendedMetaData.MIXED_CONTENT: case ExtendedMetaData.SIMPLE_CONTENT: { doc.setMixed(true); break; } } } if (o == root) { writeTopAttributes(root); } EStructuralFeature[] features = featureTable.getFeatures(eClass); int[] featureKinds = featureTable.getKinds(eClass, features); int[] elementFeatures = null; int elementCount = 0; String content = null; // Process XML attributes LOOP: for (int i = 0; i < features.length; i++ ) { int kind = featureKinds[i]; EStructuralFeature f = features[i]; if (checkForDelegates(o,features[i])){ continue; } if (kind != TRANSIENT && shouldSaveFeature(o, f)) { switch (kind) { case DATATYPE_ELEMENT_SINGLE: { if (contentKind == ExtendedMetaData.SIMPLE_CONTENT) { content = getDataTypeElementSingleSimple(o, f); continue LOOP; } break; } case DATATYPE_SINGLE: { saveDataTypeSingle(o, f); continue LOOP; } case DATATYPE_SINGLE_NILLABLE: { if (!isNil(o, f)) { saveDataTypeSingle(o, f); continue LOOP; } break; } case OBJECT_ATTRIBUTE_SINGLE: { saveEObjectSingle(o, f); continue LOOP; } case OBJECT_ATTRIBUTE_MANY: { saveEObjectMany(o, f); continue LOOP; } case OBJECT_ATTRIBUTE_IDREF_SINGLE: { saveIDRefSingle(o, f); continue LOOP; } case OBJECT_ATTRIBUTE_IDREF_MANY: { saveIDRefMany(o, f); continue LOOP; } case OBJECT_HREF_SINGLE_UNSETTABLE: { if (isNil(o, f)) { break; } // it's intentional to keep going } case OBJECT_HREF_SINGLE: { if (useEncodedAttributeStyle) { saveEObjectSingle(o, f); continue LOOP; } else { switch (sameDocSingle(o, f)) { case SAME_DOC: { saveIDRefSingle(o, f); continue LOOP; } case CROSS_DOC: { break; } default: { continue LOOP; } } } break; } case OBJECT_HREF_MANY_UNSETTABLE: { if (isEmpty(o, f)) { saveManyEmpty(o, f); continue LOOP; } // It's intentional to keep going. } case OBJECT_HREF_MANY: { if (useEncodedAttributeStyle) { saveEObjectMany(o, f); continue LOOP; } else { switch (sameDocMany(o, f)) { case SAME_DOC: { saveIDRefMany(o, f); continue LOOP; } case CROSS_DOC: { break; } default: { continue LOOP; } } } break; } case OBJECT_ELEMENT_SINGLE_UNSETTABLE: case OBJECT_ELEMENT_SINGLE: { if (contentKind == ExtendedMetaData.SIMPLE_CONTENT) { content = getElementReferenceSingleSimple(o, f); continue LOOP; } break; } case OBJECT_ELEMENT_MANY: { if (contentKind == ExtendedMetaData.SIMPLE_CONTENT) { content = getElementReferenceManySimple(o, f); continue LOOP; } break; } case OBJECT_ELEMENT_IDREF_SINGLE_UNSETTABLE: case OBJECT_ELEMENT_IDREF_SINGLE: { if (contentKind == ExtendedMetaData.SIMPLE_CONTENT) { content = getElementIDRefSingleSimple(o, f); continue LOOP; } break; } case OBJECT_ELEMENT_IDREF_MANY: { if (contentKind == ExtendedMetaData.SIMPLE_CONTENT) { content = getElementIDRefManySimple(o, f); continue LOOP; } break; } case DATATYPE_ATTRIBUTE_MANY: { break; } case OBJECT_CONTAIN_MANY_UNSETTABLE: case DATATYPE_MANY: { if (isEmpty(o, f)) { saveManyEmpty(o, f); continue LOOP; } break; } case OBJECT_CONTAIN_SINGLE_UNSETTABLE: case OBJECT_CONTAIN_SINGLE: case OBJECT_CONTAIN_MANY: case ELEMENT_FEATURE_MAP: { break; } case ATTRIBUTE_FEATURE_MAP: { saveAttributeFeatureMap(o, f); continue LOOP; } default: { continue LOOP; } } if (attributesOnly) { continue LOOP; } // We only get here if we should do this. // if (elementFeatures == null) { elementFeatures = new int[features.length]; } elementFeatures[elementCount++] = i; } } processAttributeExtensions(o); if (elementFeatures == null) { if (content == null) { content = getContent(o, features); } if (content == null) { if (o == root && writeTopElements(root)) { endSaveFeatures(o, 0, null); return true; } else { endSaveFeatures(o, EMPTY_ELEMENT, null); return false; } } else { endSaveFeatures(o, CONTENT_ELEMENT, content); return true; } } if (o == root) { writeTopElements(root); } // Process XML elements for (int i = 0; i < elementCount; i++ ) { int kind = featureKinds[elementFeatures[i]]; EStructuralFeature f = features[elementFeatures[i]]; if (checkForDelegates(o,f)) continue; switch (kind) { case DATATYPE_SINGLE_NILLABLE: { saveNil(o, f); break; } case ELEMENT_FEATURE_MAP: { saveElementFeatureMap(o, f); break; } case DATATYPE_MANY: { saveDataTypeMany(o, f); break; } case DATATYPE_ATTRIBUTE_MANY: { saveDataTypeAttributeMany(o, f); break; } case DATATYPE_ELEMENT_SINGLE: { saveDataTypeElementSingle(o, f); break; } case OBJECT_CONTAIN_SINGLE_UNSETTABLE: { if (isNil(o, f)) { saveNil(o, f); break; } // it's intentional to keep going } case OBJECT_CONTAIN_SINGLE: { saveContainedSingle(o, f); break; } case OBJECT_CONTAIN_MANY_UNSETTABLE: case OBJECT_CONTAIN_MANY: { saveContainedMany(o, f); break; } case OBJECT_HREF_SINGLE_UNSETTABLE: { if (isNil(o, f)) { saveNil(o, f); break; } // it's intentional to keep going } case OBJECT_HREF_SINGLE: { saveHRefSingle(o, f); break; } case OBJECT_HREF_MANY_UNSETTABLE: case OBJECT_HREF_MANY: { saveHRefMany(o, f); break; } case OBJECT_ELEMENT_SINGLE_UNSETTABLE: { if (isNil(o, f)) { saveNil(o, f); break; } // it's intentional to keep going } case OBJECT_ELEMENT_SINGLE: { saveElementReferenceSingle(o, f); break; } case OBJECT_ELEMENT_MANY: { saveElementReferenceMany(o, f); break; } case OBJECT_ELEMENT_IDREF_SINGLE_UNSETTABLE: { if (isNil(o, f)) { saveNil(o, f); break; } // it's intentional to keep going } case OBJECT_ELEMENT_IDREF_SINGLE: { saveElementIDRefSingle(o, f); break; } case OBJECT_ELEMENT_IDREF_MANY: { saveElementIDRefMany(o, f); break; } } } endSaveFeatures(o, 0, null); return true; } }; } @Override protected EObject getEObjectByID(String id) { if (loadTime){ if (idToEObjectMap != null) { EObject eObject = idToEObjectMap.get(id); if (eObject != null) { return eObject; } } Map<String, EObject> map = getIntrinsicIDToEObjectMap(); if (map != null) { EObject eObject = map.get(id); if (eObject != null) { return eObject; } } return null;// skip search for attribute feature as we are not using those for Henshin } else { return super.getEObjectByID(id); } // } }