From 6848b16a857a5bf031ae832cf6273d45fe7e06ca Mon Sep 17 00:00:00 2001 From: AlexisDrogoul Date: Mon, 3 Jan 2022 13:27:21 +0700 Subject: [PATCH] Possible fix for #3268. Please test as the behavior of imports is slightly changed : now in case of multiple imports of the same model, the deepest ones in the dependency graph are loaded before the others, correctly respecting the hierarchy of imports. Same for the order in which the imports are declared, which now has a semantic value : the models will be loaded in the order they are declared. --- .../msi/gaml/factories/ModelAssembler.java | 102 +++-- .../lang/gaml/indexer/GamlResourceGraph.java | 229 +++++++++++ .../gaml/indexer/GamlResourceIndexer.java | 358 +++++------------- .../gama/lang/gaml/resource/GamlResource.java | 2 +- .../GamlResourceDescriptionManager.java | 47 ++- .../resource/GamlResourceInfoProvider.java | 82 ++-- .../gaml/resource/GamlResourceServices.java | 17 +- .../scoping/BuiltinGlobalScopeProvider.java | 68 ++-- .../ErrorToDiagnoticTranslator.java | 4 +- 9 files changed, 500 insertions(+), 409 deletions(-) create mode 100644 msi.gama.lang.gaml/src/msi/gama/lang/gaml/indexer/GamlResourceGraph.java diff --git a/msi.gama.core/src/msi/gaml/factories/ModelAssembler.java b/msi.gama.core/src/msi/gaml/factories/ModelAssembler.java index 34008c53b1..0e71596566 100644 --- a/msi.gama.core/src/msi/gaml/factories/ModelAssembler.java +++ b/msi.gama.core/src/msi/gaml/factories/ModelAssembler.java @@ -1,12 +1,12 @@ /******************************************************************************************************* * - * ModelAssembler.java, in msi.gama.core, is part of the source code of the - * GAMA modeling and simulation platform (v.1.8.2). + * ModelAssembler.java, in msi.gama.core, is part of the source code of the GAMA modeling and simulation platform + * (v.1.8.2). * - * (c) 2007-2021 UMI 209 UMMISCO IRD/SU & Partners (IRIT, MIAT, TLU, CTU) + * (c) 2007-2022 UMI 209 UMMISCO IRD/SU & Partners (IRIT, MIAT, TLU, CTU) * * Visit https://github.com/gama-platform/gama for license information and contacts. - * + * ********************************************************************************************************/ package msi.gaml.factories; @@ -53,6 +53,7 @@ import msi.gaml.descriptions.ValidationContext; import msi.gaml.statements.Facets; import msi.gaml.types.Types; +import ummisco.gama.dev.utils.DEBUG; /** * Class ModelAssembler. @@ -64,20 +65,32 @@ @SuppressWarnings ({ "unchecked", "rawtypes" }) public class ModelAssembler { + static { + DEBUG.ON(); + } + /** * Assemble. * - * @param projectPath the project path - * @param modelPath the model path - * @param allModels the all models - * @param collector the collector - * @param document the document - * @param mm the mm + * @param projectPath + * the project path + * @param modelPath + * the model path + * @param allModels + * the all models + * @param collector + * the collector + * @param document + * the document + * @param mm + * the mm * @return the model description */ public ModelDescription assemble(final String projectPath, final String modelPath, final Iterable allModels, final ValidationContext collector, final boolean document, final Map mm) { + // DEBUG.OUT("All models passed to ModelAssembler: " + // + Iterables.transform(allModels, @Nullable ISyntacticElement::getName)); final ImmutableList models = ImmutableList.copyOf(allModels); final IMap speciesNodes = GamaMapFactory.create(); final IMap>[] experimentNodes = new IMap[1]; @@ -248,7 +261,8 @@ public ModelDescription assemble(final String projectPath, final String modelPat /** * Gets the species in hierarchical order. * - * @param model the model + * @param model + * the model * @return the species in hierarchical order */ private Iterable getSpeciesInHierarchicalOrder(final ModelDescription model) { @@ -277,7 +291,8 @@ private Iterable getSpeciesInHierarchicalOrder(final ModelDe /** * Creates the scheduler species. * - * @param model the model + * @param model + * the model */ private void createSchedulerSpecies(final ModelDescription model) { final SpeciesDescription sd = @@ -304,10 +319,14 @@ private void createSchedulerSpecies(final ModelDescription model) { /** * Adds the experiment. * - * @param origin the origin - * @param model the model - * @param experiment the experiment - * @param cache the cache + * @param origin + * the origin + * @param model + * the model + * @param experiment + * the experiment + * @param cache + * the cache */ void addExperiment(final String origin, final ModelDescription model, final ISyntacticElement experiment, final Map cache) { @@ -323,10 +342,14 @@ void addExperiment(final String origin, final ModelDescription model, final ISyn /** * Adds the experiment node. * - * @param element the element - * @param modelName the model name - * @param experimentNodes the experiment nodes - * @param collector the collector + * @param element + * the element + * @param modelName + * the model name + * @param experimentNodes + * the experiment nodes + * @param collector + * the collector */ void addExperimentNode(final ISyntacticElement element, final String modelName, final Map> experimentNodes, final ValidationContext collector) { @@ -357,9 +380,12 @@ void addExperimentNode(final ISyntacticElement element, final String modelName, /** * Adds the micro species. * - * @param macro the macro - * @param micro the micro - * @param cache the cache + * @param macro + * the macro + * @param micro + * the micro + * @param cache + * the cache */ void addMicroSpecies(final SpeciesDescription macro, final ISyntacticElement micro, final Map cache) { @@ -380,9 +406,12 @@ void addMicroSpecies(final SpeciesDescription macro, final ISyntacticElement mic /** * Adds the species node. * - * @param element the element - * @param speciesNodes the species nodes - * @param collector the collector + * @param element + * the element + * @param speciesNodes + * the species nodes + * @param collector + * the collector */ void addSpeciesNode(final ISyntacticElement element, final Map speciesNodes, final ValidationContext collector) { @@ -423,8 +452,10 @@ void complementSpecies(final SpeciesDescription species, final ISyntacticElement /** * Parent experiment. * - * @param model the model - * @param micro the micro + * @param model + * the model + * @param micro + * the micro */ void parentExperiment(final ModelDescription model, final ISyntacticElement micro) { // Gather the previously created species @@ -441,10 +472,14 @@ void parentExperiment(final ModelDescription model, final ISyntacticElement micr /** * Parent species. * - * @param macro the macro - * @param micro the micro - * @param model the model - * @param cache the cache + * @param macro + * the macro + * @param micro + * the micro + * @param model + * the model + * @param cache + * the cache */ void parentSpecies(final SpeciesDescription macro, final ISyntacticElement micro, final ModelDescription model, final Map cache) { @@ -483,7 +518,8 @@ SpeciesDescription lookupSpecies(final String name, final Map { + + /** + * Instantiates a new graph. + */ + public Graph() { + super(null, null, + new DefaultGraphType.Builder().directed().allowMultipleEdges(false).allowSelfLoops(false) + .weighted(false).allowCycles(true).build(), + new DefaultGraphSpecificsStrategy()); + } + + } + + /** The regular imports. */ + Graph imports = new Graph(); + + /** + * Reset. + */ + void reset() { + imports = new Graph(); + } + + /** + * The Class Edge. + */ + static class LabeledEdge { + + /** The label. */ + String label; + + /** The target. */ + final URI target; + + /** + * Instantiates a new edge. + * + * @param l + * the l + * @param target + * the target + */ + LabeledEdge(final String l, final URI target) { + this.label = l; + this.target = target; + } + + } + + /** + * Contains vertex. + * + * @param uri + * the uri + * @return true, if successful + */ + public boolean containsVertex(final URI uri) { + return imports.containsVertex(uri); + } + + /** + * Predecessors of. + * + * @param newURI + * the new URI + * @return the sets the + */ + public Set predecessorsOf(final URI uri) { + return newHashSet(imports.containsVertex(uri) ? predecessorListOf(imports, uri) : EMPTY_LIST); + } + + /** + * Successors of. + * + * @param newURI + * the new URI + * @return the sets the + */ + public Set successorsOf(final URI uri) { + return newHashSet(imports.containsVertex(uri) ? successorListOf(imports, uri) : EMPTY_LIST); + } + + /** + * Adds the edge. + * + * @param from + * the from + * @param to + * the to + * @param label + * the label + */ + public void addEdge(final URI from, final URI to, final String label) { + imports.addVertex(from); + imports.addVertex(to); + imports.removeEdge(from, to); + imports.addEdge(from, to, new LabeledEdge(label, to)); + } + + /** + * Breadth first iterator without. + * + * @param uri + * the uri + * @return the iterator + */ + public Iterator breadthFirstIteratorWithout(final URI uri) { + Iterator regular = + imports.containsVertex(uri) ? new BreadthFirstIterator<>(imports, uri) : emptyIterator(); + // to eliminate the uri + if (regular.hasNext()) { regular.next(); } + return regular; + } + + /** + * Removes the all edges. + * + * @param edges + * the edges + */ + public void removeAllEdges(final URI source, final Map edges) { + for (URI uri : edges.keySet()) { imports.removeAllEdges(source, uri); } + // TransitiveReduction.INSTANCE.reduce(regularImports); + } + + /** + * Outgoing edges of. + * + * @param uri + * the uri + * @return the map + */ + public Map outgoingEdgesOf(final URI uri) { + if (!containsVertex(uri)) return Collections.EMPTY_MAP; + Map result = GamaMapFactory.createOrdered(); + if (imports.containsVertex(uri)) { + for (LabeledEdge o : imports.outgoingEdgesOf(uri)) { result.put(o.target, o.label); } + } + return result; + } + + /** + * Sorted imports of. + * + * @param uri + * the uri + * @return the map + */ + @SuppressWarnings ("null") + public Map sortedDepthFirstSearchWithLabels(final URI uri) { + Map result = Maps.newLinkedHashMap(); + searchImports(uri, null, result); + result.remove(uri); + return result; + } + + /** + * All imports of. A simple depth first visit that keeps track of the labels + * + * @param uri + * the uri + * @param currentLabel + * the current label + * @param result + * the result + */ + private void searchImports(final URI uri, final String currentLabel, final Map result) { + if (!result.containsKey(uri)) { + result.put(uri, currentLabel); + if (imports.containsVertex(uri)) { + for (LabeledEdge edge : imports.outgoingEdgesOf(uri)) { + searchImports(edge.target, edge.label == null ? currentLabel : edge.label, result); + } + } + } else { + // if already there we re-insert it to keep the last occurence + result.remove(uri); + result.put(uri, currentLabel); + } + + } +} diff --git a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/indexer/GamlResourceIndexer.java b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/indexer/GamlResourceIndexer.java index 3b6a0c1514..70e1fef091 100644 --- a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/indexer/GamlResourceIndexer.java +++ b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/indexer/GamlResourceIndexer.java @@ -1,19 +1,16 @@ /******************************************************************************************************* * * GamlResourceIndexer.java, in msi.gama.lang.gaml, is part of the source code of the GAMA modeling and simulation - * platform (v.2.0.0). + * platform (v.1.8.2). * - * (c) 2007-2021 UMI 209 UMMISCO IRD/SU & Partners (IRIT, MIAT, TLU, CTU) + * (c) 2007-2022 UMI 209 UMMISCO IRD/SU & Partners (IRIT, MIAT, TLU, CTU) * * Visit https://github.com/gama-platform/gama for license information and contacts. * ********************************************************************************************************/ package msi.gama.lang.gaml.indexer; -import java.util.Collection; import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -23,18 +20,11 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; -import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.xtext.EcoreUtil2; -import org.jgrapht.Graphs; -import org.jgrapht.graph.SimpleDirectedGraph; -import org.jgrapht.traverse.BreadthFirstIterator; -import com.google.common.base.Objects; -import com.google.common.collect.Iterators; import com.google.common.collect.LinkedHashMultimap; import com.google.inject.Singleton; -import msi.gama.common.interfaces.BiConsumerWithPruning; import msi.gama.lang.gaml.gaml.ExperimentFileStructure; import msi.gama.lang.gaml.gaml.GamlPackage; import msi.gama.lang.gaml.gaml.Import; @@ -44,6 +34,7 @@ import msi.gama.lang.gaml.resource.GamlResourceServices; import msi.gama.util.GamaMapFactory; import msi.gama.util.IMap; +import ummisco.gama.dev.utils.DEBUG; /** * The Class GamlResourceIndexer. @@ -53,9 +44,10 @@ public class GamlResourceIndexer { /** The index. */ - static SimpleDirectedGraph index = new SimpleDirectedGraph(Edge.class); + static GamlResourceGraph index = new GamlResourceGraph(); static { + DEBUG.ON(); final IWorkspace workspace = ResourcesPlugin.getWorkspace(); workspace.addResourceChangeListener( event -> { if (event.getBuildKind() == IncrementalProjectBuilder.CLEAN_BUILD) { eraseIndex(); } }, @@ -77,11 +69,13 @@ public class GamlResourceIndexer { * the m * @return the imports as absolute URIS */ - protected static IMap getImportsAsAbsoluteURIS(final URI baseURI, final Model m) { - IMap result = EMPTY_MAP; - if (((ModelImpl) m).eIsSet(GamlPackage.MODEL__IMPORTS)) { - result = GamaMapFactory.create(); - for (final Import e : m.getImports()) { + private static Map getImportsAsAbsoluteURIS(final URI baseURI, final EObject m) { + final boolean isModel = m instanceof Model; + final boolean isExpe = m instanceof ExperimentFileStructure; + Map result = EMPTY_MAP; + if (isModel && ((ModelImpl) m).eIsSet(GamlPackage.MODEL__IMPORTS)) { + result = GamaMapFactory.createOrdered(); + for (final Import e : ((Model) m).getImports()) { final String u = e.getImportURI(); if (u != null) { URI uri = URI.createURI(u, true); @@ -90,89 +84,17 @@ protected static IMap getImportsAsAbsoluteURIS(final URI baseURI, f result.put(uri, label); } } + } else if (isExpe) { + final String u = ((ExperimentFileStructure) m).getExp().getImportURI(); + if (u != null) { + URI uri = URI.createURI(u, true); + uri = GamlResourceServices.properlyEncodedURI(uri.resolve(baseURI)); + result = Collections.singletonMap(uri, null); + } } return result; } - /** - * Gets the imports as absolute URIS. - * - * @param baseURI - * the base URI - * @param m - * the m - * @return the imports as absolute URIS - */ - protected static IMap getImportsAsAbsoluteURIS(final URI baseURI, final ExperimentFileStructure m) { - final IMap result = GamaMapFactory.create(); - final String u = m.getExp().getImportURI(); - if (u != null) { - URI uri = URI.createURI(u, true); - uri = GamlResourceServices.properlyEncodedURI(uri.resolve(baseURI)); - result.put(uri, null); - } - - return result; - } - - /** - * All labeled imports of. - * - * @param r - * the r - * @return the i map - */ - public static IMap allLabeledImportsOf(final GamlResource r) { - return r.getCache().get(IMPORTED_URIS, r, () -> allLabeledImportsOf(r.getURI())); - } - - /** - * The Class Edge. - */ - static class Edge { - - /** The label. */ - String label; - - /** The target. */ - final URI target; - - /** - * Instantiates a new edge. - * - * @param l - * the l - * @param target - * the target - */ - Edge(final String l, final URI target) { - this.label = l; - this.target = target; - } - - /** - * Gets the target. - * - * @return the target - */ - URI getTarget() { return target; } - - /** - * Gets the label. - * - * @return the label - */ - String getLabel() { return label; } - - /** - * Sets the label. - * - * @param b - * the new label - */ - public void setLabel(final String b) { label = b; } - } - /** * Adds the import. * @@ -184,25 +106,28 @@ static class Edge { * the label */ static void addImport(final URI from, final URI to, final String label) { - index.addVertex(to); - index.addVertex(from); - index.addEdge(from, to, new Edge(label, to)); + index.addEdge(from, to, label); } /** - * Clear resource set. + * Find import. * - * @param resourceSet - * the resource set - */ - public static void clearResourceSet(final ResourceSet resourceSet) { - final boolean wasDeliver = resourceSet.eDeliver(); - try { - resourceSet.eSetDeliver(false); - resourceSet.getResources().clear(); - } finally { - resourceSet.eSetDeliver(wasDeliver); + * @param model + * the model + * @param uri + * the uri + * @return the e object + */ + static private EObject findImport(final EObject model, final URI baseURI, final URI uri) { + if (model instanceof ExperimentFileStructure) { + String m = ((ExperimentFileStructure) model).getExp().getImportURI(); + if (m.contains(URI.decode(uri.lastSegment())) || uri.equals(baseURI) && m.isEmpty()) return model; + } else if (model instanceof Model) { + for (final Import e : ((Model) model).getImports()) { + if (e.getImportURI().contains(URI.decode(uri.lastSegment()))) return e; + } } + return null; } /** @@ -210,212 +135,111 @@ public static void clearResourceSet(final ResourceSet resourceSet) { */ public static synchronized EObject updateImports(final GamlResource r) { final URI baseURI = GamlResourceServices.properlyEncodedURI(r.getURI()); - final Set nativeEdges = index.containsVertex(baseURI) ? index.outgoingEdgesOf(baseURI) : null; - final Set edges = - nativeEdges == null || nativeEdges.isEmpty() ? Collections.EMPTY_SET : new HashSet(nativeEdges); + final Map existingEdges = index.outgoingEdgesOf(baseURI); if (r.getContents().isEmpty()) return null; final EObject contents = r.getContents().get(0); if (contents == null) return null; - final boolean isModel = contents instanceof Model; - final boolean isExpe = contents instanceof ExperimentFileStructure; - final IMap added; - if (isModel) { - added = getImportsAsAbsoluteURIS(baseURI, (Model) contents); - } else if (isExpe) { - added = getImportsAsAbsoluteURIS(baseURI, (ExperimentFileStructure) contents); - } else - return null; - final EObject[] faulty = new EObject[1]; - if (added.forEachPair(new BiConsumerWithPruning() { - - @Override - public boolean process(final URI uri, final String b) { - if (baseURI.equals(uri)) return true; - final Iterator iterator = edges.iterator(); - boolean found = false; - while (iterator.hasNext()) { - final Edge edge = iterator.next(); - if (edge.getTarget().equals(uri)) { - found = true; - if (!Objects.equal(edge.getLabel(), b)) { edge.setLabel(b); } - iterator.remove(); - break; - } - } - if (!found) { - if (!EcoreUtil2.isValidUri(r, uri)) { - if (isModel) { - faulty[0] = findImport((Model) contents, uri); - } else { - faulty[0] = findImport((ExperimentFileStructure) contents, uri); - } - return false; - } - final boolean alreadyThere = index.containsVertex(uri); - addImport(baseURI, uri, b); - if (!alreadyThere) { - // This call should trigger the recursive call to - // updateImports() - r.getResourceSet().getResource(uri, true); - } - } - return true; - } - - private EObject findImport(final ExperimentFileStructure model, final URI uri) { - if (model.getExp().getImportURI().contains(URI.decode(uri.lastSegment())) || (uri.equals(baseURI) && model.getExp().getImportURI().isEmpty())) return model; - return null; - } - - private EObject findImport(final Model model, final URI uri) { - for (final Import e : model.getImports()) { - if (e.getImportURI().contains(URI.decode(uri.lastSegment())) || (uri.equals(baseURI) && e.getImportURI().isEmpty())) return e; + final Map newEdges = getImportsAsAbsoluteURIS(baseURI, contents); + for (Map.Entry entry : newEdges.entrySet()) { + URI uri = entry.getKey(); + if (baseURI.equals(uri)) { continue; } + String label = entry.getValue(); + if (!existingEdges.containsKey(uri)) { + if (!EcoreUtil2.isValidUri(r, uri)) return findImport(contents, baseURI, uri); + final boolean alreadyThere = index.containsVertex(uri); + addImport(baseURI, uri, label); + if (!alreadyThere) { + // This call should trigger the recursive call to updateImports() + r.getResourceSet().getResource(uri, true); } - return null; + } else { + index.addEdge(baseURI, uri, existingEdges.remove(uri)); } - })) { - index.removeAllEdges(edges); - return null; } - return faulty[0]; + index.removeAllEdges(baseURI, existingEdges); + return null; } /** - * Validate imports of. + * Validate the imports of a resource by reconstructing the associated resources and verifying their status. * * @param resource * the resource * @return the linked hash multimap */ public static LinkedHashMultimap validateImportsOf(final GamlResource resource) { - final IMap uris = allLabeledImportsOf(resource); - uris.remove(GamlResourceServices.properlyEncodedURI(resource.getURI())); + final Map uris = allImportsOf(resource); + LinkedHashMultimap imports = null; if (!uris.isEmpty()) { - final LinkedHashMultimap imports = LinkedHashMultimap.create(); - if (uris.forEachPair((a, b) -> { - final GamlResource r = (GamlResource) resource.getResourceSet().getResource(a, true); + imports = LinkedHashMultimap.create(); + for (Map.Entry entry : uris.entrySet()) { + final GamlResource r = (GamlResource) resource.getResourceSet().getResource(entry.getKey(), true); + if (r == resource) { continue; } if (r.hasErrors()) { resource.invalidate(r, "Errors detected"); - return false; + return null; } - imports.put(b, r); - return true; - })) return imports; - + imports.put(entry.getValue(), r); + } } - return null; - } - - /** - * @see msi.gama.lang.gaml.indexer.IModelIndexer#directImportersOf(org.eclipse.emf.common.util.URI) - */ - public static Set directImportersOf(final URI uri) { - final URI newURI = GamlResourceServices.properlyEncodedURI(uri); - if (index.containsVertex(newURI)) return new HashSet(Graphs.predecessorListOf(index, newURI)); - return Collections.EMPTY_SET; - } - - /** - * @see msi.gama.lang.gaml.indexer.IModelIndexer#directImportsOf(org.eclipse.emf.common.util.URI) - */ - public static Set directImportsOf(final URI uri) { - final URI newURI = GamlResourceServices.properlyEncodedURI(uri); - if (index.containsVertex(newURI)) return new HashSet(Graphs.successorListOf(index, newURI)); - return Collections.EMPTY_SET; + return imports; } /** * All labeled imports of. * - * @param uri - * the uri + * @param r + * the r * @return the i map */ - private static IMap allLabeledImportsOf(final URI uri) { - final URI newURI = GamlResourceServices.properlyEncodedURI(uri); - final IMap result = GamaMapFactory.create(); - allLabeledImports(newURI, null, result); - return result; - } - - /** - * All labeled imports. - * - * @param uri - * the uri - * @param currentLabel - * the current label - * @param result - * the result - */ - private static void allLabeledImports(final URI uri, final String currentLabel, final Map result) { - if (!result.containsKey(uri)) { - result.put(uri, currentLabel); - if (indexes(uri)) { - final Collection edges = index.outgoingEdgesOf(uri); - for (final Edge e : edges) { - allLabeledImports(index.getEdgeTarget(e), e.getLabel() == null ? currentLabel : e.getLabel(), - result); - } - } - } - + public static Map allImportsOf(final GamlResource r) { + return r.getCache().get(IMPORTED_URIS, r, () -> allImportsOf(r.getURI())); } /** - * @see msi.gama.lang.gaml.indexer.IModelIndexer#allImportsOf(org.eclipse.emf.common.util.URI) + * Erase index. */ - public static Iterator allImportsOf(final URI uri) { - if (!indexes(uri)) return Iterators.singletonIterator(uri);// .emptyIterator(); - final Iterator result = new BreadthFirstIterator(index, GamlResourceServices.properlyEncodedURI(uri)); - result.next(); // to eliminate the uri - return result; + public static void eraseIndex() { + // DEBUG.OUT("Erasing GAML indexer index"); + index.reset(); } /** - * Indexes. + * Checks if is imported. * - * @param uri - * the uri - * @return true, if successful + * @param r + * the r + * @return true, if is imported */ - public static boolean indexes(final URI uri) { - return index.containsVertex(GamlResourceServices.properlyEncodedURI(uri)); + public static boolean isImported(final GamlResource r) { + return !directImportersOf(r.getURI()).isEmpty(); } /** - * Equals. - * - * @param uri1 - * the uri 1 - * @param uri2 - * the uri 2 - * @return true, if successful + * @see msi.gama.lang.gaml.indexer.IModelIndexer#directImportersOf(org.eclipse.emf.common.util.URI) */ - public static boolean equals(final URI uri1, final URI uri2) { - if (uri1 == null) return uri2 == null; - if (uri2 == null) return false; - return GamlResourceServices.properlyEncodedURI(uri1).equals(GamlResourceServices.properlyEncodedURI(uri2)); + public static Set directImportersOf(final URI uri) { + return index.predecessorsOf(GamlResourceServices.properlyEncodedURI(uri)); } /** - * Erase index. + * @see msi.gama.lang.gaml.indexer.IModelIndexer#directImportsOf(org.eclipse.emf.common.util.URI) */ - public static void eraseIndex() { - // DEBUG.OUT("Erasing GAML indexer index"); - index = new SimpleDirectedGraph(Edge.class); + public static Set directImportsOf(final URI uri) { + return index.successorsOf(GamlResourceServices.properlyEncodedURI(uri)); } /** - * Checks if is imported. + * All labeled imports of. * - * @param r - * the r - * @return true, if is imported + * @param uri + * the uri + * @return the i map */ - public static boolean isImported(final GamlResource r) { - return !directImportersOf(r.getURI()).isEmpty(); + public static Map allImportsOf(final URI uri) { + // DEBUG.OUT("Computing all labeled imports for " + uri.lastSegment()); + return index.sortedDepthFirstSearchWithLabels(GamlResourceServices.properlyEncodedURI(uri)); } } diff --git a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResource.java b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResource.java index 64e5628488..9fece2cbd8 100644 --- a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResource.java +++ b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResource.java @@ -136,7 +136,7 @@ private ModelDescription buildModelDescription(final LinkedHashMultimap deltas, final IResourceDescription candidate, final IResourceDescriptions context) { - // final boolean result = false; - final URI newUri = candidate.getURI(); - try (ICollector deltaUris = Collector.getSet()) { - for (final Delta d : deltas) { - deltaUris.add(GamlResourceServices.properlyEncodedURI(d.getUri())); - } - final Iterator it = GamlResourceIndexer.allImportsOf(newUri); - while (it.hasNext()) { - final URI next = it.next(); - if (deltaUris.contains(next)) { return true; } - } - return super.isAffected(deltas, candidate, context); + Map imports; + if (!(candidate instanceof GamlResourceDescription)) { + // Seems to happen, although it shouldnt ! + imports = GamlResourceIndexer.allImportsOf(candidate.getURI()); + } else { + imports = GamlResourceIndexer + .allImportsOf((GamlResource) ((GamlResourceDescription) candidate).getResource()); + } + if (imports.isEmpty()) return false; + for (Delta d : deltas) { + if (d.haveEObjectDescriptionsChanged() && imports.containsKey(properlyEncodedURI(d.getUri()))) return true; } + return false; + // return super.isAffected(deltas, candidate, context); } @Override diff --git a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResourceInfoProvider.java b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResourceInfoProvider.java index 93a6ea2687..db5a2f6c35 100644 --- a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResourceInfoProvider.java +++ b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResourceInfoProvider.java @@ -1,14 +1,13 @@ -/********************************************************************************************* +/******************************************************************************************************* * - * 'GamlResourceInfoProvider.java, in plugin msi.gama.lang.gaml, is part of the source code of the GAMA modeling and - * simulation platform. (v. 1.8.1) + * GamlResourceInfoProvider.java, in msi.gama.lang.gaml, is part of the source code of the + * GAMA modeling and simulation platform (v.1.8.2). * - * (c) 2007-2020 UMI 209 UMMISCO IRD/UPMC & Partners + * (c) 2007-2022 UMI 209 UMMISCO IRD/SU & Partners (IRIT, MIAT, TLU, CTU) * - * Visit https://github.com/gama-platform/gama for license information and developers contact. - * - * - **********************************************************************************************/ + * Visit https://github.com/gama-platform/gama for license information and contacts. + * + ********************************************************************************************************/ package msi.gama.lang.gaml.resource; import static java.util.Arrays.asList; @@ -29,7 +28,7 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.ResourceSet; -import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.xtext.resource.SynchronizedXtextResourceSet; import org.eclipse.xtext.resource.XtextResourceSet; @@ -47,22 +46,33 @@ import msi.gaml.compilation.ast.ISyntacticElement; import ummisco.gama.dev.utils.DEBUG; +/** + * The Class GamlResourceInfoProvider. + */ @Singleton @SuppressWarnings ({ "unchecked", "rawtypes" }) public class GamlResourceInfoProvider implements IGamlResourceInfoProvider { + /** The instance. */ public static GamlResourceInfoProvider INSTANCE = new GamlResourceInfoProvider(); + /** The resource set. */ private XtextResourceSet resourceSet; + /** + * Gets the info. + * + * @param originalURI the original URI + * @param r the r + * @param stamp the stamp + * @return the info + */ public GamlFileInfo getInfo(final URI originalURI, final GamlResource r, final long stamp) { Set imports = null; final Set uris = GamlResourceIndexer.directImportsOf(originalURI); for (final URI u : uris) { - if (imports == null) { - imports = new LinkedHashSet(); - } + if (imports == null) { imports = new LinkedHashSet(); } imports.add(u.deresolve(originalURI).toString()); } @@ -71,9 +81,7 @@ public GamlFileInfo getInfo(final URI originalURI, final GamlResource r, final l try (InputStream is = resourceSet.getURIConverter().createInputStream(originalURI); BufferedReader reader = new BufferedReader(new InputStreamReader(is))) { boolean tagsFound = false; - while (!tagsFound && (str = reader.readLine()) != null) { - tagsFound = str.contains("Tags: "); - } + while (!tagsFound && (str = reader.readLine()) != null) { tagsFound = str.contains("Tags: "); } if (tagsFound) { tags = new HashSet<>(asList(split(uncapitalize(deleteWhitespace(substringAfter(str, "Tags: "))), ','))); } @@ -84,15 +92,13 @@ public GamlFileInfo getInfo(final URI originalURI, final GamlResource r, final l Set uses = null; Set exps = null; - final TreeIterator tree = EcoreUtil2.getAllContents(r, true); + final TreeIterator tree = EcoreUtil.getAllContents(r, true); boolean processExperiments = true; while (tree.hasNext()) { final EObject e = tree.next(); if (e instanceof Pragma) { final String s = ((Pragma) e).getName(); - if (IKeyword.NO_EXPERIMENT.equals(s)) { - processExperiments = false; - } + if (IKeyword.NO_EXPERIMENT.equals(s)) { processExperiments = false; } } else if (e instanceof StringLiteral) { final String s = ((StringLiteral) e).getOp(); if (s.length() > 4) { @@ -100,36 +106,24 @@ public GamlFileInfo getInfo(final URI originalURI, final GamlResource r, final l final String ext = u.fileExtension(); if (ext != null && !ext.isEmpty()) { // if (GamaBundleLoader.HANDLED_FILE_EXTENSIONS.contains(ext)) { - if (uses == null) { - uses = new LinkedHashSet(); - } + if (uses == null) { uses = new LinkedHashSet(); } uses.add(s); // } } } } else if (processExperiments && e instanceof S_Experiment) { String s = ((S_Experiment) e).getName(); - if (s == null) { - DEBUG.ERR("EXPERIMENT NULL"); - } - if (EGaml.getInstance().isBatch(e)) { - s = GamlFileInfo.BATCH_PREFIX + s; - } + if (s == null) { DEBUG.ERR("EXPERIMENT NULL"); } + if (EGaml.getInstance().isBatch(e)) { s = GamlFileInfo.BATCH_PREFIX + s; } - if (exps == null) { - exps = new LinkedHashSet(); - } + if (exps == null) { exps = new LinkedHashSet(); } exps.add(s); } else if (processExperiments && e instanceof HeadlessExperiment) { String s = ((HeadlessExperiment) e).getName(); - if (EGaml.getInstance().isBatch(e)) { - s = GamlFileInfo.BATCH_PREFIX + s; - } + if (EGaml.getInstance().isBatch(e)) { s = GamlFileInfo.BATCH_PREFIX + s; } - if (exps == null) { - exps = new LinkedHashSet(); - } + if (exps == null) { exps = new LinkedHashSet(); } exps.add(s); } } @@ -159,6 +153,11 @@ public ISyntacticElement getContents(final URI uri) { } } + /** + * Clear resource set. + * + * @param resourceSet the resource set + */ protected void clearResourceSet(final ResourceSet resourceSet) { final boolean wasDeliver = resourceSet.eDeliver(); try { @@ -171,10 +170,13 @@ protected void clearResourceSet(final ResourceSet resourceSet) { } } + /** + * Gets the resource set. + * + * @return the resource set + */ private XtextResourceSet getResourceSet() { - if (resourceSet == null) { - resourceSet = new SynchronizedXtextResourceSet(); - } + if (resourceSet == null) { resourceSet = new SynchronizedXtextResourceSet(); } return resourceSet; } diff --git a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResourceServices.java b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResourceServices.java index d5debb876b..6029fb541e 100644 --- a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResourceServices.java +++ b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/resource/GamlResourceServices.java @@ -348,7 +348,7 @@ public static String getProjectPathOf(final Resource r) { imports.put(uri, null); if (r != null) { imports.put(r.getURI(), null); - final Map uris = GamlResourceIndexer.allLabeledImportsOf(r); + final Map uris = GamlResourceIndexer.allImportsOf(r); imports.putAll(uris); } result.getCache().getOrCreate(result).set(GamlResourceIndexer.IMPORTED_URIS, imports); @@ -404,4 +404,19 @@ private static XtextResourceSet getPoolSet() { return poolSet; } + /** + * Equals. + * + * @param uri1 + * the uri 1 + * @param uri2 + * the uri 2 + * @return true, if successful + */ + public static boolean equals(final URI uri1, final URI uri2) { + if (uri1 == null) return uri2 == null; + if (uri2 == null) return false; + return properlyEncodedURI(uri1).equals(properlyEncodedURI(uri2)); + } + } diff --git a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/scoping/BuiltinGlobalScopeProvider.java b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/scoping/BuiltinGlobalScopeProvider.java index 4d3beebcb9..2a0607081f 100644 --- a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/scoping/BuiltinGlobalScopeProvider.java +++ b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/scoping/BuiltinGlobalScopeProvider.java @@ -1,9 +1,9 @@ /******************************************************************************************************* * * BuiltinGlobalScopeProvider.java, in msi.gama.lang.gaml, is part of the source code of the GAMA modeling and - * simulation platform (v.2.0.0). + * simulation platform (v.1.8.2). * - * (c) 2007-2021 UMI 209 UMMISCO IRD/SU & Partners (IRIT, MIAT, TLU, CTU) + * (c) 2007-2022 UMI 209 UMMISCO IRD/SU & Partners (IRIT, MIAT, TLU, CTU) * * Visit https://github.com/gama-platform/gama for license information and contacts. * @@ -16,8 +16,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -25,7 +23,6 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.xtext.naming.QualifiedName; import org.eclipse.xtext.resource.EObjectDescription; import org.eclipse.xtext.resource.IEObjectDescription; @@ -44,7 +41,6 @@ import msi.gama.lang.gaml.EGaml; import msi.gama.lang.gaml.gaml.GamlDefinition; import msi.gama.lang.gaml.gaml.GamlPackage; -import msi.gama.lang.gaml.indexer.GamlResourceIndexer; import msi.gama.lang.gaml.resource.GamlResource; import msi.gama.lang.gaml.resource.GamlResourceServices; import msi.gama.runtime.GAMA; @@ -76,6 +72,10 @@ * * @author Vincent Simonet, adapted for GAML by Alexis Drogoul, 2012 */ + +/** + * The Class BuiltinGlobalScopeProvider. + */ @Singleton @SuppressWarnings ({ "unchecked", "rawtypes" }) public class BuiltinGlobalScopeProvider extends ImportUriGlobalScopeProvider implements IUnits { @@ -407,8 +407,7 @@ static void add(final EClass eClass, final String t, final OperatorProto o) { public static GamlDefinition addWithDoc(final String t, final IGamlDescription o, final String keyword, final EClass... classes) { -// DEBUG.OUT("Adding stub for " + keyword + " " + t); - + // DEBUG.OUT("Adding stub for " + keyword + " " + t); GamlDefinition stub = null; QualifiedName qName = QualifiedName.create(t); @@ -558,37 +557,19 @@ public static void createDescriptions() { } } - /** - * Gets the all imported URIs. - * - * @param resource - * the resource - * @param set - * the set - * @return the all imported UR is - */ - public Map getAllImportedURIs(final Resource resource, final ResourceSet set) { - return GamlResourceIndexer.allLabeledImportsOf((GamlResource) resource); - } - - @Override - protected LinkedHashSet getImportedUris(final Resource resource) { - LinkedHashSet result = new LinkedHashSet<>(); - Iterator uris = allImportsOf(resource.getURI()); - while (uris.hasNext()) { result.add(uris.next()); } - return result; - } @Override protected IScope getScope(final Resource resource, final boolean ignoreCase, final EClass type, final Predicate filter) { IScope scope = getGlobalScope(type); - final Collection uniqueImportURIs = getAllImportedURIs(resource, resource.getResourceSet()).keySet(); - if (uniqueImportURIs.size() == 1) return scope; - final List urisAsList = Lists.newArrayList(uniqueImportURIs); - urisAsList.remove(resource.getURI()); - Collections.reverse(urisAsList); - final IResourceDescriptions descriptions = getResourceDescriptions(resource, urisAsList); + Collection imports = allImportsOf((GamlResource) resource).keySet(); + int size = imports.size(); + if (size == 0) return scope; + if (size > 1) { + imports = Lists.newArrayList(imports); + Collections.reverse((List) imports); + } + final IResourceDescriptions descriptions = getResourceDescriptions(resource, imports); return SelectableBasedScope.createScope(scope, descriptions, filter, type, false); } @@ -604,12 +585,17 @@ public static IEObjectDescription getVar(final String name) { return descriptions.get(eVar).get(QualifiedName.create(name)); } - - public static XtextResourceSet getResourceSet() { - return rs; - } + /** + * Gets the resource set. + * + * @return the resource set + */ + public static XtextResourceSet getResourceSet() { return rs; } - public static IMap getResources() { - return resources; - } + /** + * Gets the resources. + * + * @return the resources + */ + public static IMap getResources() { return resources; } } diff --git a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/validation/ErrorToDiagnoticTranslator.java b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/validation/ErrorToDiagnoticTranslator.java index 89a902b050..8e71a91283 100644 --- a/msi.gama.lang.gaml/src/msi/gama/lang/gaml/validation/ErrorToDiagnoticTranslator.java +++ b/msi.gama.lang.gaml/src/msi/gama/lang/gaml/validation/ErrorToDiagnoticTranslator.java @@ -33,8 +33,8 @@ import msi.gama.lang.gaml.gaml.Model; import msi.gama.lang.gaml.gaml.Statement; import msi.gama.lang.gaml.gaml.impl.StatementImpl; -import msi.gama.lang.gaml.indexer.GamlResourceIndexer; import msi.gama.lang.gaml.resource.GamlResource; +import msi.gama.lang.gaml.resource.GamlResourceServices; import msi.gaml.compilation.GamlCompilationError; import msi.gaml.descriptions.ValidationContext; @@ -57,7 +57,7 @@ public Diagnostic translate(final ValidationContext errors, final GamlResource r public Diagnostic translate(final GamlCompilationError e, final GamlResource r, final CheckMode mode) { final URI errorURI = e.getURI(); - if (!GamlResourceIndexer.equals(errorURI, r.getURI())) { + if (!GamlResourceServices.equals(errorURI, r.getURI())) { // final String uri = URI.decode(errorURI.toFileString()); final String s = URI.decode(errorURI.lastSegment()); final EObject m = r.getContents().get(0);