/******************************************************************************* * Copyright (c) 2009, 2013 Borland Software 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: * Borland Software Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.m2m.internal.qvt.oml.ast.parser; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.ecore.EAnnotation; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EOperation; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.EcoreFactory; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.m2m.internal.qvt.oml.ast.env.IVirtualOperationTable; import org.eclipse.m2m.internal.qvt.oml.ast.env.VirtualTable; import org.eclipse.m2m.internal.qvt.oml.ast.env.VirtualTableAdapter; import org.eclipse.m2m.internal.qvt.oml.evaluator.ModuleInstanceFactory; import org.eclipse.m2m.internal.qvt.oml.expressions.Module; import org.eclipse.ocl.ecore.OperationCallExp; /** * This helper class solves the problem of serialization/deserialization of * executable QVTo XMI, with AST extensions like property init expressions. * * FIXME - consider elimination of some of the adapters and use only annotations * so we can stick to plain serialization. */ public class ExecutableXMIHelper { private static final String SOURCE_URI_BASE = QvtOperationalParserUtil.QVT_NAMESPACE_URI; private static final String VIRTUAL_TABLE_SOURCE = SOURCE_URI_BASE + "/VTable"; //$NON-NLS-1$ private static final String STATIC_SOURCE = SOURCE_URI_BASE + "/static"; //$NON-NLS-1$ private static final String OPERATION_CALL_SOURCE = SOURCE_URI_BASE + "/opCall"; //$NON-NLS-1$ private static final String OPERATION_CALL_DETAILS_OPCODE = "opCode"; //$NON-NLS-1$ public static void fixResourceOnLoad(Resource resource) { fixOnLoad(resource.getAllContents()); } public static void fixEObjectOnLoad(EObject eObj) { restoreEObjectOnLoad(eObj); fixOnLoad(eObj.eAllContents()); } private static void fixOnLoad(TreeIterator<EObject> it) { while(it.hasNext()) { EObject nextObj = it.next(); restoreEObjectOnLoad(nextObj); } } private static void restoreEObjectOnLoad(EObject eObj) { if(eObj instanceof Module) { Module module = (Module) eObj; if (false == module.getEFactoryInstance() instanceof ModuleInstanceFactory) { module.setEFactoryInstance(new ModuleInstanceFactory()); } } else if(eObj instanceof EOperation) { loadVTOperFromAnnotation((EOperation)eObj); } else if(eObj instanceof EPackage) { EPackage ePackage = (EPackage)eObj; if(IntermediateClassFactory.isIntermediatePackage(ePackage) && false == ePackage.getEFactoryInstance() instanceof IntermediateClassFactory) { new IntermediateClassFactory(ePackage); } } else if(eObj instanceof EStructuralFeature) { loadStaticFeatureFromAnnotation((EStructuralFeature) eObj); } else if(eObj instanceof OperationCallExp) { loadOperationCallDetails((OperationCallExp) eObj); } } public static void fixResourceOnSave(Resource rc) { fixOnSave(rc.getAllContents()); } public static void fixEObjectOnSave(EObject eObj) { prepareEObjectToSave(eObj); fixOnSave(eObj.eAllContents()); } private static void fixOnSave(TreeIterator<EObject> it) { while(it.hasNext()) { EObject nextObj = it.next(); prepareEObjectToSave(nextObj); } } private static void prepareEObjectToSave(EObject eObj) { if(eObj instanceof EOperation) { saveVTOperTable2Annotation((EOperation)eObj); } else if(eObj instanceof EStructuralFeature) { saveStaticFeature((EStructuralFeature) eObj); } else if(eObj instanceof OperationCallExp) { saveOperationCallDetails((OperationCallExp) eObj); } } private static void loadVTOperFromAnnotation(EOperation operation) { EAnnotation annotation = operation.getEAnnotation(VIRTUAL_TABLE_SOURCE); if(annotation != null) { VirtualTable vt = VirtualTableAdapter.getAdapter(operation, true).getVirtualTable(); for(EObject next : annotation.getReferences()) { if(next instanceof EOperation) { vt.addOperation((EOperation)next); } } } } private static void saveVTOperTable2Annotation(EOperation operation) { IVirtualOperationTable virtualTable = IVirtualOperationTable.Access.INSTANCE.getVirtualTable(operation); if(false == virtualTable instanceof VirtualTable) { return; } if(operation.getEAnnotation(VIRTUAL_TABLE_SOURCE) != null) { return; } EAnnotation annotation = EcoreFactory.eINSTANCE.createEAnnotation(); operation.getEAnnotations().add(annotation); annotation.setSource(VIRTUAL_TABLE_SOURCE); VirtualTable vt = (VirtualTable) virtualTable; for (EOperation next : vt.getOperations()) { annotation.getReferences().add(next); } } private static void saveStaticFeature(EStructuralFeature feature) { if (feature.getEAnnotation(STATIC_SOURCE) != null) { return; } if(IntermediateClassFactory.isFeatureStatic(feature)) { EAnnotation annotation = EcoreFactory.eINSTANCE.createEAnnotation(); annotation.setSource(STATIC_SOURCE); feature.getEAnnotations().add(annotation); } } private static void loadStaticFeatureFromAnnotation(EStructuralFeature feature) { EAnnotation annotation = feature.getEAnnotation(STATIC_SOURCE); if (annotation != null) { IntermediateClassFactory.markFeatureAsStatic(feature); } } private static void saveOperationCallDetails(OperationCallExp opCallExp) { if (opCallExp.getEAnnotation(OPERATION_CALL_SOURCE) != null) { return; } EAnnotation annotation = EcoreFactory.eINSTANCE.createEAnnotation(); annotation.setSource(OPERATION_CALL_SOURCE); opCallExp.getEAnnotations().add(annotation); annotation.getDetails().put(OPERATION_CALL_DETAILS_OPCODE, String.valueOf(opCallExp.getOperationCode())); } private static void loadOperationCallDetails(OperationCallExp opCallExp) { EAnnotation annotation = opCallExp.getEAnnotation(OPERATION_CALL_SOURCE); if (annotation == null) { return; } String opCodeString = annotation.getDetails().get(OPERATION_CALL_DETAILS_OPCODE); if (opCodeString == null) { return; } try { opCallExp.setOperationCode(Integer.valueOf(opCodeString)); } catch (NumberFormatException e) { } } }