blob: f3557cd28a23917edf0fbb569da2d12fbb3700ec [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011-2018 The University of York.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License, v. 2.0 are satisfied: GNU General Public License, version 3.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-3.0
*
* Contributors:
* Antonio Garcia-Dominguez - initial API and implementation
******************************************************************************/
package org.hawk.graph.updater;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.NoSuchElementException;
import org.hawk.core.IMetaModelResourceFactory;
import org.hawk.core.IModelIndexer;
import org.hawk.core.graph.IGraphDatabase;
import org.hawk.core.graph.IGraphEdge;
import org.hawk.core.graph.IGraphIterable;
import org.hawk.core.graph.IGraphNode;
import org.hawk.core.model.IHawkClass;
import org.hawk.core.model.IHawkClassifier;
import org.hawk.core.model.IHawkMetaModelResource;
import org.hawk.graph.Slot;
import org.hawk.graph.TypeNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Cache that can be shared across multiple {@link GraphModelBatchInjector}
* classes to avoid retrieving the same type node again and again. Designed to
* be simply GC'ed during the {@link GraphModelUpdater#updateProxies()} stage.
*/
public class TypeCache {
private static final Logger LOGGER = LoggerFactory.getLogger(TypeCache.class);
private Map<IHawkClass, IGraphNode> hashedEClasses = new HashMap<>();
private Map<IGraphNode, Map<String, Slot>> hashedEClassSlots = new HashMap<>();
private IModelIndexer hawk;
public TypeCache(IModelIndexer hawk) {
this.hawk = hawk;
}
public IGraphNode getEClassNode(IGraphDatabase graph, IHawkClassifier e) throws Exception {
IHawkClass eClass = null;
if (e instanceof IHawkClass)
eClass = ((IHawkClass) e);
else
System.err.println("getEClassNode called on a non-class classifier:\n" + e);
IGraphNode classnode = hashedEClasses.get(eClass);
if (classnode == null) {
final String packageNSURI = eClass.getPackageNSURI();
IGraphNode ePackageNode = null;
final IGraphIterable<? extends IGraphNode> iterMM = graph.getMetamodelIndex().get("id", packageNSURI);
if (!iterMM.iterator().hasNext()) {
// Metamodel is not in the store, try to find it
LOGGER.info("Metamodel {} is not in the graph, trying to locate it", packageNSURI);
for (IMetaModelResourceFactory mmp : hawk.getMetaModelParsers()) {
IHawkMetaModelResource mr = mmp.getMetamodel(packageNSURI);
if (mr != null) {
LOGGER.info("Found metamodel for {}, inserting", packageNSURI);
final HashSet<IHawkMetaModelResource> setMR = new HashSet<>(Arrays.asList(mr));
hawk.getMetaModelUpdater().insertMetamodels(setMR, hawk);
}
}
}
try {
ePackageNode = iterMM.getSingle();
} catch (NoSuchElementException ex) {
throw new Exception(String.format(
"Metamodel %s does not have a Node associated with it in the store, please make sure it has been inserted",
packageNSURI));
} catch (Exception e2) {
LOGGER.error("Error while finding metamodel node", e2);
}
for (IGraphEdge r : ePackageNode.getEdges()) {
final IGraphNode otherNode = r.getStartNode();
if (otherNode.equals(ePackageNode)) {
continue;
}
final Object id = otherNode.getProperty(IModelIndexer.IDENTIFIER_PROPERTY);
if (id.equals(eClass.getName())) {
classnode = otherNode;
break;
}
}
if (classnode != null) {
hashedEClasses.put(eClass, classnode);
} else {
throw new Exception(String.format(
"eClass: %s (%s) does not have a Node associated with it in the store, please make sure the metamodel %s has been inserted",
eClass.getName(), eClass.getUri(), packageNSURI));
}
hashedEClassSlots.put(classnode, new TypeNode(classnode).getSlots());
}
return classnode;
}
public Map<String, Slot> getEClassNodeSlots(IGraphDatabase graph, IHawkClassifier e) throws Exception {
return hashedEClassSlots.get(getEClassNode(graph, e));
}
}