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