View Javadoc

1   /*
2    * Copyright 2006 - 2012 Christina Bohk and Roland Ewald
3    *  
4    * Licensed under the Apache License, Version 2.0 (the "License"); 
5    * you may not use this file except in compliance with the License. 
6    * You may obtain a copy of the License at 
7    *  
8    *  http://www.apache.org/licenses/LICENSE-2.0
9    *  
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License. 
15   */
16  package p3j.gui.panels.projections;
17  
18  import java.awt.BorderLayout;
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import javax.swing.JPanel;
23  import javax.swing.tree.DefaultMutableTreeNode;
24  import javax.swing.tree.DefaultTreeModel;
25  import javax.swing.tree.TreeNode;
26  import javax.swing.tree.TreePath;
27  
28  import p3j.misc.Misc;
29  
30  /**
31   * Super class of all nodes representing PPPM entities in the projection tree.
32   * 
33   * Created: August 24, 2008
34   * 
35   * @param <E>
36   *          type of the represented entity
37   * 
38   * @author Christina Bohk
39   * @author Roland Ewald
40   * 
41   */
42  public class ProjectionTreeNode<E> extends DefaultMutableTreeNode {
43  
44  	/** Serialization ID. */
45  	private static final long serialVersionUID = 1987698685076459120L;
46  
47  	/** Reference to the represented entity. */
48  	private final E entity;
49  
50  	/** Class of the entity (necessary for lookup functions). */
51  	private final Class<?> entityClass;
52  
53  	/** Panel holding the content overview for this node. */
54  	private JPanel contentPanel;
55  
56  	/**
57  	 * Default constructor.
58  	 * 
59  	 * @param pppmEntity
60  	 *          the PPPM entity to be represented
61  	 * @param name
62  	 *          the name to be displayed
63  	 */
64  	public ProjectionTreeNode(E pppmEntity, String name) {
65  		super(name);
66  		entity = pppmEntity;
67  		entityClass = pppmEntity.getClass();
68  	}
69  
70  	public E getEntity() {
71  		return entity;
72  	}
73  
74  	/**
75  	 * Method that is called by the
76  	 * {@link javax.swing.event.TreeSelectionListener} when this node gets
77  	 * selected.
78  	 * 
79  	 * @param selectionPath
80  	 *          the path containing all ancestors
81  	 * @param generalPanel
82  	 *          the general panel to put the content on
83  	 * @param projTree
84  	 *          the projection tree
85  	 */
86  	public void selected(TreePath selectionPath, JPanel generalPanel,
87  	    IProjectionTree projTree) {
88  		contentPanel = selected(selectionPath, projTree);
89  		if (contentPanel != null) {
90  			generalPanel.add(contentPanel, BorderLayout.CENTER);
91  		}
92  	}
93  
94  	/**
95  	 * Method that is called by
96  	 * {@link ProjectionTreeNode#selected(TreePath, JPanel, DefaultTreeModel, javax.swing.JTree)}
97  	 * originally. Implementations of {@link ProjectionTreeNode} might override
98  	 * either of the 'selected' methods, this one is more convenient as it stores
99  	 * the generated panel in an auxiliary variable and does not require to add
100 	 * the panel manually, it just needs to be returned.
101 	 * 
102 	 * @param selectionPath
103 	 *          the path containing all ancestors
104 	 * @param projTree
105 	 *          the projection tree
106 	 * @return panel with a node summary
107 	 */
108 	public JPanel selected(TreePath selectionPath, IProjectionTree projTree) {
109 		return null;
110 	}
111 
112 	/**
113 	 * This is called when the node's representation might have changed. A reason
114 	 * for this could be changes from the outside. Default implementation is
115 	 * empty. This should simple re-invoke
116 	 * {@link DefaultMutableTreeNode#setUserObject(Object)}.
117 	 */
118 	protected void refreshRepresentation() {
119 	}
120 
121 	/**
122 	 * Method that is called by the
123 	 * {@link javax.swing.event.TreeSelectionListener} when this node gets
124 	 * de-selected.
125 	 */
126 	public void deselected() {
127 	}
128 
129 	public Class<?> getEntityClass() {
130 		return entityClass;
131 	}
132 
133 	public JPanel getContentPanel() {
134 		return contentPanel;
135 	}
136 
137 	/**
138 	 * Traverses current {@link javax.swing.JTree} towards its root. See
139 	 * {@link ProjectionTreeNode#getProjectionEntity(Class, ProjectionTreeNode)},
140 	 * which is called with this.
141 	 * 
142 	 * @param <T>
143 	 *          required type
144 	 * @param targetClass
145 	 *          class of required type
146 	 * @return found entity, or null
147 	 */
148 	public <T> T getProjectionEntity(Class<T> targetClass) {
149 		return getProjectionEntity(targetClass, this);
150 	}
151 
152 	/**
153 	 * Traverses a {@link javax.swing.JTree} towards its root. Returns first
154 	 * entity of a given type that is found. Requires that all nodes are of type
155 	 * {@link ProjectionTreeNode}, returns null when encountering another class.
156 	 * 
157 	 * @param <T>
158 	 *          the type of the required entity
159 	 * @param targetClass
160 	 *          the class of the required entity
161 	 * @param sourceNode
162 	 *          the node from where to start searching upwards
163 	 * @return first entity of requested type on path towards root, or null if not
164 	 *         found
165 	 */
166 	@SuppressWarnings("unchecked")
167 	public <T> T getProjectionEntity(Class<T> targetClass,
168 	    ProjectionTreeNode<?> sourceNode) {
169 		if (Misc.checkClassEquality(sourceNode.getEntityClass(), targetClass)) {
170 			return (T) sourceNode.getEntity();
171 		}
172 		TreeNode parent = sourceNode.getParent();
173 		if (!(parent instanceof ProjectionTreeNode<?>)) {
174 			return null;
175 		}
176 
177 		return getProjectionEntity(targetClass, (ProjectionTreeNode<?>) parent);
178 	}
179 
180 	/**
181 	 * Gets a projection tree node of a specific type, which is on the path.
182 	 * 
183 	 * @param targetClass
184 	 *          the target class
185 	 * 
186 	 * @param <T>
187 	 *          the type of the target
188 	 * 
189 	 * @return the projection tree node on path
190 	 */
191 	@SuppressWarnings("unchecked")
192 	public <T> T getProjectionTreeNodeOnPath(Class<T> targetClass) {
193 		TreeNode treeNode = getParent();
194 		while (treeNode != null) {
195 			if (treeNode.getClass().equals(targetClass)) {
196 				return (T) treeNode;
197 			}
198 			treeNode = treeNode.getParent();
199 		}
200 		return null;
201 	}
202 
203 	/**
204 	 * Looks for a certain object associated with a child node of type
205 	 * {@link ProjectionTreeNode}.
206 	 * 
207 	 * @param childEntity
208 	 *          the target entity
209 	 * @return the child node associated with this entity
210 	 */
211 	public ProjectionTreeNode<?> getChildWithEntity(Object childEntity) {
212 		if (getEntity() == childEntity) {
213 			return this;
214 		}
215 		for (int i = 0; i < this.getChildCount(); i++) {
216 			ProjectionTreeNode<?> child = (ProjectionTreeNode<?>) this.getChildAt(i);
217 			ProjectionTreeNode<?> result = child.getChildWithEntity(childEntity);
218 			if (result != null) {
219 				return result;
220 			}
221 		}
222 		return null;
223 	}
224 
225 	/**
226 	 * Retrieves all children of a given type. Traverses the tree in preorder.
227 	 * 
228 	 * @param <X>
229 	 *          the type of the entity
230 	 * @param entityType
231 	 *          the type of the entity
232 	 * @return list of child nodes representing such entities (which have to be
233 	 *         non-null)
234 	 */
235 	public <X> List<ProjectionTreeNode<X>> getChildsByType(Class<X> entityType) {
236 		return getChildsByType(new ArrayList<ProjectionTreeNode<X>>(), entityType);
237 	}
238 
239 	@SuppressWarnings("unchecked")
240 	protected <X> List<ProjectionTreeNode<X>> getChildsByType(
241 	    List<ProjectionTreeNode<X>> list, Class<X> entityType) {
242 		if (getEntity() != null
243 		    && Misc.checkClassEquality(this.getEntityClass(), entityType)) {
244 			list.add((ProjectionTreeNode<X>) this);
245 		}
246 		for (int i = 0; i < this.getChildCount(); i++) {
247 			ProjectionTreeNode<?> node = (ProjectionTreeNode<?>) getChildAt(i);
248 			node.getChildsByType(list, entityType);
249 		}
250 		return list;
251 	}
252 
253 	/**
254 	 * Refreshes nodes and all of its children recursively, by invoking
255 	 * {@link ProjectionTreeNode#refreshRepresentation()}.
256 	 * 
257 	 * @param treeModel
258 	 *          the tree model to be notified
259 	 */
260 	protected void refreshRecursively(DefaultTreeModel treeModel) {
261 		refreshRepresentation();
262 		treeModel.nodeChanged(this);
263 		for (int i = 0; i < getChildCount(); i++) {
264 			ProjectionTreeNode<?> node = (ProjectionTreeNode<?>) getChildAt(i);
265 			node.refreshRecursively(treeModel);
266 		}
267 	}
268 
269 	/**
270 	 * Retrieves list of child nodes.
271 	 * 
272 	 * @return list of child nodes
273 	 */
274 	public List<ProjectionTreeNode<?>> getChilds() {
275 		List<ProjectionTreeNode<?>> result = new ArrayList<ProjectionTreeNode<?>>();
276 		for (int i = 0; i < getChildCount(); i++) {
277 			result.add((ProjectionTreeNode<?>) getChildAt(i));
278 		}
279 		return result;
280 	}
281 
282 	/**
283 	 * Gets the user object string.
284 	 * 
285 	 * @return the object string
286 	 */
287 	public String getEntityLabel() {
288 		return this.getEntity().toString();
289 	}
290 
291 }