/******************************************************************************* * Copyright (c) 2006-2012 * Software Technology Group, Dresden University of Technology * DevBoost GmbH, Berlin, Amtsgericht Charlottenburg, HRB 140026 * * 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: * Software Technology Group - TU Dresden, Germany; * DevBoost GmbH - Berlin, Germany * - initial API and implementation ******************************************************************************/ package org.reuseware.coconut.resource.sokan.indexer; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.reuseware.coconut.compositionprogram.CompositionProgram; import org.reuseware.coconut.compositionprogram.CompositionprogramPackage; import org.reuseware.coconut.compositionprogram.FragmentInstance; import org.reuseware.coconut.fracol.FracolPackage; import org.reuseware.coconut.resource.ReuseResources; import org.reuseware.coconut.resource.sokan.IndexConstants; import org.reuseware.coconut.resource.sokan.util.SokanReuseResourceUtil; import org.reuseware.coconut.resource.util.ReuseResourcesUtil; import org.reuseware.coconut.reuseextension.ComponentModelSpecification; import org.reuseware.coconut.reuseextension.CompositionLanguageSpecification; import org.reuseware.coconut.reuseextension.ReuseExtension; import org.reuseware.coconut.reuseextension.ReuseextensionPackage; import org.reuseware.coconut.reuseextension.RootElementContext; import org.reuseware.coconut.reuseextensionactivator.ComponentModelSpecificationActivator; import org.reuseware.coconut.reuseextensionactivator.CompositionLanguageSpecificationActivator; import org.reuseware.coconut.reuseextensionactivator.ReuseExtensionActivator; import org.reuseware.coconut.reuseextensionactivator.ReuseExtensionActivatorList; import org.reuseware.coconut.reuseextensionactivator.ReuseextensionactivatorPackage; import org.reuseware.sokan.ID; import org.reuseware.sokan.IndexMetaData; import org.reuseware.sokan.IndexRow; import org.reuseware.sokan.index.DependencyMap; import org.reuseware.sokan.index.indexer.DependencyIndexer; import org.reuseware.sokan.index.util.IndexUtil; import org.reuseware.sokan.index.util.ResourceUtil; /** * This indexer is responsible for calculating and persisting all dependencies * between reuse resources. The information indexed by this indexer is used * to calculate the updates required a reuse resource changes. * <p> * Index fields: <i>multiple</i>. */ public class ReuseResourceDependencyIndexer implements DependencyIndexer { /** * @param artifactURI the URI * @param metaData the meta data to fill * @param resourceSet the resource set to use */ public void createIndex(URI artifactURI, IndexMetaData metaData, ResourceSet resourceSet) { clearOldInfo(metaData, resourceSet); Resource resource = null; try { resource = resourceSet.getResource(artifactURI, true); } catch (Exception e) { //ok } if (resource == null || resource.getContents().isEmpty()) { return; } indexReuseExtension(resource, metaData, resourceSet); indexReuseExtensionActivator(resource, metaData, resourceSet); indexCompositionProgram(resource, metaData, resourceSet); } private void clearOldInfo(IndexMetaData metaData, ResourceSet resourceSet) { metaData.putSingle(IndexConstants.COLUMN_CM_IMPLEMENTED_FRAGMENT_COLLABORATION, null); metaData.getMulti(IndexConstants.COLUMN_CM_EXTENDED_ROOT_ECLASS).clear(); metaData.putSingle(IndexConstants.COLUMN_CL_IMPLEMENTED_FRAGMENT_COLLABORATION, null); metaData.getMulti(IndexConstants.COLUMN_CL_EXTENDED_ROOT_ECLASS).clear(); metaData.getMulti(IndexConstants.COLUMN_CM_ACTIVATED_REUSE_EXTENSION).clear(); metaData.getMulti(IndexConstants.COLUMN_CL_ACTIVATED_REUSE_EXTENSION).clear(); metaData.getMulti(IndexConstants.COLUMN_INSTANTIATED_FRAGMENT).clear(); emptyOldCompositionProgramTargetsOfDerivedCPs(metaData, resourceSet); emptyOldCompositionProgramTargets(metaData, resourceSet); emptyOldDerivedCompositionPrograms(metaData, resourceSet); metaData.getMulti(IndexConstants.COLUMN_COMPOSED_FRAGMENT).clear(); metaData.getMulti(IndexConstants.COLUMN_DERIVED_COMPOSITION_PROGRAM).clear(); } private void emptyOldDerivedCompositionPrograms(IndexMetaData metaData, ResourceSet resourceSet) { for (String oldDerivedUCPI : metaData.getMulti(IndexConstants.COLUMN_DERIVED_COMPOSITION_PROGRAM)) { URI uri = ResourceUtil.uriFrom(ResourceUtil.idFrom(oldDerivedUCPI)); if (uri != null) { Resource oldDerivedCPResource = null; try { oldDerivedCPResource = resourceSet.getResource(uri, true); } catch (Exception e) { //ok } if (oldDerivedCPResource == null) { continue; } oldDerivedCPResource.getContents().clear(); oldDerivedCPResource.setModified(true); } } } private void emptyOldCompositionProgramTargetsOfDerivedCPs(IndexMetaData metaData, ResourceSet resourceSet) { for (String oldUCPI : metaData.getMulti(IndexConstants.COLUMN_DERIVED_COMPOSITION_PROGRAM)) { IndexRow row = IndexUtil.INSTANCE.getIndex(ResourceUtil.idFrom(oldUCPI)); if (row != null) { IndexMetaData cpMetaData = row.getMetaData(); emptyOldCompositionProgramTargets(cpMetaData, resourceSet); } } } private void emptyOldCompositionProgramTargets(IndexMetaData metaData, ResourceSet resourceSet) { for (String oldTargetUFI : metaData.getMulti(IndexConstants.COLUMN_COMPOSED_FRAGMENT)) { URI uri = ResourceUtil.uriFrom(ResourceUtil.idFrom(oldTargetUFI)); if (uri != null) { Resource oldTargetResource = null; try { oldTargetResource = resourceSet.getResource(uri, true); } catch (Exception e) { //ok } if (oldTargetResource == null) { continue; } oldTargetResource.getContents().clear(); oldTargetResource.setModified(true); for (URI oldDiagramURI : ReuseResources.INSTANCE.getDiagramURIs( ResourceUtil.idFrom(oldTargetUFI).getSegments())) { Resource oldDiagramResource = null; try { oldDiagramResource = resourceSet.getResource(oldDiagramURI, true); } catch (Exception e) { //ok } if (oldDiagramResource != null) { oldDiagramResource.getContents().clear(); oldDiagramResource.setModified(true); } } } } } private void indexReuseExtension(Resource resource, IndexMetaData metaData, ResourceSet resourceSet) { if (!(resource.getContents().get(0) instanceof ReuseExtension)) { return; } ReuseExtension rex = (ReuseExtension) resource.getContents().get(0); if (rex == null) { return; } if (rex.getFracol() == null) { return; } String fracolIDString = null; if (rex.getFracol().eIsProxy()) { String fracolName = getNameFromProxy(rex.getFracol()); List<String> id = new ArrayList<String>(); id.addAll(rex.getFracolNamespace()); id.add(fracolName + ".fracol"); fracolIDString = ResourceUtil.idString(id); } else { fracolIDString = ResourceUtil.idString( ResourceUtil.idFrom(rex.getFracol().eResource().getURI())); } Set<String> eClassIDs = new TreeSet<String>(); createEClassIDs(rex, eClassIDs); if (rex instanceof ComponentModelSpecification) { metaData.putSingle( IndexConstants.COLUMN_CM_IMPLEMENTED_FRAGMENT_COLLABORATION, fracolIDString); metaData.putMultiple( IndexConstants.COLUMN_CM_EXTENDED_ROOT_ECLASS, new ArrayList<String>(eClassIDs)); } else if (rex instanceof CompositionLanguageSpecification) { metaData.putSingle( IndexConstants.COLUMN_CL_IMPLEMENTED_FRAGMENT_COLLABORATION, fracolIDString); metaData.putMultiple( IndexConstants.COLUMN_CL_EXTENDED_ROOT_ECLASS, new ArrayList<String>(eClassIDs)); } } private void indexReuseExtensionActivator(Resource resource, IndexMetaData metaData, ResourceSet resourceSet) { if (!(resource.getContents().get(0) instanceof ReuseExtensionActivatorList)) { return; } ReuseExtensionActivatorList reuseExtensionActivatorList = (ReuseExtensionActivatorList) resource.getContents().get(0); List<String> cmRexIDs = new ArrayList<String>(); List<String> clRexIDs = new ArrayList<String>(); for (ReuseExtensionActivator activator : reuseExtensionActivatorList.getActivators()) { ReuseExtension rex = activator.getReuseExtension(); if (rex == null) { continue; } if (rex.eIsProxy()) { String rexName = getNameFromProxy(rex); List<String> id = new ArrayList<String>(); id.addAll(rex.getRexNamespace()); id.add(rexName + ".rex"); if (activator instanceof ComponentModelSpecificationActivator) { cmRexIDs.add(ResourceUtil.idString(id)); } else if (activator instanceof CompositionLanguageSpecificationActivator) { clRexIDs.add(ResourceUtil.idString(id)); } } else { if (rex instanceof ComponentModelSpecification) { cmRexIDs.add( ResourceUtil.idString(ResourceUtil.idFrom(rex.eResource().getURI()))); } if (rex instanceof CompositionLanguageSpecification) { clRexIDs.add( ResourceUtil.idString(ResourceUtil.idFrom(rex.eResource().getURI()))); } } } metaData.putMultiple( IndexConstants.COLUMN_CM_ACTIVATED_REUSE_EXTENSION, cmRexIDs); metaData.putMultiple( IndexConstants.COLUMN_CL_ACTIVATED_REUSE_EXTENSION, clRexIDs); } private void indexCompositionProgram(Resource resource, IndexMetaData metaData, ResourceSet resourceSet) { if (!(resource.getContents().get(0) instanceof CompositionProgram)) { return; } CompositionProgram compositionProgram = (CompositionProgram) resource.getContents().get(0); for (FragmentInstance fi : compositionProgram.getFragmentInstances()) { metaData.putMultiple( IndexConstants.COLUMN_INSTANTIATED_FRAGMENT, ResourceUtil.idString(fi.getUFI())); if (fi.isTarget()) { metaData.putMultiple( IndexConstants.COLUMN_COMPOSED_FRAGMENT, ResourceUtil.idString(fi.getTargetUFI())); } } } private void createEClassIDs(ReuseExtension rex, Set<String> eClassIDs) { for (RootElementContext rootContext : rex.getRootElementContexts()) { if (rootContext.getEBoundClass() == null) { continue; } eClassIDs.add(SokanReuseResourceUtil.eClassToString(rootContext.getEBoundClass())); } } /** * Dependent of the type of artifact this method calls one of * the ReuseResourcesUtil.*Changed() methods to calculate * the impact of the change on other artifacts. * * @param artifactID the artifact's ID * @param depMap the dependency map to fill */ public void getDependent(ID artifactID, DependencyMap depMap) { IndexRow row = IndexUtil.INSTANCE.getIndex(artifactID); if (isOfType(row, CompositionprogramPackage.Literals.COMPOSITION_PROGRAM)) { SokanReuseResourceUtil.processDirtyIDs(ReuseResourcesUtil.compositionProgramChanged(artifactID.getSegments()), depMap); } else if (isOfType(row, FracolPackage.Literals.FRAGMENT_COLLABORATION)) { SokanReuseResourceUtil.processDirtyIDs(ReuseResourcesUtil.fragmentCollaborationChanged(artifactID.getSegments()), depMap); } else if (isOfType(row, ReuseextensionPackage.Literals.COMPONENT_MODEL_SPECIFICATION)) { SokanReuseResourceUtil.processDirtyIDs(ReuseResourcesUtil.componentModelSpecChanged(artifactID.getSegments()), depMap); } else if (isOfType(row, ReuseextensionPackage.Literals.COMPOSITION_LANGUAGE_SPECIFICATION)) { SokanReuseResourceUtil.processDirtyIDs(ReuseResourcesUtil.compositionLanguageSpecChanged(artifactID.getSegments()), depMap); } else if (isOfType(row, ReuseextensionactivatorPackage.Literals.REUSE_EXTENSION_ACTIVATOR_LIST)) { SokanReuseResourceUtil.processDirtyIDs(ReuseResourcesUtil.reuseExtensionActivatorChanged(artifactID.getSegments()), depMap); } SokanReuseResourceUtil.processDirtyIDs(ReuseResourcesUtil.fragmentChanged(artifactID.getSegments()), depMap); } private boolean isOfType(IndexRow row, EClass eClass) { return row.getMetaData().getMulti(IndexConstants.COLUMN_ROOT_ECLASS).contains( SokanReuseResourceUtil.eClassToString(eClass)); } private static final String EMFTEXT_PROXY_FRAGMENT = "EMFTEXT_INTERNAL_URI_FRAGMENT_"; private String getNameFromProxy(EObject proxy) { String fragment = ((InternalEObject) proxy).eProxyURI().fragment(); String name = null; if (fragment.startsWith(EMFTEXT_PROXY_FRAGMENT)) { name = fragment.substring(EMFTEXT_PROXY_FRAGMENT.length()); name = name.substring(name.indexOf("_") + 1); } return name; } }