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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.scenegraph;
14 import java.beans.PropertyChangeListener;
\r
16 import org.simantics.scenegraph.utils.NodeUtil;
\r
21 public abstract class Node implements INode {
23 private static final long serialVersionUID = -5540999051056414851L;
\r
25 public transient static long IDCOUNTER = 1;
\r
27 protected transient ParentNode<?> parent = null;
\r
28 protected transient Location location = Location.LOCAL;
\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;
34 protected Long id = IDCOUNTER++;
\r
37 * @see org.simantics.scenegraph.INode#getId()
\r
44 * @see org.simantics.scenegraph.INode#getParent()
\r
46 public ParentNode<?> getParent() {
51 * @see org.simantics.scenegraph.INode#setParent(org.simantics.scenegraph.ParentNode)
\r
53 public void setParent(ParentNode<?> parent) {
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
64 * @see org.simantics.scenegraph.INode#getRootNode()
\r
66 public ParentNode<?> getRootNode() {
\r
67 return parent != null ? parent.getRootNode() : null;
\r
70 public void remove() {
71 if (parent != null) {
\r
72 parent.asyncRemoveNode(this);
77 * @see org.simantics.scenegraph.INode#init()
\r
82 public void attach() {
\r
87 * @see org.simantics.scenegraph.INode#cleanup()
\r
89 public void cleanup() {
94 * @see org.simantics.scenegraph.INode#delete()
\r
96 public void delete() {
\r
97 // 1. Remove this node from parent
\r
98 parent.asyncRemoveNode(this);
\r
102 * Remove any ID<->Node mapping this node might have in the scene graph's
\r
103 * {@link LookupService}.
\r
105 protected void retractMapping() {
\r
106 NodeUtil.tryUnmap(this);
\r
109 public <TC> TC appendParent(String id, Class<TC> nc) {
\r
110 assert(parent != null);
\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
120 if (identifier == null)
\r
121 identifier = "" + this.id;
\r
123 // 1. Remove this node from original parent
\r
124 parent.unlinkChild(this);
\r
126 // 2. Add new node under parent
\r
127 TC instance = parent.addNode(id, nc);
\r
129 // 3. Add this node under new parent
\r
130 ((ParentNode<?>)instance).appendChild(identifier, this);
\r
136 public String toString() {
137 return getSimpleClassName() + " (" + id + ")";
140 public String getSimpleClassName() {
141 return getSimpleClassName(getClass());
144 public static String getSimpleClassName(Class<?> clazz) {
145 String name = clazz.getSimpleName();
146 int pos = name.indexOf("$$");
148 name = name.substring(0, pos);
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
159 * @throws UnsupportedOperationException if no ILookupService is available
\r
163 public void setLookupId(String id) {
\r
164 NodeUtil.getLookupService(this).map(id, this);
\r
168 * A shorthand utility for {@link NodeUtil#lookup(INode, String, Class)}.
\r
174 protected <T extends INode> T lookupNode(String id, Class<T> clazz) {
\r
175 return NodeUtil.lookup(this, id, clazz);
\r
179 * A shorthand utility for {@link NodeUtil#lookupId(INode)}).
\r
184 protected String lookupId(INode node) {
\r
185 return NodeUtil.lookupId(node);
\r