]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/Node.java
Merge commit 'd186091'
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / Node.java
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
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.scenegraph;
13
14 import java.beans.PropertyChangeListener;\r
15 \r
16 import org.simantics.scenegraph.utils.NodeUtil;\r
17 \r
18 /**
19  * @author J-P
20  */
21 public abstract class Node implements INode {
22 \r
23     private static final long                  serialVersionUID       = -5540999051056414851L;\r
24 \r
25     public transient static long               IDCOUNTER              = 1;\r
26
27     protected transient ParentNode<?>          parent                 = null;\r
28     protected transient Location               location               = Location.LOCAL;\r
29 \r
30     // This is for internal server communications. Do not touch.
31     // Support for only one listener should be enough, thus we don't need PropertyChangeSupport\r
32     protected transient PropertyChangeListener propertyChangeListener = null;
33
34     protected Long                             id                     = IDCOUNTER++;\r
35 \r
36     /**\r
37      * @see org.simantics.scenegraph.INode#getId()\r
38      */\r
39     public Long getId() {
40         return id;
41     }
42
43     /**\r
44      * @see org.simantics.scenegraph.INode#getParent()\r
45      */\r
46     public ParentNode<?> getParent() {
47         return parent;
48     }
49
50     /**\r
51      * @see org.simantics.scenegraph.INode#setParent(org.simantics.scenegraph.ParentNode)\r
52      */\r
53     public void setParent(ParentNode<?> parent) {
54         this.parent = parent;
55     }
56
57     /**\r
58      * The default implementation of {@link #getRootNode()} always asks for the\r
59      * root node from the parent. Scene graph leaf nodes are never considered to\r
60      * be real scene graph root nodes, although they are can be thought of as\r
61      * such when they are not attached to any scene graph. This implementation\r
62      * prevents the need to have a separate rootNodeCache field in all nodes.\r
63      * \r
64      * @see org.simantics.scenegraph.INode#getRootNode()\r
65      */\r
66     public ParentNode<?> getRootNode() {\r
67         return parent != null ? parent.getRootNode() : null;\r
68     }\r
69 \r
70     public void remove() {
71         if (parent != null) {\r
72             parent.asyncRemoveNode(this);
73         }
74     }
75
76     /**\r
77      * @see org.simantics.scenegraph.INode#init()\r
78      */\r
79     public void init() {
80     }\r
81     \r
82     public void attach() {\r
83     }\r
84     
85
86     /**\r
87      * @see org.simantics.scenegraph.INode#cleanup()\r
88      */\r
89     public void cleanup() {
90         retractMapping();\r
91     }\r
92 \r
93     /**\r
94      * @see org.simantics.scenegraph.INode#delete()\r
95      */\r
96     public void delete() {\r
97         // 1. Remove this node from parent\r
98         parent.asyncRemoveNode(this);\r
99     }\r
100 \r
101     /**\r
102      * Remove any ID<->Node mapping this node might have in the scene graph's\r
103      * {@link LookupService}.\r
104      */\r
105     protected void retractMapping() {\r
106         NodeUtil.tryUnmap(this);\r
107     }\r
108 \r
109     public <TC> TC appendParent(String id, Class<TC> nc) {\r
110         assert(parent != null);\r
111 \r
112         // 0. Find identifier from parent\r
113         String identifier = null;\r
114         for(String s : parent.children.keySet()) { // FIXME: should not be this complicated\r
115             if(parent.children.get(s) == this) { // Find this from parent child list\r
116                 identifier = s;\r
117                 break;\r
118             }\r
119         }\r
120         if (identifier == null)\r
121             identifier = "" + this.id;\r
122 \r
123         // 1. Remove this node from original parent\r
124         parent.unlinkChild(this);\r
125 \r
126         // 2. Add new node under parent\r
127         TC instance = parent.addNode(id, nc);\r
128 \r
129         // 3. Add this node under new parent\r
130         ((ParentNode<?>)instance).appendChild(identifier, this);\r
131 \r
132         return instance;\r
133     }\r
134
135     @Override
136     public String toString() {
137         return getSimpleClassName() + " (" + id + ")";
138     }
139
140     public String getSimpleClassName() {
141         return getSimpleClassName(getClass());
142     }
143
144     public static String getSimpleClassName(Class<?> clazz) {
145         String name = clazz.getSimpleName();
146         int pos = name.indexOf("$$");
147         if (pos >= 0)
148             name = name.substring(0, pos);
149         return name;
150     }\r
151 \r
152     /**\r
153      * Associates this node with the specified ID in the {@link ILookupService}\r
154      * that must be offered by the scene graph root node. After this\r
155      * association, one can use {@link NodeUtil#lookup(INode, String)} to lookup\r
156      * this node from the scene graph by its ID.\r
157      * \r
158      * @param id\r
159      * @throws UnsupportedOperationException if no ILookupService is available\r
160      *         for this node\r
161      */\r
162     @ClientSide\r
163     public void setLookupId(String id) {\r
164         NodeUtil.getLookupService(this).map(id, this);\r
165     }\r
166 \r
167     /**\r
168      * A shorthand utility for {@link NodeUtil#lookup(INode, String, Class)}.\r
169      * \r
170      * @param id\r
171      * @param clazz\r
172      * @return\r
173      */\r
174     protected <T extends INode> T lookupNode(String id, Class<T> clazz) {\r
175         return NodeUtil.lookup(this, id, clazz);\r
176     }\r
177 \r
178     /**\r
179      * A shorthand utility for {@link NodeUtil#lookupId(INode)}).\r
180      * \r
181      * @param node\r
182      * @return\r
183      */\r
184     protected String lookupId(INode node) {\r
185         return NodeUtil.lookupId(node);\r
186     }\r
187 \r
188 }