Added new field TypeId to dependency index for exact type searching 58/3758/1
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 3 Jan 2020 11:51:33 +0000 (13:51 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Fri, 3 Jan 2020 12:34:38 +0000 (14:34 +0200)
The new field is String-valued and contains a concatenation of the
resource ids of a resource's type hierarchy, separated by a whitespace,
for example `41233 12423 1233`. This field uses the WhitespaceAnalyzer,
i.e. its contents are tokenized by whitespace and thus searches like
`TypeId:41233` will return exactly those resources that are instances of
the type resource `41233`.

This commit also simplifies and fixes some of the existing index
searching code to use this new field instead of the old `Types` field
for type-based searching.

If existing product-code uses the indexing facilities directly and not
through `QueryIndexUtils` or `Instances`, such code will also require
changes to take this new field into use.

See `IndexQueries` to form queries related to this field.

gitlab #438

Change-Id: I9992ad32a9e6da41c88641e60fed6e1793253738

14 files changed:
bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexUtils.java
bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsMemorySearcher.java
bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/IndexedRelationsSearcherBase.java
bundles/org.simantics.db.indexing/src/org/simantics/db/indexing/Queries.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/EntityInstances.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Dependencies.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependenciesRelation.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Entry.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/IndexQueries.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/IndexedInstances.java
bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/SearchResourceDialog.java
bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/ExistingInstancesRemover.java
bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/Removers.java
bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java

index 26a6e68ae9f9378dd4b7a429c7ac2ccdbe317684..760acd68c465578b269cdf12e164dafbb65a2516 100644 (file)
@@ -91,7 +91,7 @@ public class IndexUtils {
     public static Collection<Resource> findByName(ReadGraph graph, Resource model, String name) throws DatabaseException {
         Layer0 L0 = Layer0.getInstance(graph);
         HashSet<Resource> results = new HashSet<Resource>();
-        
+
         String search = IndexQueries.quoteTerm(Dependencies.FIELD_NAME, name);
 
         for(Resource resource : findResources(graph, model, search)) {
@@ -101,29 +101,21 @@ public class IndexUtils {
     }
 
     public static Collection<Resource> findByType(ReadGraph graph, Resource model, Resource type) throws DatabaseException {
-       
-        HashSet<Resource> results = new HashSet<Resource>();
-        Layer0 L0 = Layer0.getInstance(graph);
-        String typeName = graph.getRelatedValue(type, L0.HasName, Bindings.STRING);
-        String search = IndexQueries.quoteTerm(Dependencies.FIELD_TYPES, typeName);
+        HashSet<Resource> results = new HashSet<>();
+        String search = IndexQueries.resourceIdTerm(Dependencies.FIELD_TYPE_RESOURCE, type);
 
         for(Resource resource : findResources(graph, model, search)) {
-               if(graph.isInstanceOf(resource, type)) results.add(resource);
+            if(graph.isInstanceOf(resource, type)) results.add(resource);
         }
         return results;
     }
 
     public static Collection<Resource> findByTypeAndName(ReadGraph graph, Resource model, Resource type, String name) throws DatabaseException {
-       
-        Layer0 L0 = Layer0.getInstance(graph);
-        
         HashSet<Resource> results = new HashSet<Resource>();
-        String typeName = graph.getRelatedValue(type, L0.HasName, Bindings.STRING);
-        
-        String search = IndexQueries.and(IndexQueries.quoteTerm(Dependencies.FIELD_TYPES, typeName), IndexQueries.quoteTerm(Dependencies.FIELD_NAME, name));
+        String search = IndexQueries.and(IndexQueries.resourceIdTerm(Dependencies.FIELD_TYPE_RESOURCE, type), IndexQueries.quoteTerm(Dependencies.FIELD_NAME, name));
 
         for(Resource resource : findResources(graph, model, search)) {
-               if(graph.isInstanceOf(resource, type)) results.add(resource);
+            if(graph.isInstanceOf(resource, type)) results.add(resource);
         }
         return results;
     }
index d1282c766f968db9cb6539071666659f8c877042..0275c2e00a6274a117c55b88d7fb0d8d9ae17d88 100644 (file)
@@ -126,9 +126,7 @@ public class IndexedRelationsMemorySearcher extends IndexedRelationsSearcherBase
         }
 
         changeState(monitor, session, State.READY);
-        
-//        closeInternal();
-        
+
         return result;
 
     }
@@ -137,10 +135,8 @@ public class IndexedRelationsMemorySearcher extends IndexedRelationsSearcherBase
         try {
             if(writer != null)
                 writer.commit();
-        } catch (CorruptIndexException e) {
-            e.printStackTrace();
         } catch (IOException e) {
-            e.printStackTrace();
+            getLogger().error("Index commit failed", e);
         }
     }
 
index afcaafd51858229f8ac153c535493c1711717cef..5df5d68c114d37dc98de59bd6a45100e81dfda3d 100644 (file)
@@ -347,6 +347,7 @@ abstract public class IndexedRelationsSearcherBase {
                     removedTerm = new Term(key, (String) keyValue);
                 } else {
                     // FIXME: should throw an exception for illegal input data but this would leave the index in an incoherent state
+                    getLogger().error("Attempting to remove document from index of {} with key {} and unrecognized key value type {} : {}", input, key, keyValue, keyValue != null ? keyValue.getClass() : "null");
                     continue;
                 }
 
@@ -433,7 +434,7 @@ abstract public class IndexedRelationsSearcherBase {
                     boolean done = false;
                     if(requireChangeInfoOnReplace()) {
                            TopDocs exist = searcher.search(new TermQuery(removedTerm), null, 2);
-                           if(exist.scoreDocs.length == 1 && requireChangeInfoOnReplace()) {
+                           if(exist.scoreDocs.length == 1) {
                                Document doc = reader.document(exist.scoreDocs[0].doc);
                                if(!areSame(doc, document)) {
                                    writer.deleteDocuments(removedTerm);
index 21b32fa1ecd14d1ae0a5238095365d4dbd56f6ff..eab6a7a121d283adf10f88e95cce33efe3ca539d 100644 (file)
@@ -136,20 +136,21 @@ public class Queries {
     final static PerFieldAnalyzerWrapper analyzer = createAnalyzer();
     
     static PerFieldAnalyzerWrapper createAnalyzer() {
-       
-       Map<String,Analyzer> analyzerPerField = new HashMap<>();
-       analyzerPerField.put("Model", new KeywordAnalyzer());
-       analyzerPerField.put("Parent", new KeywordAnalyzer());
-       analyzerPerField.put("Resource", new KeywordAnalyzer());
-       analyzerPerField.put("GUID", new KeywordAnalyzer());
-       analyzerPerField.put("Name", new KeywordAnalyzer());
-       analyzerPerField.put("Types", new TypeStringAnalyzer(false));
-       analyzerPerField.put(Dependencies.FIELD_NAME_SEARCH, new LowerCaseWhitespaceAnalyzer(Version.LUCENE_4_9));
-       analyzerPerField.put(Dependencies.FIELD_TYPES_SEARCH, new TypeStringAnalyzer(true));
-       
+
+        Map<String,Analyzer> analyzerPerField = new HashMap<>();
+        analyzerPerField.put(Dependencies.FIELD_MODEL, new KeywordAnalyzer());
+        analyzerPerField.put(Dependencies.FIELD_PARENT, new KeywordAnalyzer());
+        analyzerPerField.put(Dependencies.FIELD_RESOURCE, new KeywordAnalyzer());
+        analyzerPerField.put(Dependencies.FIELD_GUID, new KeywordAnalyzer());
+        analyzerPerField.put(Dependencies.FIELD_NAME, new KeywordAnalyzer());
+        analyzerPerField.put(Dependencies.FIELD_TYPES, new TypeStringAnalyzer(false));
+        analyzerPerField.put(Dependencies.FIELD_NAME_SEARCH, new LowerCaseWhitespaceAnalyzer(Version.LUCENE_4_9));
+        analyzerPerField.put(Dependencies.FIELD_TYPES_SEARCH, new TypeStringAnalyzer(true));
+        analyzerPerField.put(Dependencies.FIELD_TYPE_RESOURCE, new WhitespaceAnalyzer(Version.LUCENE_4_9));
+
         PerFieldAnalyzerWrapper analyzer = new PerFieldAnalyzerWrapper(new LowerCaseWhitespaceAnalyzer(Version.LUCENE_4_9), analyzerPerField);
         return analyzer;
-        
+
     }
 
     static PerFieldAnalyzerWrapper getAnalyzer() {
index ffbec2f5e01ca88222926bb1c03848ed940d692a..838728b17c98169b8f937c09ae811ccdd3bff82e 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2019 Association for Decentralized Information Management
  * in Industry THTH ry.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -17,7 +17,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
-import org.simantics.databoard.Bindings;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.common.primitiverequest.Adapter;
@@ -26,6 +25,7 @@ import org.simantics.db.common.request.ObjectsWithType;
 import org.simantics.db.common.request.TernaryRead;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.adapter.Instances;
+import org.simantics.db.layer0.genericrelation.Dependencies;
 import org.simantics.db.layer0.genericrelation.IndexQueries;
 import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.db.request.ReadExt;
@@ -116,10 +116,7 @@ public class EntityInstances implements Instances {
             StringBuilder sb = new StringBuilder();
             boolean emptyFilter = filter.isEmpty();
             if (emptyFilter || !type.equals(L0.Entity)) {
-                String typeName = graph.getPossibleRelatedValue(type, L0.HasName, Bindings.STRING);
-                if (typeName == null || typeName.isEmpty())
-                    return null;
-                sb.append("Types:").append( IndexQueries.quoteTerm(typeName) );
+                IndexQueries.appendResourceIdTerm(sb, Dependencies.FIELD_TYPE_RESOURCE, type);
             }
             if (!emptyFilter) {
                 if (sb.length() > 0)
index 3ca66ce773aa9fe433fb5fe2ab36d27794f56e0a..0aa36390b6030ed4068ed99ed9c5160640feeb73 100644 (file)
@@ -38,13 +38,14 @@ public class Dependencies extends FunctionImpl4<ReadGraph, Resource, String, Int
     public static final String FIELD_GUID    = "GUID";
     public static final String FIELD_NAME_SEARCH = "NameSearch";
     public static final String FIELD_TYPES_SEARCH = "TypesSearch";
+    public static final String FIELD_TYPE_RESOURCE = "TypeId";
 
     protected Resource getIndexRelation(ReadGraph graph) {
         return Layer0X.getInstance(graph).DependenciesRelation;
     }
 
     protected static String getBindingPattern() {
-        return "bfffffff";
+        return "bffffffff";
     }
 
     @Override
index 6f310120bc6f5c5cc6eb9bbf0469199091a471ac..771bf8649df554121b0af9e86405d538b89422d0 100644 (file)
@@ -18,6 +18,7 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
 
 import org.simantics.databoard.Bindings;
@@ -79,7 +80,8 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic
                Pair.make(Dependencies.FIELD_TYPES, "Text"),
                Pair.make(Dependencies.FIELD_GUID, "Text"),
                Pair.make(Dependencies.FIELD_NAME_SEARCH, "Text"),
-               Pair.make(Dependencies.FIELD_TYPES_SEARCH, "Text")
+               Pair.make(Dependencies.FIELD_TYPES_SEARCH, "Text"),
+               Pair.make(Dependencies.FIELD_TYPE_RESOURCE, "Text")
        };
 
        final Resource resource;
@@ -175,30 +177,31 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic
 
                        });
 
-            Map<Resource, String> typeStrings = cs.createMap(String.class);
+                       Map<Resource, Pair<String, String>> typeStrings = cs.createMap(String.class);
                        for(Entry e : result) {
                                if(e.principalType != null) {
-                                   String typeString = typeStrings.get(e.principalType);
-                                   if(typeString == null) {
-                                       typeString = graph.syncRequest(new SuperTypeString(e.principalType));
-                                       if (typeString.isEmpty()) {
-                                           LOGGER.error("No name for type", new DatabaseException("No name for type " + NameUtils.getURIOrSafeNameInternal(graph, e.resource) + " (" + e.resource + ")"));
-                                       }
-                                       typeStrings.put(e.principalType, typeString);
-                                   }
-                                   e.types = typeString;
+                                       Pair<String, String> typeString = typeStrings.get(e.principalType);
+                                       if(typeString == null) {
+                                               String superTypeString = graph.syncRequest(new SuperTypeString(e.principalType));
+                                               if (superTypeString.isEmpty()) {
+                                                       LOGGER.error("No name for type", new DatabaseException("No name for type " + NameUtils.getURIOrSafeNameInternal(graph, e.resource) + " (" + e.resource + ")"));
+                                               }
+                                               String superTypeIds = IndexQueries.toResourceIdString(e.principalType, graph.getSupertypes(e.principalType));
+                                               typeString = Pair.make(superTypeString, superTypeIds);
+                                               typeStrings.put(e.principalType, typeString);
+                                       }
+                                       e.types = typeString.first;
+                                       e.typeId = typeString.second;
                                } else {
-                                   e.types = graph.syncRequest(new TypeString(L0, graph.getTypes(e.resource)));
+                                       Set<Resource> typeSet = graph.getTypes(e.resource);
+                                       e.types = graph.syncRequest(new TypeString(L0, typeSet));
+                                       e.typeId = IndexQueries.toResourceIdString(typeSet);
                                }
-                               GUID id = graph.getPossibleRelatedValue(e.resource, L0.identifier, GUID.BINDING);
-                               if(id != null)
-                                       e.id = id.indexString();
-                               else 
-                                       e.id = "";
+                               e.id = IndexQueries.idFromGUID( graph.getPossibleRelatedValue(e.resource, L0.identifier, GUID.BINDING) );
                        }
 
                        //SessionGarbageCollection.gc(null, graph.getSession(), false, null);
-                       
+
                }
 
        }
@@ -223,10 +226,10 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic
 
                                long time = System.nanoTime();
 
-                SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+                               SerialisationSupport ss = graph.getService(SerialisationSupport.class);
 
                                Resource subject = ss.getResource(subjectId); 
-                               
+
                                Collection<Entry> entries = find(graph, subject);
 
                                long time2 = System.nanoTime();
@@ -234,10 +237,10 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic
                                if (PROFILE)
                                        LOGGER.info("Found " + entries.size() + " dependencies in " + 1e-6 * (time2 - time) + "ms for " + graph.getPossibleURI(subject) + ".");
 
-                               ArrayList<Object[]> result = new ArrayList<Object[]>();
+                               ArrayList<Object[]> result = new ArrayList<>();
                                for (Entry entry : entries) {
                                        if(entry.name == null) continue;
-                                       result.add(new Object[] { ss.getRandomAccessId(entry.parent), ss.getRandomAccessId(entry.resource), entry.name, entry.types, entry.id, entry.name, entry.types });
+                                       result.add(new Object[] { ss.getRandomAccessId(entry.parent), ss.getRandomAccessId(entry.resource), entry.name, entry.types, entry.id, entry.name, entry.types, entry.typeId });
                                }
                                return result;
 
@@ -360,201 +363,204 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic
        @Override
        public synchronized void trackAndIndex(RequestProcessor processor, Resource model__) {
 
-           if(trackers == 0) {
+               if(trackers == 0) {
 
-               if(listener != null) throw new IllegalStateException("Dependency tracking was active");
-
-               listener = new GenericChangeListener<DependencyChangesRequest, DependencyChanges>() {
-
-                   @Override
-                   public boolean preEventRequest() {
-                       return !Indexing.isDependenciesIndexingDisabled();
-                   }
-
-                   @Override
-                   public void onEvent(ReadGraph graph, MetadataI metadata, DependencyChanges event) throws DatabaseException {
-
-                       TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: starting index update processing");
-
-                       if(DEBUG)
-                           LOGGER.info("Adding metadata " + event + " in revision " + graph.getService(ManagementSupport.class).getHeadRevisionId());
-
-                       WriteGraph w = (WriteGraph)graph;
-                       if(!event.isEmpty())
-                               w.addMetadata(event);
-
-                       final Session session = graph.getSession();
-                       final IndexedRelations indexer = session.getService(IndexedRelations.class);
-                       Layer0 L0 = Layer0.getInstance(graph);
-                       SerialisationSupport ss = graph.getService(SerialisationSupport.class);
-
-                       for(Map.Entry<Resource, Change[]>  modelEntry : event.get().entrySet()) {
-
-                           final Resource model = modelEntry.getKey();
-                           final Change[] changes = modelEntry.getValue();
-
-                           boolean linkChange = false;
-
-                           Collection<Object[]> _additions = Collections.emptyList();
-                           Collection<Object> _removals = Collections.emptyList();
-                           Collection<Object> _replacementKeys = Collections.emptyList();
-                           Collection<Object[]> _replacementObjects = Collections.emptyList();
-                           Collection<Pair<String, String>> _typeChanges = Collections.emptyList();
-
-                           if(DEBUG) LOGGER.info("MODEL: " + NameUtils.getSafeLabel(graph, model));
-                           //                final Change[] changes = event.get(model);
-                           if(DEBUG) LOGGER.info("  CHANGES: " + Arrays.toString(changes));
-                           if (changes != null) {
-                               _additions = new ArrayList<Object[]>();
-                               _removals = new ArrayList<Object>();
-                               _replacementKeys = new ArrayList<Object>();
-                               _replacementObjects = new ArrayList<Object[]>();
-                               _typeChanges = new HashSet<Pair<String, String>>();
-
-                               for (Change _entry : changes) {
-                                   if (_entry instanceof ComponentAddition) {
-                                       ComponentAddition entry = (ComponentAddition)_entry;
-                                       final String name = graph.getPossibleRelatedValue(entry.component, L0.HasName, Bindings.STRING);
-                                       final GUID id = graph.getPossibleRelatedValue(entry.component, L0.identifier, GUID.BINDING);
-                                       final String types = graph.syncRequest(new TypeString(L0, graph.getTypes(entry.component)));
-                                       if (name != null && types != null) {
-                                               if(!entry.isValid(graph)) continue;
-                                           Resource parent = graph.getPossibleObject(entry.component, L0.PartOf);
-                                           if (parent != null) {
-                                               _additions.add(new Object[] { ss.getRandomAccessId(parent), ss.getRandomAccessId(entry.component), name, types, id != null ? id.indexString() : "", name, types});
-                                           } else {
-                                                   //LOGGER.info("resource " + entry.component + ": no parent for entry " + name + " " + types);
-                                           }
-                                       } else {
-                                           //LOGGER.info("resource " + entry.component + ": " + name + " " + types);
-                                       }
-                                   } else if(_entry instanceof ComponentModification) {
-                                       ComponentModification entry = (ComponentModification)_entry;
-                                       final String name = graph.getPossibleRelatedValue(entry.component, L0.HasName, Bindings.STRING);
-                                       final GUID id = graph.getPossibleRelatedValue(entry.component, L0.identifier, GUID.BINDING);
-                                       if(graph.isInstanceOf(entry.component, L0.Type)) {
-                                           SerialisationSupport support = session.getService(SerialisationSupport.class);
-                                           _typeChanges.add(new Pair<String, String>(name, String.valueOf(support.getRandomAccessId((Resource) entry.component))));
-                                       } else {
-                                           final String types = graph.syncRequest(new TypeString(L0, graph.getTypes(entry.component)));
-                                           if (name != null && types != null) {
-                                               Resource part = graph.getPossibleObject(entry.component, L0.PartOf);
-                                               if(part != null) {
-                                                   _replacementKeys.add(ss.getRandomAccessId(entry.component));
-                                                   _replacementObjects.add(new Object[] { ss.getRandomAccessId(part), 
-                                                           ss.getRandomAccessId(entry.component), name, types, id != null ? id.indexString() : "", name, types});
-                                               }
-                                           }
-                                       }
-                                   } else if (_entry instanceof ComponentRemoval) {
-                                       ComponentRemoval entry = (ComponentRemoval)_entry;
-                                       if(!entry.isValid(graph)) continue;
-                                       _removals.add(ss.getRandomAccessId(((ComponentRemoval)_entry).component));
-                                   } else if (_entry instanceof LinkChange) {
-                                       linkChange = true;
-                                   }
-                               }
-                           }
-
-                           final boolean reset = linkChange || event.hasUnresolved;
-                           //LOGGER.info("dependencies(" + NameUtils.getSafeLabel(graph, model) + "): reset=" + reset + " linkChange=" + linkChange + " unresolved=" + event.hasUnresolved );
-
-                           if (reset || !_additions.isEmpty() || !_removals.isEmpty() || !_replacementKeys.isEmpty() || !_typeChanges.isEmpty()) {
-
-                               TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: starting index update");
-
-                               final Collection<Object[]> additions = _additions;
-                               final Collection<Object> removals = _removals;
-                               final Collection<Object> replacementKeys = _replacementKeys;
-                               final Collection<Object[]> replacementObjects = _replacementObjects; 
-                               final boolean typeNameChanges = typeNameChanges(graph, indexer, model, _typeChanges);
-
-                            final UUID pending = Indexing.makeIndexPending();
-
-                            {
-                                {
-                                       try {
-                                           boolean didChange = false;
-                                           // Unresolved and linkChanges are not relevant any more
-                                           boolean doReset = typeNameChanges;
-
-                                           if (doReset) {
-
-                                            if(DEBUG) {
-                                                LOGGER.info("resetIndex " + reset + " " + typeNameChanges);
-                                            }
-
-                                               indexer.removeAll(null, graph, DependenciesRelation.this, resource, model);
-                                               didChange = true;
-
-                                           } else {
-
-                                               if (!replacementKeys.isEmpty() && (replacementKeys.size() == replacementObjects.size())) {
-                                                   if(DEBUG) {
-                                                       LOGGER.info(replacementKeys.size() + " index replacements: " + replacementKeys);
-                                                   }
-                                                   didChange |= indexer.replace(null, graph, DependenciesRelation.this, resource, model, Dependencies.FIELD_RESOURCE, replacementKeys, replacementObjects);
-                                               }
-                                               if (!removals.isEmpty()) {
-                                                   if(DEBUG) {
-                                                       LOGGER.info(removals.size() + " index removals: " + removals);
-                                                   }
-                                                   indexer.remove(null, graph, DependenciesRelation.this, resource, model, Dependencies.FIELD_RESOURCE, removals);
-                                                   didChange = true;
-                                               }
-                                               if (!additions.isEmpty()) {
-                                                   if(DEBUG) {
-                                                       for(Object[] os : additions) LOGGER.info("Adding to index " + model + ": " + Arrays.toString(os));
-                                                   }
-                                                   //LOGGER.info(additions.size() + " index insertions");
-                                                   indexer.insert(null, graph, DependenciesRelation.this, resource, model, additions);
-                                                   didChange = true;
-                                               }
-
-                                           }
-
-                                           if (didChange)
-                                               // TODO: because this data is ran with
-                                               // ThreadUtils.getBlockingWorkExecutor()
-                                               // fireListeners needs to use peekService,
-                                               // not getService since there is no
-                                               // guarantee that the session isn't being
-                                               // disposed while this method is executing.
-                                               fireListeners(graph, model);
-
-                                       } catch (Throwable t) {
-                                           // Just to know if something unexpected happens here.
-                                           LOGGER.error("Dependencies index update failed for model "
-                                                + model + " and relation " + resource + ".", t);
-
-                                           // NOTE: Last resort: failure to update index
-                                           // properly results in removal of the whole index.
-                                           // This is the only thing that can be done
-                                           // at this point to ensure that the index will
-                                           // return correct results in the future, through
-                                           // complete reinitialization. 
-                                           //indexer.removeAll(null, session, DependenciesRelation.this, resource, model);
-                                       } finally {
-                                           Indexing.releaseIndexPending(pending);
-                                           Indexing.clearCaches(model);
-                                       }
-                                }
-                            }
-
-                               TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: index update done");
-                           }
-                       }
-
-                   }
-
-               };
+                       if(listener != null) throw new IllegalStateException("Dependency tracking was active");
 
-               GraphChangeListenerSupport changeSupport = processor.getService(GraphChangeListenerSupport.class);
-               changeSupport.addMetadataListener(listener);
+                       listener = new GenericChangeListener<DependencyChangesRequest, DependencyChanges>() {
 
-           }
+                               @Override
+                               public boolean preEventRequest() {
+                                       return !Indexing.isDependenciesIndexingDisabled();
+                               }
+
+                               @Override
+                               public void onEvent(ReadGraph graph, MetadataI metadata, DependencyChanges event) throws DatabaseException {
+
+                                       TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: starting index update processing");
+
+                                       if(DEBUG)
+                                               LOGGER.info("Adding metadata " + event + " in revision " + graph.getService(ManagementSupport.class).getHeadRevisionId());
+
+                                       WriteGraph w = (WriteGraph)graph;
+                                       if(!event.isEmpty())
+                                               w.addMetadata(event);
+
+                                       final Session session = graph.getSession();
+                                       final IndexedRelations indexer = session.getService(IndexedRelations.class);
+                                       Layer0 L0 = Layer0.getInstance(graph);
+                                       SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+
+                                       for(Map.Entry<Resource, Change[]>  modelEntry : event.get().entrySet()) {
+
+                                               final Resource model = modelEntry.getKey();
+                                               final Change[] changes = modelEntry.getValue();
+
+                                               boolean linkChange = false;
+
+                                               Collection<Object[]> _additions = Collections.emptyList();
+                                               Collection<Object> _removals = Collections.emptyList();
+                                               Collection<Object> _replacementKeys = Collections.emptyList();
+                                               Collection<Object[]> _replacementObjects = Collections.emptyList();
+                                               Collection<Pair<String, String>> _typeChanges = Collections.emptyList();
+
+                                               if(DEBUG) LOGGER.info("MODEL: " + NameUtils.getSafeLabel(graph, model));
+                                               if (changes != null) {
+                                                       if (DEBUG) {
+                                                               LOGGER.info("  CHANGE COUNT: " + changes.length);
+                                                               for (Change c : changes)
+                                                                       LOGGER.info("    CHANGE: " + c.toString(graph));
+                                                       }
+                                                       _additions = new ArrayList<>();
+                                                       _removals = new ArrayList<>();
+                                                       _replacementKeys = new ArrayList<>();
+                                                       _replacementObjects = new ArrayList<>();
+                                                       _typeChanges = new HashSet<>();
+
+                                                       for (Change _entry : changes) {
+                                                               if (_entry instanceof ComponentAddition) {
+                                                                       ComponentAddition entry = (ComponentAddition)_entry;
+                                                                       final String name = graph.getPossibleRelatedValue(entry.component, L0.HasName, Bindings.STRING);
+                                                                       Set<Resource> typeSet = graph.getTypes(entry.component);
+                                                                       if (name != null && typeSet != null) {
+                                                                               if (!entry.isValid(graph))
+                                                                                       continue;
+                                                                               Resource parent = graph.getPossibleObject(entry.component, L0.PartOf);
+                                                                               if (parent != null) {
+                                                                                       final GUID id = graph.getPossibleRelatedValue(entry.component, L0.identifier, GUID.BINDING);
+                                                                                       final String types = graph.syncRequest(new TypeString(L0, typeSet));
+                                                                                       final String typeIds = IndexQueries.toResourceIdString(typeSet);
+                                                                                       _additions.add(new Object[] { ss.getRandomAccessId(parent), ss.getRandomAccessId(entry.component), name, types, IndexQueries.idFromGUID(id), name, types, typeIds});
+                                                                               } else {
+                                                                                       //LOGGER.info("resource " + entry.component + ": no parent for entry " + name + " " + types);
+                                                                               }
+                                                                       } else {
+                                                                               //LOGGER.info("resource " + entry.component + ": " + name + " " + types);
+                                                                       }
+                                                               } else if(_entry instanceof ComponentModification) {
+                                                                       ComponentModification entry = (ComponentModification)_entry;
+                                                                       final String name = graph.getPossibleRelatedValue(entry.component, L0.HasName, Bindings.STRING);
+                                                                       if(graph.isInstanceOf(entry.component, L0.Type)) {
+                                                                               SerialisationSupport support = session.getService(SerialisationSupport.class);
+                                                                               _typeChanges.add(new Pair<String, String>(name, String.valueOf(support.getRandomAccessId((Resource) entry.component))));
+                                                                       } else {
+                                                                               Set<Resource> typeSet = graph.getTypes(entry.component);
+                                                                               if (name != null && !typeSet.isEmpty()) {
+                                                                                       Resource part = graph.getPossibleObject(entry.component, L0.PartOf);
+                                                                                       if(part != null) {
+                                                                                               final GUID id = graph.getPossibleRelatedValue(entry.component, L0.identifier, GUID.BINDING);
+                                                                                               final String types = graph.syncRequest(new TypeString(L0, typeSet));
+                                                                                               final String typeIds = IndexQueries.toResourceIdString(typeSet);
+                                                                                               _replacementKeys.add(ss.getRandomAccessId(entry.component));
+                                                                                               _replacementObjects.add(new Object[] { ss.getRandomAccessId(part), 
+                                                                                                               ss.getRandomAccessId(entry.component), name, types, IndexQueries.idFromGUID(id), name, types, typeIds});
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               } else if (_entry instanceof ComponentRemoval) {
+                                                                       ComponentRemoval entry = (ComponentRemoval)_entry;
+                                                                       if(!entry.isValid(graph)) continue;
+                                                                       _removals.add(ss.getRandomAccessId(((ComponentRemoval)_entry).component));
+                                                               } else if (_entry instanceof LinkChange) {
+                                                                       linkChange = true;
+                                                               }
+                                                       }
+                                               }
+
+                                               final boolean reset = linkChange || event.hasUnresolved;
+                                               //LOGGER.info("dependencies(" + NameUtils.getSafeLabel(graph, model) + "): reset=" + reset + " linkChange=" + linkChange + " unresolved=" + event.hasUnresolved );
+
+                                               if (reset || !_additions.isEmpty() || !_removals.isEmpty() || !_replacementKeys.isEmpty() || !_typeChanges.isEmpty()) {
+
+                                                       TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: starting index update");
+
+                                                       final Collection<Object[]> additions = _additions;
+                                                       final Collection<Object> removals = _removals;
+                                                       final Collection<Object> replacementKeys = _replacementKeys;
+                                                       final Collection<Object[]> replacementObjects = _replacementObjects; 
+                                                       final boolean typeNameChanges = typeNameChanges(graph, indexer, model, _typeChanges);
+
+                                                       final UUID pending = Indexing.makeIndexPending();
+                                                       try {
+                                                               boolean didChange = false;
+                                                               // Unresolved and linkChanges are not relevant any more
+                                                               boolean doReset = typeNameChanges;
+
+                                                               if (doReset) {
+
+                                                                       if(DEBUG) {
+                                                                               LOGGER.info("resetIndex " + reset + " " + typeNameChanges);
+                                                                       }
+
+                                                                       indexer.removeAll(null, graph, DependenciesRelation.this, resource, model);
+                                                                       didChange = true;
+
+                                                               } else {
+
+                                                                       if (!replacementKeys.isEmpty() && (replacementKeys.size() == replacementObjects.size())) {
+                                                                               if(DEBUG) {
+                                                                                       LOGGER.info(replacementKeys.size() + " index replacements: " + replacementKeys);
+                                                                               }
+                                                                               didChange |= indexer.replace(null, graph, DependenciesRelation.this, resource, model, Dependencies.FIELD_RESOURCE, replacementKeys, replacementObjects);
+                                                                       }
+                                                                       if (!removals.isEmpty()) {
+                                                                               if(DEBUG) {
+                                                                                       LOGGER.info(removals.size() + " index removals: " + removals);
+                                                                               }
+                                                                               indexer.remove(null, graph, DependenciesRelation.this, resource, model, Dependencies.FIELD_RESOURCE, removals);
+                                                                               didChange = true;
+                                                                       }
+                                                                       if (!additions.isEmpty()) {
+                                                                               if(DEBUG) {
+                                                                                       for(Object[] os : additions) LOGGER.info("Adding to index " + model + ": " + Arrays.toString(os));
+                                                                               }
+                                                                               //LOGGER.info(additions.size() + " index insertions");
+                                                                               indexer.insert(null, graph, DependenciesRelation.this, resource, model, additions);
+                                                                               didChange = true;
+                                                                       }
+
+                                                               }
+
+                                                               if (didChange)
+                                                                       // TODO: because this data is ran with
+                                                                       // ThreadUtils.getBlockingWorkExecutor()
+                                                                       // fireListeners needs to use peekService,
+                                                                       // not getService since there is no
+                                                                       // guarantee that the session isn't being
+                                                                       // disposed while this method is executing.
+                                                                       fireListeners(graph, model);
+
+                                                       } catch (Throwable t) {
+                                                               // Just to know if something unexpected happens here.
+                                                               LOGGER.error("Dependencies index update failed for model "
+                                                                               + model + " and relation " + resource + ".", t);
+
+                                                               // NOTE: Last resort: failure to update index
+                                                               // properly results in removal of the whole index.
+                                                               // This is the only thing that can be done
+                                                               // at this point to ensure that the index will
+                                                               // return correct results in the future, through
+                                                               // complete reinitialization. 
+                                                               //indexer.removeAll(null, session, DependenciesRelation.this, resource, model);
+                                                       } finally {
+                                                               Indexing.releaseIndexPending(pending);
+                                                               Indexing.clearCaches(model);
+                                                       }
+
+                                                       TimeLogger.log(DependenciesRelation.class, "trackAndIndex.onEvent: index update done");
+                                               }
+                                       }
 
-           trackers++;
+                               }
+
+                       };
+
+                       GraphChangeListenerSupport changeSupport = processor.getService(GraphChangeListenerSupport.class);
+                       changeSupport.addMetadataListener(listener);
+
+               }
+
+               trackers++;
 
        }
 
@@ -617,22 +623,22 @@ public class DependenciesRelation extends UnsupportedRelation implements Generic
        }
 
        public static void addSubtree(ReadGraph graph, Resource indexRoot, Resource subtreeRoot) throws DatabaseException {
-               
+
                DependenciesRelation dr = new DependenciesRelation(graph, indexRoot);
-        SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+               SerialisationSupport ss = graph.getService(SerialisationSupport.class);
 
-        ArrayList<Entry> entries = dr.find(graph, subtreeRoot);
-        entries.add(new Entry(graph, subtreeRoot));
+               ArrayList<Entry> entries = dr.find(graph, subtreeRoot);
+               entries.add(new Entry(graph, subtreeRoot));
 
                ArrayList<Object[]> result = new ArrayList<Object[]>(entries.size());
                for (Entry entry : entries) {
-                       result.add(new Object[] { ss.getRandomAccessId(entry.parent), ss.getRandomAccessId(entry.resource), entry.name, entry.types, entry.id, entry.name, entry.types });
+                       result.add(new Object[] { ss.getRandomAccessId(entry.parent), ss.getRandomAccessId(entry.resource), entry.name, entry.types, entry.id, entry.name, entry.types, entry.typeId });
                }
 
                Layer0X L0X = Layer0X.getInstance(graph);
-        IndexedRelations indexer = graph.getService(IndexedRelations.class);
-        indexer.insert(null, graph, dr, L0X.DependenciesRelation, indexRoot, result);
-               
+               IndexedRelations indexer = graph.getService(IndexedRelations.class);
+               indexer.insert(null, graph, dr, L0X.DependenciesRelation, indexRoot, result);
+
        }
-       
+
 }
index 8da8209499665c4f4ff9c60d0889d9a39d9a46ef..50d723ec9b1ae7d77a8c54ce4358cdafd89e8bb6 100644 (file)
@@ -1,5 +1,7 @@
 package org.simantics.db.layer0.genericrelation;
 
+import java.util.Set;
+
 import org.simantics.databoard.Bindings;
 import org.simantics.datatypes.literal.GUID;
 import org.simantics.db.ReadGraph;
@@ -22,13 +24,10 @@ class Entry implements Comparable<Entry> {
                this.parent = graph.getPossibleObject(resource, L0.PartOf);
                this.resource = resource;
                this.name = graph.getPossibleRelatedValue(resource, L0.HasName, Bindings.STRING);
-               this.types = graph.syncRequest(new TypeString(L0, graph.getTypes(resource)));
-               this.id = idFromGUID(graph.getPossibleRelatedValue(resource, L0.identifier, GUID.BINDING));
-       }
-       
-       private static String idFromGUID(GUID guid) {
-               if(guid == null) return "";
-               return guid.indexString();
+               Set<Resource> typeSet = graph.getTypes(resource);
+               this.types = graph.syncRequest(new TypeString(L0, typeSet));
+               this.id = IndexQueries.idFromGUID(graph.getPossibleRelatedValue(resource, L0.identifier, GUID.BINDING));
+               this.typeId = IndexQueries.toResourceIdString(typeSet);
        }
 
        Entry(ReadGraph graph, Resource resource) throws DatabaseException {
@@ -41,6 +40,7 @@ class Entry implements Comparable<Entry> {
        String types;
        String name;
        String id;
+       String typeId;
        Resource principalType;
 
        @Override
index 2be6bf5d0e1f270655ed0828acbc07975e075b52..ee6296fdd4ecb7a1fbc02e4934119f456aabf0f1 100644 (file)
@@ -1,5 +1,9 @@
 package org.simantics.db.layer0.genericrelation;
 
+import java.util.Collection;
+
+import org.simantics.datatypes.literal.GUID;
+import org.simantics.db.Resource;
 
 /**
  * This class contains utilities related to queries made into Lucene indexes,
@@ -183,6 +187,22 @@ public class IndexQueries {
                                ).toString();
        }
 
+       public static StringBuilder appendLongTerm(StringBuilder sb, String field, long term) {
+               return sb.append(field).append(':').append(term);
+       }
+
+       public static String longTerm(String field, long term) {
+               return appendLongTerm(new StringBuilder(), field, term).toString();
+       }
+
+       public static StringBuilder appendResourceIdTerm(StringBuilder sb, String field, Resource term) {
+               return appendLongTerm(sb, field, term.getResourceId());
+       }
+
+       public static String resourceIdTerm(String field, Resource term) {
+               return appendLongTerm(new StringBuilder(), field, term.getResourceId()).toString();
+       }
+
        private static String join(String withString, String... exps) {
                if (exps.length == 0)
                        return "";
@@ -210,6 +230,32 @@ public class IndexQueries {
                return join(" OR ", exps);
        }
 
+       public static String idFromGUID(GUID guid) {
+               return guid != null ? guid.indexString() : "";
+       }
+
+       public static String toResourceIdString(Resource r, Collection<Resource> rs) {
+               StringBuilder sb = new StringBuilder();
+               sb.append(r.getResourceId());
+               for (Resource rr : rs)
+                       sb.append(' ').append(rr.getResourceId());
+               return sb.toString();
+       }
+
+       public static String toResourceIdString(Collection<Resource> rs) {
+               if (rs.isEmpty())
+                       return "";
+               StringBuilder sb = new StringBuilder();
+               boolean first = true;
+               for (Resource rr : rs) {
+                       if (!first)
+                               sb.append(' ');
+                       first = false;
+                       sb.append(rr.getResourceId());
+               }
+               return sb.toString();
+       }
+
 //     public static void main(String[] args) {
 //             System.out.println("esc: " + escape("AND01", true, true));
 //             System.out.println("esc: " + escape("AND 01", true, true));
index 09a1fc9021c77ee6440e93aeb84c87a68baf175d..57aefa5197798d3a8a2be227dc197c8a8999d6fb 100644 (file)
@@ -1,19 +1,13 @@
 package org.simantics.db.layer0.request;
 
-import java.util.Collection;
-import java.util.Collections;
 import java.util.HashSet;
-import java.util.Map;
 import java.util.Set;
 
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.common.request.ResourceRead2;
 import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.genericrelation.IndexQueries;
-import org.simantics.layer0.Layer0;
-import org.simantics.operation.Layer0X;
-import org.simantics.scl.runtime.function.Function;
+import org.simantics.db.layer0.QueryIndexUtils;
 
 public class IndexedInstances extends ResourceRead2<Set<Resource>> {
 
@@ -23,28 +17,7 @@ public class IndexedInstances extends ResourceRead2<Set<Resource>> {
 
        @Override
        public Set<Resource> perform(ReadGraph graph) throws DatabaseException {
-               
-        Layer0 L0 = Layer0.getInstance(graph);
-        Layer0X L0X = Layer0X.getInstance(graph);
-
-        String typeName = graph.getRelatedValue(resource, L0.HasName);
-
-        Function dependencies = graph.adapt(L0X.Dependencies, Function.class);
-        
-        Collection<Map<String, Object>> results = (Collection<Map<String, Object>>)dependencies.apply(graph, resource2, "Types:" + IndexQueries.quoteTerm(typeName));
-        if (results == null)
-            return Collections.emptySet();
-
-        HashSet<Resource> result = new HashSet<Resource>(results.size());
-        for(Map<String, Object> entry : results) {
-            Resource res = (Resource)entry.get("Resource");
-            if(res != null) {
-               if (graph.isInstanceOf(res, resource))
-                       result.add(res);
-            }
-        }
-        return result;
-               
+               return new HashSet<>(QueryIndexUtils.searchByTypeShallow(graph, resource2, resource));
        }
 
 }
index 06710f6e29bd03a3dec4ecbdc50d5f4afdbd4b64..591436dc529ec8329cd41890b1c0f3cb7e63b7d2 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2016 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2019 Association for Decentralized Information Management
  * in Industry THTH ry.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
@@ -311,8 +311,9 @@ public class SearchResourceDialog extends FilteredItemsSelectionDialog {
 
                             Resource project = Simantics.peekProjectResource();
                             if (project != null) {
+                                Layer0 L0 = Layer0.getInstance(graph);
                                 IResourceFilter rf = resourceFilter;
-                                String filter = getFilterForResourceFilter(rf);
+                                String filter = getFilterForResourceFilter(L0, rf);
                                 if (!filter.isEmpty())
                                     filter += " AND "; //$NON-NLS-1$
                                 
@@ -320,8 +321,6 @@ public class SearchResourceDialog extends FilteredItemsSelectionDialog {
                                 filter += Arrays.stream(terms).map(term -> "+" + IndexQueries.escape(term.toLowerCase(), false) + "*").collect(Collectors.joining(" ")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                                 filter +=")"; //$NON-NLS-1$
 
-                                Layer0 L0 = Layer0.getInstance(graph);
-
                                 Set<Resource> indexRoots = new HashSet<>();
                                 indexRoots.addAll(graph.syncRequest(new ObjectsWithType(project, L0.ConsistsOf, L0.IndexRoot)));
                                 indexRoots.addAll(graph.syncRequest(new OntologiesFromLibrary(graph.getRootLibrary())));
@@ -472,13 +471,13 @@ public class SearchResourceDialog extends FilteredItemsSelectionDialog {
         this.resourceFilter = resourceFilter;
     }
 
-    private String getFilterForResourceFilter(IResourceFilter filter) {
+    private String getFilterForResourceFilter(Layer0 l0, IResourceFilter filter) {
         if (filter == null || filter == ResourceSearch.FILTER_ALL)
             return ""; //$NON-NLS-1$
         if (filter == ResourceSearch.FILTER_RELATIONS)
-            return "Types:Relation";  //$NON-NLS-1$
+            return IndexQueries.resourceIdTerm(Dependencies.FIELD_TYPE_RESOURCE, l0.Relation);
         if (filter == ResourceSearch.FILTER_TYPES)
-            return "Types:Type";  //$NON-NLS-1$
+            return IndexQueries.resourceIdTerm(Dependencies.FIELD_TYPE_RESOURCE, l0.Type); 
         return ""; //$NON-NLS-1$
     }
 
index 787a400f9439022a4346532bd3c6fce3471127fe..84c0f4151d5b4f0c437d301cd9f1d920208b57fa 100644 (file)
@@ -90,23 +90,6 @@ public class ExistingInstancesRemover extends AbstractRemover {
                if (indexRoot == null)
                        return Collections.emptySet();
 
-//             @SuppressWarnings("rawtypes")
-//             Function modules = graph.adapt(Layer0X.getInstance(graph).Dependencies, Function.class);
-//             @SuppressWarnings("unchecked")
-//             List<Map<String, Object>> result = (List<Map<String, Object>>) modules.apply(graph, root, "Types:\"" + IndexQueries.escape(componentTypeName) + "\"");
-//             if (result.isEmpty()) {
-//                     justRemove(graph);
-//                     return;
-//             }
-//
-//             final Set<Resource> instances = new HashSet<Resource>();
-//             for (Map<String, Object> entry : result) {
-//                     Resource c = (Resource) entry.get(Dependencies.FIELD_RESOURCE);
-//                     if (c != null && graph.hasStatement(c, L0.InstanceOf, resource)) {
-//                             instances.add(c);
-//                     }
-//             }
-
                Set<Resource> result = new THashSet<Resource>();
                Instances search = graph.adapt(type, Instances.class);
                discoverInstances(graph, type, indexRoot, search, result);
index 3d04996120278e63de6270438ba8f1d722b9362b..4949793b46b9bbdae244427a8646e82fecae6364 100644 (file)
  *******************************************************************************/
 package org.simantics.modeling.adapters;
 
-import gnu.trove.set.hash.THashSet;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import org.simantics.databoard.Bindings;
@@ -28,7 +25,7 @@ import org.simantics.db.common.request.PossibleObjectWithType;
 import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.VariableException;
-import org.simantics.db.layer0.genericrelation.IndexQueries;
+import org.simantics.db.layer0.QueryIndexUtils;
 import org.simantics.db.layer0.request.PossibleModel;
 import org.simantics.db.layer0.variable.RVI;
 import org.simantics.db.layer0.variable.Variable;
@@ -37,11 +34,11 @@ import org.simantics.diagram.content.ConnectionUtil;
 import org.simantics.diagram.stubs.DiagramResource;
 import org.simantics.layer0.Layer0;
 import org.simantics.modeling.ModelingResources;
-import org.simantics.operation.Layer0X;
-import org.simantics.scl.runtime.function.Function;
 import org.simantics.structural.stubs.StructuralResource2;
 import org.simantics.utils.ui.ErrorLogger;
 
+import gnu.trove.set.hash.THashSet;
+
 /**
  * @author Tuukka Lehtonen
  */
@@ -121,48 +118,41 @@ final class Removers {
             return;
         NamedResource namedRoot = new NamedResource(rootName, root);
 
-        @SuppressWarnings("rawtypes")
-        Function modules = graph.adapt(Layer0X.getInstance(graph).Dependencies, Function.class);
-        @SuppressWarnings("unchecked")
-        List<Map<String, Object>> rows = (List<Map<String, Object>>) modules.apply(graph, root, "Types:" + IndexQueries.quoteTerm(result.componentType.getName()));
-        if (rows.isEmpty())
+        List<Resource> components = QueryIndexUtils.searchByTypeShallow(graph, root, result.componentType.getResource());
+        if (components.isEmpty())
             return;
 
         ModelingResources MOD = ModelingResources.getInstance(graph);
         StructuralResource2 STR = StructuralResource2.getInstance(graph);
 
-        for (Map<String, Object> row : rows) {
-            Resource component = (Resource) row.get("Resource");
-            if (graph.isInstanceOf(component, result.componentType.getResource())) {
-                String componentName = graph.getPossibleRelatedValue(component, L0.HasName, Bindings.STRING);
-                next_connection:
-                    for (Resource connection : graph.getObjects(component, connectionRelation)) {
-                        if (graph.isInstanceOf(connection, STR.Connection)) {
-
-                            if (diagramConnectionRelation != null) {
-                                // When diagram connection relation is defined, validate that
-                                // exactly the specified diagram connection relation is being
-                                // used and not some other relation from another symbol.
-                                for (Resource element : graph.getObjects(component, MOD.ComponentToElement)) {
-                                    for (Resource diagramConnector : graph.getObjects(element, diagramConnectionRelation)) {
-                                        Resource diagramConnection = ConnectionUtil.tryGetConnection(graph, diagramConnector);
-                                        if (diagramConnection == null)
-                                            continue;
-                                        Resource correspondingConnection = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection);
-                                        Resource correspondingConnectionSpecial = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnectionSpecial);
-                                        if (connection.equals(correspondingConnection) || connection.equals(correspondingConnectionSpecial)) {
-                                            addUse(graph, component, componentName, namedRoot, rootURI, result);
-                                            continue next_connection;
-                                        }
+        for (Resource component : components) {
+            String componentName = graph.getPossibleRelatedValue(component, L0.HasName, Bindings.STRING);
+            next_connection:
+                for (Resource connection : graph.getObjects(component, connectionRelation)) {
+                    if (graph.isInstanceOf(connection, STR.Connection)) {
+
+                        if (diagramConnectionRelation != null) {
+                            // When diagram connection relation is defined, validate that
+                            // exactly the specified diagram connection relation is being
+                            // used and not some other relation from another symbol.
+                            for (Resource element : graph.getObjects(component, MOD.ComponentToElement)) {
+                                for (Resource diagramConnector : graph.getObjects(element, diagramConnectionRelation)) {
+                                    Resource diagramConnection = ConnectionUtil.tryGetConnection(graph, diagramConnector);
+                                    if (diagramConnection == null)
+                                        continue;
+                                    Resource correspondingConnection = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection);
+                                    Resource correspondingConnectionSpecial = graph.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnectionSpecial);
+                                    if (connection.equals(correspondingConnection) || connection.equals(correspondingConnectionSpecial)) {
+                                        addUse(graph, component, componentName, namedRoot, rootURI, result);
+                                        continue next_connection;
                                     }
                                 }
-                            } else {
-                                addUse(graph, component, componentName, namedRoot, rootURI, result);
                             }
+                        } else {
+                            addUse(graph, component, componentName, namedRoot, rootURI, result);
                         }
-
                     }
-            }
+                }
         }
     }
 
index cfd5fe69b4ec3eac4129c38a0c526e1b5e8a6441..b311aed94dbfd48bdcd78d6956113480245bbd3b 100644 (file)
@@ -1,8 +1,5 @@
 package org.simantics.structural.synchronization.client;
 
-import gnu.trove.map.hash.TObjectIntHashMap;
-import gnu.trove.set.hash.THashSet;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -28,10 +25,15 @@ import org.simantics.structural.synchronization.protocol.SerializedVariable;
 import org.simantics.structural.synchronization.protocol.SynchronizationEventHandler;
 import org.simantics.structural.synchronization.protocol.SynchronizationException;
 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
 
 public class Synchronizer {
     
-    public static boolean TRACE = false;
+    private static final Logger LOGGER = LoggerFactory.getLogger(Synchronizer.class);
     
     ReadGraph graph;
     Layer0 L0;
@@ -152,8 +154,8 @@ public class Synchronizer {
      */
     public void fullSynchronization(Variable variable, SynchronizationEventHandler handler) throws DatabaseException {
         long duration = 0;
-        if(TRACE) {
-            System.out.println("fullSynchronization " + variable.getURI(graph));
+        if(LOGGER.isTraceEnabled()) {
+            LOGGER.trace("fullSynchronization {}", variable.getURI(graph));
             duration -= System.nanoTime();
         }
         SCLContext context = SCLContext.getCurrent();
@@ -165,9 +167,9 @@ public class Synchronizer {
         } finally {
             context.put("graph", oldGraph);
         }
-        if(TRACE) {
+        if(LOGGER.isTraceEnabled()) {
             duration += System.nanoTime();
-            System.out.println("full sync in " + 1e-9*duration + "s.");
+            LOGGER.trace("full sync done in {} s", 1e-9*duration);
         }
     }
     
@@ -275,8 +277,8 @@ public class Synchronizer {
     
     public void partialSynchronization(Variable variable, SynchronizationEventHandler handler, TObjectIntHashMap<Variable> changeFlags) throws DatabaseException {
         long duration = 0;
-        if(TRACE) {
-            System.out.println("partialSynchronization " + variable.getURI(graph));
+        if(LOGGER.isTraceEnabled()) {
+            LOGGER.trace("partialSynchronization {}", variable.getURI(graph));
             duration -= System.nanoTime();
         }
         int changeStatus = changeFlags.get(variable);
@@ -290,27 +292,31 @@ public class Synchronizer {
         } finally {
             context.put("graph", oldGraph);
         } 
-        if(TRACE) {
+        if(LOGGER.isTraceEnabled()) {
             duration += System.nanoTime();
-            System.out.println("partial sync in " + 1e-9*duration + "s.");
+            LOGGER.trace("partial sync in {} s", 1e-9*duration);
         }
     }
     
     public void partialSynchronization(Variable variable, SynchronizationEventHandler handler, long fromRevision) throws DatabaseException {
+        boolean trace = LOGGER.isTraceEnabled();
+        if (trace)
+            LOGGER.trace("Partial synchronization for {} from rev {}", variable.getURI(graph), fromRevision);
+
         TObjectIntHashMap<Variable> modifiedComponents = StructuralChangeFlattener.getModifiedComponents(graph, variable, fromRevision);
-        /*System.out.println("----------------");
-        modifiedComponents.forEachEntry(
-                new TObjectIntProcedure<Variable>() {
-                    @Override
-                    public boolean execute(Variable a, int b) {
-                        try {
-                            System.out.println("Changed: " + a.getURI(graph) + " " + b);
-                        } catch (DatabaseException e) {
-                            e.printStackTrace();
-                        }
-                        return true;
-                    }
-                });*/
+
+        if (trace) {
+            LOGGER.trace("----------------");
+            modifiedComponents.forEachEntry((Variable a, int b) -> {
+                try {
+                    LOGGER.trace("Changed: " + a.getURI(graph) + " " + b);
+                } catch (DatabaseException e) {
+                    LOGGER.error("Variable.getURI failed", e);
+                }
+                return true;
+            });
+        }
+
         partialSynchronization(variable, handler, modifiedComponents);
     }
     
@@ -324,5 +330,4 @@ public class Synchronizer {
         return graph.getService(ManagementSupport.class).getHeadRevisionId()+1;
     }
 
-    
 }