1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.db.layer0.adapter.impl;
\r
14 import gnu.trove.set.hash.THashSet;
\r
16 import java.util.ArrayList;
\r
17 import java.util.Collection;
\r
18 import java.util.Collections;
\r
19 import java.util.List;
\r
20 import java.util.Set;
\r
22 import org.simantics.databoard.Bindings;
\r
23 import org.simantics.db.ReadGraph;
\r
24 import org.simantics.db.Resource;
\r
25 import org.simantics.db.common.primitiverequest.Adapter;
\r
26 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
\r
27 import org.simantics.db.common.request.ObjectsWithType;
\r
28 import org.simantics.db.common.request.TernaryRead;
\r
29 import org.simantics.db.exception.DatabaseException;
\r
30 import org.simantics.db.layer0.adapter.Instances;
\r
31 import org.simantics.db.layer0.genericrelation.IndexQueries;
\r
32 import org.simantics.db.layer0.util.Layer0Utils;
\r
33 import org.simantics.db.service.CollectionSupport;
\r
34 import org.simantics.layer0.Layer0;
\r
35 import org.simantics.operation.Layer0X;
\r
36 import org.simantics.scl.runtime.function.Function;
\r
39 * @author Antti Villberg
\r
40 * @author Tuukka Lehtonen
\r
42 public class EntityInstances implements Instances {
\r
44 private static final boolean TRACE_QUERIES = false;
\r
46 private final Resource type;
\r
48 public EntityInstances(Resource type) {
\r
53 public Collection<Resource> find(ReadGraph graph, Resource index) throws DatabaseException {
\r
54 return find(graph, index, "");
\r
58 * A (cacheable) query to optimize single index queries for immutable
\r
59 * indexes such as ontologies.
\r
61 public static class QueryIndex extends TernaryRead<Resource, Resource, String, List<Resource>> {
\r
63 public QueryIndex(Resource index, Resource type, String filter) {
\r
64 super(index, type, filter);
\r
68 public List<Resource> perform(ReadGraph graph)
\r
69 throws DatabaseException {
\r
70 Resource type = parameter2;
\r
72 Layer0 L0 = Layer0.getInstance(graph);
\r
73 Layer0X L0X = Layer0X.getInstance(graph);
\r
74 String typeName = graph.getRelatedValue(type, L0.HasName);
\r
75 if (typeName.isEmpty())
\r
76 return Collections.emptyList();
\r
78 @SuppressWarnings({ "unchecked", "rawtypes" })
\r
79 Function dependencyResources = graph.syncRequest(new Adapter(L0X.DependencyResources, Function.class), TransientCacheListener.<Function>instance());
\r
81 StringBuilder filtersb = new StringBuilder();
\r
82 filtersb.append("Types:*").append( IndexQueries.escape( typeName, true ) );
\r
83 if (parameter3.length() > 0)
\r
84 filtersb.append(" AND ").append( parameter3 );
\r
85 String filter = filtersb.toString();
\r
87 if (TRACE_QUERIES) {
\r
88 System.out.println("EntityInstances.QueryIndex: finding " + filter + " from index " + graph.getPossibleURI(parameter));
\r
89 //new Exception("EntityInstances: finding " + filter + " from index " + graph.getPossibleURI(parameter)).printStackTrace();
\r
92 @SuppressWarnings("unchecked")
\r
93 List<Resource> results = (List<Resource>)dependencyResources.apply(graph, parameter, filter);
\r
94 if (results == null || results.isEmpty())
\r
95 return Collections.emptyList();
\r
98 System.out.println(" EntityInstances.QueryIndex: got " + results.size() + " results");
\r
100 // // TreeSet to keep the results in deterministic order.
\r
101 // Set<Resource> resultSet = new TreeSet<Resource>();
\r
102 // for (Map<String, Object> entry : results) {
\r
103 // Resource res = (Resource)entry.get("Resource");
\r
104 // if (res != null && !resultSet.contains(res))
\r
105 // resultSet.add(res);
\r
108 CollectionSupport coll = graph.getService(CollectionSupport.class);
\r
109 List<Resource> result = coll.createList();
\r
111 for (Resource res : Layer0Utils.sortByCluster(graph, results)) {
\r
112 if (graph.isInstanceOf(res, type))
\r
117 System.out.println(" EntityInstances.QueryIndex: got " + results.size() + " unique type-matching results");
\r
124 public String toString() {
\r
125 return "QueryIndex " + parameter + " " + parameter2 + " " + parameter3;
\r
130 private List<Resource> findRec(ReadGraph graph, Resource index, String filter, Set<Resource> visited) throws DatabaseException {
\r
132 if(!visited.add(index)) return Collections.emptyList();
\r
134 CollectionSupport coll = graph.getService(CollectionSupport.class);
\r
136 List<Resource> indexResult = graph.syncRequest(new QueryIndex(index, type, filter), TransientCacheListener.<List<Resource>>instance());
\r
138 Layer0 L0 = Layer0.getInstance(graph);
\r
139 Collection<Resource> linkedRoots = graph.syncRequest(new ObjectsWithType(index, L0.IsLinkedTo, L0.IndexRoot));
\r
140 if (linkedRoots.isEmpty())
\r
141 return indexResult;
\r
143 List<Resource> result = indexResult;
\r
144 for (Resource dep : linkedRoots) {
\r
145 Collection<Resource> linkedIndexResults = findRec(graph, dep, filter, visited);
\r
146 if (linkedIndexResults.isEmpty())
\r
148 if (result == indexResult) {
\r
149 result = coll.createList();
\r
150 result.addAll(indexResult);
\r
153 result.addAll(linkedIndexResults);
\r
161 public Collection<Resource> find(ReadGraph graph, Resource index, String filter) throws DatabaseException {
\r
162 CollectionSupport coll = graph.getService(CollectionSupport.class);
\r
164 List<Resource> rec = findRec(graph, index, filter, new THashSet<Resource>());
\r
165 for(Resource global : Layer0Utils.listGlobalOntologies(graph)) {
\r
166 List<Resource> rs = graph.syncRequest(new QueryIndex(global, type, filter), TransientCacheListener.<List<Resource>>instance());
\r
167 if(rec.isEmpty() && !rs.isEmpty()) {
\r
168 // TODO: rec could be an immutable empty list
\r
169 rec = new ArrayList<Resource>();
\r
173 Collection<Resource> result = coll.asSortedList(rec);
\r
178 public Collection<Resource> findByName(ReadGraph graph, Resource model,
\r
179 String name) throws DatabaseException {
\r
180 Layer0 L0 = Layer0.getInstance(graph);
\r
181 CollectionSupport coll = graph.getService(CollectionSupport.class);
\r
182 List<Resource> results = coll.createList();
\r
183 for(Resource match : find(graph, model, name)) {
\r
184 if(name.equals(graph.getPossibleRelatedValue(match, L0.HasName, Bindings.STRING))) results.add(match);
\r