/******************************************************************************* * 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.henshin.tggeditor.actions.imports; import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Stack; import org.eclipse.emf.ecore.EAnnotation; 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.EModelElement; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EcoreFactory; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.impl.EClassImpl; import org.eclipse.emf.ecore.impl.EPackageImpl; import org.eclipse.emf.ecore.impl.EStructuralFeatureImpl; import org.eclipse.emf.ecore.impl.EcoreFactoryImpl; import org.eclipse.emf.ecore.util.BasicExtendedMetaData; import org.eclipse.emf.ecore.util.BasicExtendedMetaData.EClassifierExtendedMetaData; import org.eclipse.emf.ecore.util.BasicExtendedMetaData.EPackageExtendedMetaData; public class ReconstructingMetaData extends BasicExtendedMetaData { EPackage reconstructedPackage; public Map<Object, EStructuralFeature> getMap() { return map; } public void setReconstructedPackage(EPackage reconstructedPackage) { this.reconstructedPackage = reconstructedPackage; } public void setDocumentRoot(String documentRoot) { this.documentRoot = documentRoot; } private Stack<String> currentElement; public void setCurrentElement(Stack<String> currentElement) { this.currentElement = currentElement; } public void setMap(Map<Object, EStructuralFeature> map) { this.map = map; } String documentRoot = null; private Map<Object, EStructuralFeature> map; String contextURI; String xmlFile; String getDocumentRoot() { return documentRoot; } public EPackage getReconstructedPackage() { return reconstructedPackage; } public ReconstructingMetaData(String xmlFile,Stack<String> currentElement,Map<Object,EStructuralFeature> map) { this.currentElement= currentElement; this.map = map; this.xmlFile = xmlFile; } @Override public Collection<EPackage> demandedPackages() { // TODO Auto-generated method stub return Arrays.asList(reconstructedPackage); } @Override public EStructuralFeature getAttribute(EClass eClass, String namespace, String name) { System.out.println("get attr " + eClass.getName() + " queried " + name); EStructuralFeature feature = eClass .getEStructuralFeature(name.toLowerCase()); if (feature != null) return feature; return super.getAttribute(eClass, namespace, name); } @Override public EStructuralFeature getAttribute(String namespace, String name) { System.out.println("get attr : " + name); //map.clear(); return null; } @Override public EStructuralFeature getElement(EClass eClass, String namespace, String name) { System.out.println("getElement " + eClass.getName() + "." + name); EStructuralFeature feature = eClass .getEStructuralFeature(name.toLowerCase()); if (feature != null) return feature; return super.getElement(eClass, namespace, name); } @Override public EStructuralFeature getElement(String namespace, String name) { return null; } private boolean firstType = true; @Override public EClassifier getType(EPackage ePackage, String name) { System.out.println("getType " + name); EClassifier type = null; if (name.equals("")) return type = ePackage.getEClassifier("DocumentRoot"); if (ePackage == null || ePackage.equals(reconstructedPackage)){ type = reconstructedPackage.getEClassifier(name); } if (type != null) return type; for (EClassifier ec : ePackage.getEClassifiers()) { if (ec.getName().toLowerCase().equals(name.toLowerCase())){ type = ec; break; } } if (type == null) type = super.getType(ePackage, name); if (type != null) firstType = false; return type; } @Override public List<EStructuralFeature> getAllAttributes(EClass eClass) { // TODO Auto-generated method stub return super.getAllAttributes(eClass); } @Override public List<EStructuralFeature> getAllElements(EClass eClass) { return super.getAllElements(eClass); } /* * (non-Javadoc) * * @see org.eclipse.emf.ecore.util.BasicExtendedMetaData# * demandFeature(java.lang.String, java.lang.String, * boolean, boolean) */ @Override public EStructuralFeature demandFeature(String namespace, String name, boolean isElement, boolean isReference) { System.out.println("demanded Feature ns:" + namespace + " name:" + name + " isElement:" + isElement + " isRef:" + isReference); String origName = name; if (name.contains(":")){ name = name.substring(name.lastIndexOf(":")+1); } name = name.toLowerCase(); //name = name.substring(0, 1).toLowerCase() + name.substring(1); EStructuralFeature feat = super.demandFeature( namespace, name, isElement, isReference); feat.setDerived(false); feat.setTransient(false); feat.setVolatile(false); getDocumentRoot(reconstructedPackage) .getEStructuralFeatures().remove(feat); feat.setUpperBound(-1); // this.getExtendedMetaData(feat).setGroup(feat); if (!isReference) { feat.setEType(EcorePackage.Literals.ESTRING); EClass cont = (EClass) this.demandType(namespace, currentElement.elementAt(currentElement .size() - 1)); if (cont.getEStructuralFeature(name) == null) cont.getEStructuralFeatures().add(feat); else feat = cont.getEStructuralFeature(name); feat.setUpperBound(1); System.out.println("created feat " + name + " for " + cont.getName()); this.setAnnotation(feat, "name", origName); this.setAnnotation(feat, "kind", "attribute"); if (isElement) this.setAnnotation(feat, "namespace", "##targetNamespace"); } else if (isElement) { // getDocumentRoot(reconstructedPackage) if (currentElement.size() - 1 > 0) { String container = currentElement .elementAt(currentElement.size() - 2); EClass cont = (EClass) this.demandType( namespace, container); if (cont.getEStructuralFeature(name) == null) { EClassifier targetType = this.demandType( namespace, origName); if (targetType instanceof EDataType){ feat = EcoreFactory.eINSTANCE.createEAttribute(); feat.setDerived(false); feat.setTransient(false); feat.setVolatile(false); feat.setName(name); feat.setEType(targetType); cont.getEStructuralFeatures().add(feat); feat.setUpperBound(1); System.out.println("created feat " + name + " for " + cont.getName()); this.setAnnotation(feat, "name", origName); this.setAnnotation(feat, "kind", "element"); if (isElement) this.setAnnotation(feat, "namespace", "##targetNamespace"); return feat; } feat.setEType(targetType); feat.setUpperBound(-1); cont.getEStructuralFeatures().add(feat); } else { feat = cont.getEStructuralFeature(name); EClassifier targetType = this.demandType( namespace, origName); feat.setEType(targetType); feat.setUpperBound(-1); } this.setAnnotation(feat, "name", origName); this.setAnnotation(feat, "kind", "element"); this.setAnnotation(feat, "namespace", "##targetNamespace"); System.out.println("created feat " + name + " for " + cont.getName()); } else { String container = currentElement .elementAt(currentElement.size() - 1); this.setAnnotation(feat, "name", origName); this.setAnnotation(feat, "kind", "element"); this.setAnnotation(feat, "namespace", "##targetNamespace"); getDocumentRoot(reconstructedPackage) .getEStructuralFeatures().add(feat); EClassifier targetType = this.demandType( namespace, container); feat.setEType(targetType); } } if (isElement && isReference && feat instanceof EReference) { ((EReference) feat).setContainment(true); } return feat; } @Override public EPackage demandPackage(String namespace) { System.out.println("demanded Package " + namespace); if (namespace != null && contextURI == null) { contextURI = namespace; } else { namespace = contextURI; } if (namespace == null){ namespace = xmlFile.replaceAll("\\\\", "/"); contextURI = namespace; } if (reconstructedPackage != null) return reconstructedPackage; reconstructedPackage = (EPackageImpl) EcoreFactoryImpl.eINSTANCE .createEPackage(); reconstructedPackage.setName(namespace); reconstructedPackage.setNsPrefix("xml"); reconstructedPackage.setNsURI(LoadReconstructXMLForSource.generateReconstructedPackageURI(namespace)); // if (BASESCHEME.equals(namespace)) // EPackage.Registry.INSTANCE.put(null, // reconstructedPackage); EPackage.Registry.INSTANCE.put(reconstructedPackage.getNsURI(), reconstructedPackage); System.out.println("created Package " + reconstructedPackage.toString()); return reconstructedPackage; } @Override public String getName(EClassifier eClassifier) { String name = super.getName(eClassifier); if (name.endsWith("_._type")){ name = name.substring(0, name.length() - 7); } return name; } @Override public EClassifier demandType(String namespace, String name) { System.out.println("demanded Type " + namespace + " name:" + name); EClassifier classifier = getType(namespace, name); if (classifier != null) return classifier; if (name.contains(":")){ name = name.substring(name.indexOf(":")+1); } if (reconstructedPackage == null) reconstructedPackage = demandPackage(null); if (reconstructedPackage.getEClassifier(name) != null) return reconstructedPackage.getEClassifier(name); if (getDocumentRoot(reconstructedPackage) == null || firstType) { firstType = false; documentRoot = ""; if (getDocumentRoot(reconstructedPackage) ==null){ EClass documentRootEClass = EcoreFactory.eINSTANCE .createEClass(); // documentRootEClass.getESuperTypes().add( // XMLTypePackage.eINSTANCE // .getXMLTypeDocumentRoot()); documentRootEClass.setName("DocumentRoot"); reconstructedPackage.getEClassifiers().add( documentRootEClass); documentRoot = ""; setDocumentRoot(documentRootEClass); documentRoot = "DocumentRoot"; this.setAnnotation(documentRootEClass, "name", ""); this.setAnnotation(documentRootEClass, "kind", "mixed"); } EStructuralFeature ref = getElement(getDocumentRoot(reconstructedPackage), namespace, name); if (ref == null) ref = demandFeature(namespace, name, true, true); getDocumentRoot(reconstructedPackage).getEStructuralFeatures().add(ref); this.setAnnotation(ref, "name", name); EClassifier type = demandType(namespace, name); ref.setEType(type); return type; } EClassImpl eClass = (EClassImpl) EcoreFactoryImpl.eINSTANCE .createEClass(); eClass.setName(name); this.setAnnotation(eClass, "name", eClass.getName() + "_._type"); this.setAnnotation(eClass, "kind", "elementOnly"); reconstructedPackage.getEClassifiers().add(eClass); System.out.println("created Type " + eClass.toString()); EAttribute eAttribute = EcoreFactory.eINSTANCE .createEAttribute(); eAttribute.setName(LoadReconstructXMLForSource.MIXEDELEMENTFEATURE); eAttribute.setEType(EcorePackage.Literals.EFEATURE_MAP); eAttribute.setDerived(false); eAttribute.setTransient(true); eAttribute.setVolatile(false); eAttribute .setUpperBound(1); this.setAnnotation(eAttribute, "name", ":mixed"); this.setAnnotation(eAttribute, "kind", "elementWildcard"); eClass.getEStructuralFeatures().add(eAttribute); eAttribute = EcoreFactory.eINSTANCE.createEAttribute(); eAttribute.setName(LoadReconstructXMLForSource.XML_ELEMENT_TEXT); eAttribute.setEType(EcorePackage.Literals.ESTRING); eAttribute.setDerived(false); eAttribute.setTransient(false); eAttribute.setVolatile(false); eAttribute.setUpperBound(1); this.setAnnotation(eAttribute, "name", eAttribute.getName() + "_._type"); this.setAnnotation(eAttribute, "kind", "attribute"); eClass.getEStructuralFeatures().add(eAttribute); return eClass; } @Override public EStructuralFeature getAffiliation(EClass eClass, EStructuralFeature eStructuralFeature) { // TODO Auto-generated method stub return super.getAffiliation(eClass, eStructuralFeature); } @Override public EStructuralFeature getAffiliation( EStructuralFeature eStructuralFeature) { // TODO Auto-generated method stub return super.getAffiliation(eStructuralFeature); } @Override public EStructuralFeature getAttributeWildcardAffiliation( EClass eClass, String namespace, String name) { return super.getAttributeWildcardAffiliation(eClass, namespace, name); } @Override public EClass getDocumentRoot(EPackage ePackage) { EClassifier type = getExtendedMetaData(ePackage).getType(""); if (type != null) return (EClass) type; return (EClass) ePackage.getEClassifier(documentRoot); } @Override public EStructuralFeature getElementWildcardAffiliation( EClass eClass, String namespace, String name) { return super.getElementWildcardAffiliation(eClass, namespace, name); } @Override public EPackage getPackage(String namespace) { // TODO Auto-generated method stub if (reconstructedPackage != null && reconstructedPackage.getNsURI().equals( namespace)) return reconstructedPackage; if (reconstructedPackage != null && (namespace == null || namespace.isEmpty())) return reconstructedPackage; return super.getPackage(namespace); } @Override public EClassifier getType(String namespace, String name) { if (name.equals(documentRoot)) return super.getType(namespace, ""); return super.getType(namespace, name); } @Override public boolean isDocumentRoot(EClass eClass) { return "DocumentRoot".equals(getName(eClass)); } @Override public void setDocumentRoot(EClass eClass) { setName(eClass, documentRoot); setContentKind(eClass, MIXED_CONTENT); } private void setAnnotation(EModelElement eClassifier,String name,String value){ EAnnotation eAnnotation = getAnnotation(eClassifier, true); eAnnotation.getDetails().put(name, value); } public static void cleanExtendedMetaData(EPackage ePkg){ if (ePkg == null) return; for (EClassifier eClassifier : ePkg.getEClassifiers()) { EClassifierExtendedMetaData.Holder holder = (EClassifierExtendedMetaData.Holder)eClassifier; holder.setExtendedMetaData(null); for (EObject obj : eClassifier.eContents()) { if (obj instanceof EStructuralFeature){ EStructuralFeatureExtendedMetaData.Holder h = (EStructuralFeatureExtendedMetaData.Holder)obj; h.setExtendedMetaData(null); try { Field field = EStructuralFeatureImpl.class.getDeclaredField("settingDelegate"); boolean accessible = field.isAccessible(); field.setAccessible(true); field.set(obj, null); field.setAccessible(accessible); } catch (Exception ex){ } } } } EPackageExtendedMetaData.Holder holder = (EPackageExtendedMetaData.Holder)ePkg; holder.setExtendedMetaData(null); } }