/***************************************************************************** * Copyright (c) 2010 Atos Origin. * * * 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: * Tristan FAURE tristan.faure@atosorigin.com - Initial API and implementation * *****************************************************************************/ package org.eclipse.papyrus.infra.core.modelsetquery.impl; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.IdentityHashMap; import java.util.Map; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EContentAdapter; import org.eclipse.emf.edit.provider.ItemPropertyDescriptor; import org.eclipse.papyrus.infra.core.modelsetquery.IFillableModelSetQueryAdapter; /** * This cache creates a map associating EClasses to all the corresponding * This implementation takes more space but it is more performant for get and put methods * instances * * @author Tristan Faure */ public class ModelSetQueryAdapterTimeMatters extends EContentAdapter implements IFillableModelSetQueryAdapter { /** * The cache of elements */ private Map<EClassifier, Collection<EObject>> cache = Collections.synchronizedMap(new IdentityHashMap<EClassifier, Collection<EObject>>()); public ModelSetQueryAdapterTimeMatters() { super(); } protected void addAdapter(Notifier notifier) { super.addAdapter(notifier); if(notifier instanceof EObject) { EObject eobject = (EObject)notifier; addObjectInCache(eobject); } } @Override protected void removeAdapter(Notifier notifier) { super.removeAdapter(notifier); if(notifier instanceof EObject) { EObject eobject = (EObject)notifier; removeObjectFromCache(eobject); } } private void addObjectInCache(EObject newObj) { EClass eClass = newObj.eClass(); putObjectInCache(eClass, newObj); for(EClass eSuperClass : eClass.getEAllSuperTypes()) { putObjectInCache(eSuperClass, newObj); } } private void putObjectInCache(EClassifier eClassifier, EObject newObj) { Collection<EObject> listOfClassifiers = cache.get(eClassifier); if (listOfClassifiers == null) { listOfClassifiers = new HashSet<EObject>(); cache.put(eClassifier, listOfClassifiers); } if(listOfClassifiers != null) { listOfClassifiers.add(newObj); } } private void removeObjectFromCache(EObject newObj) { EClass eClass = newObj.eClass(); removeObjectFromCache(eClass, newObj); for(EClass eSuperClass : eClass.getEAllSuperTypes()) { removeObjectFromCache(eSuperClass, newObj); } } private void removeObjectFromCache(EClassifier eClassifier, EObject newObj) { Collection<EObject> listOfClassifiers = cache.get(eClassifier); if(listOfClassifiers != null) { listOfClassifiers.remove(newObj); } if (listOfClassifiers.isEmpty()) { cache.remove(eClassifier); } } public Collection<EObject> getReachableObjectsOfType(EObject object, EClassifier type) { if(!cache.containsKey(type)) { cache.put(type, new HashSet<EObject>(ItemPropertyDescriptor.getReachableObjectsOfType(object, type))); } return cache.get(type); } public void dispose() { cache.clear(); cache = null; } /** * This method provides a way for user to force first entries in the cache. * The list of element must be a HashSet to optimize the performances * * @param type * @param list */ public void addEntriesInCache(EClassifier type, HashSet<EObject> list) { for (EObject e : list) { addObjectInCache(e); } } public boolean isAlreadyComputed(EClassifier type) { return cache.containsKey(type); } }