View Javadoc

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 }