1 /*
2 * This file is a part of CAST project.
3 * (c) Copyright 2007, AGH University of Science & Technology
4 * https://caribou.iisg.agh.edu.pl/trac/cast
5 *
6 * Licensed under the Eclipse Public License, Version 1.0 (the "License").
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 * http://www.eclipse.org/legal/epl-v10.html
10 */
11 /*
12 * File: NodeIndexer.java
13 * Created: 2008-11-25
14 * Author: tmilos
15 * $Id: NodeIndexer.java 3408 2009-09-30 15:19:10Z tmilos $
16 */
17
18 package pl.edu.agh.cast.model.visual.backward;
19
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import org.eclipse.core.runtime.IProgressMonitor;
24 import org.eclipse.core.runtime.NullProgressMonitor;
25
26 import pl.edu.agh.cast.common.collections.MultiMap;
27 import pl.edu.agh.cast.model.attributes.AttributeValue;
28 import pl.edu.agh.cast.model.attributes.NodeAttributeManager;
29
30 /**
31 * Class for indexing {@link Node}s based on the specified attribute. The type of nodes to index may be specified.
32 *
33 * If the indexing attribute is equal to {@link NodeAttributeManager#PERMANENT_ID} then the existing index of supplied
34 * {@link VisualModelCachingFactory} is used.
35 *
36 * @author AGH CAST Team
37 */
38 public class NodeIndexer {
39
40 private MultiMap<Object, Node> nodeMap;
41
42 private VisualModelCachingFactory visualModelFactory;
43
44 private String attribute;
45
46 private String type;
47
48 private boolean isId = false;
49
50 /**
51 * Creates node indexer with index built based on {@link NodeAttributeManager#PERMANENT_ID} attribute. All types of
52 * nodes are indexed.
53 *
54 * @param visualModelFactory
55 * {@link VisualModelCachingFactory} that provides nodes
56 */
57 public NodeIndexer(VisualModelCachingFactory visualModelFactory) {
58 this(visualModelFactory, NodeAttributeManager.PERMANENT_ID);
59 }
60
61 /**
62 * Creates node indexer with index built based on <code>attribute</code> attribute.All types of nodes are indexed.
63 *
64 * @param visualModelFactory
65 * {@link VisualModelCachingFactory} that provides nodes
66 * @param attribute
67 * name of the attribute to be used for indexing
68 */
69 public NodeIndexer(VisualModelCachingFactory visualModelFactory, String attribute) {
70 this(visualModelFactory, attribute, null);
71 }
72
73 /**
74 * Creates node indexer with index built based on <code>attribute</code> attribute. Only nodes of type
75 * <code>type</code> are indexed.
76 *
77 * @param visualModelFactory
78 * {@link VisualModelCachingFactory} that provides nodes
79 * @param attribute
80 * name of the attribute to be used for indexing
81 * @param type
82 * type of nodes to index - if <code>null</code> then all types are considered
83 */
84 public NodeIndexer(VisualModelCachingFactory visualModelFactory, String attribute, String type) {
85 this(visualModelFactory, attribute, type, new NullProgressMonitor());
86 }
87
88 /**
89 * Creates node indexer with index built based on <code>attribute</code> attribute. Only nodes of type
90 * <code>type</code> are indexed.
91 *
92 * @param visualModelFactory
93 * {@link VisualModelCachingFactory} that provides nodes
94 * @param attribute
95 * name of the attribute to be used for indexing
96 * @param type
97 * type of nodes to index - if <code>null</code> then all types are considered
98 * @param monitor
99 * operation progress monitor
100 */
101 public NodeIndexer(VisualModelCachingFactory visualModelFactory, String attribute, String type,
102 IProgressMonitor monitor) {
103 this.visualModelFactory = visualModelFactory;
104 this.attribute = attribute;
105 this.type = type;
106 // if the attribute is the ID then use VMCF index
107 if (NodeAttributeManager.PERMANENT_ID.equals(attribute)) {
108 isId = true;
109 monitor.worked(this.visualModelFactory.getNodeCount());
110 } else {
111 isId = false;
112 // allowing duplicates results in better performance :>
113 nodeMap = new MultiMap<Object, Node>(true);
114
115 // create index
116 for (Node node : this.visualModelFactory.getNodes()) {
117 if (this.type == null || this.type.equals(node.getType())) {
118 AttributeValue value = node.getAttributeValue(this.attribute);
119 if (value != null && value.getValue() != null) {
120 nodeMap.put(value.getValue(), node);
121 }
122 }
123 monitor.worked(1);
124 }
125 }
126 }
127
128 /**
129 * Wraps <code>node</code> into a list. If <code>node</code> is <code>null</code> then <code>null</code> is
130 * returned.
131 *
132 * @param node
133 * node to wrap
134 * @return a list containing the node (if it's not <code>null</code>)
135 */
136 private List<Node> enlistNode(Node node) {
137 if (node == null) {
138 return null;
139 }
140 List<Node> nList = new ArrayList<Node>(1);
141 nList.add(node);
142 return nList;
143 }
144
145 /**
146 * Returns list of nodes that have the indexing attribute value equal to <code>value</code>.
147 *
148 * WARNING: in order to preserve performance, no validation on <code>value</code> type is performed
149 *
150 * @param value
151 * lookup value
152 * @return list of matching nodes
153 */
154 public List<Node> lookup(Object value) {
155 if (isId) {
156 Node node = visualModelFactory.findNode((String)value);
157 // return if node type is allowed
158 if (node != null && (type == null || type.equals(node.getType()))) {
159 return enlistNode(node);
160 } else {
161 return null;
162 }
163 } else {
164 return nodeMap.get(value);
165 }
166 }
167
168 }