/******************************************************************************* * Copyright (c) 2012, 2013 Association for Decentralized Information Management in * Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.g3d.scenegraph.base; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.simantics.utils.datastructures.MapList; public abstract class ParentNode extends Node { private MapList children = new MapList(); public synchronized void addNode(String relName, T child) { if (child.getParent() != null) child.getParent().deattachNode(child.getParentRel(), child); child.setParent(this, relName); children.add(relName, (T) child); childrenChanged(); fireNodeAdded(child, relName); } /** * Removes child node and it's hierarchy. * @param relName * @param child * @return */ @SuppressWarnings("unchecked") public synchronized final boolean removeNode(String relName, INode child) { if (children.remove(relName, (T) child)) { fireNodeRemoved(child, relName); child.remove(); child.setParent(null, null); return true; } return false; } /** * Removes child node. The child nodes hierarchy is left intact. * @param relName * @param child * @return */ @SuppressWarnings("unchecked") public synchronized final boolean deattachNode(String relName, INode child) { if (children.remove(relName, (T) child)) { fireNodeRemoved(child, relName); child.setParent(null, null); return true; } return false; } public synchronized final boolean removeNodes(String relName) { List nodes = children.getValues(relName); for (T child : nodes) { if (children.remove(relName, (T) child)) { fireNodeRemoved(child, relName); child.remove(); child.setParent(null, null); } } return nodes.size() > 0; } public synchronized final void removeNodes() { synchronized (children) { boolean changed = false; for (String key : children.getKeys()) { for (T child : children.getValues(key)) { if (child != null) { changed = true; if (child instanceof ParentNode) { ((ParentNode) child).removeNodes(); } child.cleanup(); child.setParent(null, null); // if (propertyChangeListener != null) { // propertyChangeListener.propertyChange(new // PropertyChangeEvent(this, // "children["+child.getId()+"]", child.getClass(), // NULL)); // "children" is a special field name // } } } } children.clear(); if (changed) childrenChanged(); } } public synchronized List getNodes(String rel) { return children.getValues(rel); } public synchronized List getNodes() { List result = new ArrayList(); for (String s : children.getKeys()) result.addAll(children.getValues(s)); return result; } protected void childrenChanged() { } @Override public void remove() { synchronized (children) { List toRemove = new ArrayList(); for (String key : children.getKeys()) { for (T child : children.getValues(key)) { if (child != null) { toRemove.add(child); } } } for (T n : toRemove) { n.remove(); } children.clear(); if (toRemove.size() > 0) childrenChanged(); super.remove(); } } protected void fireNodeAdded(INode node, String rel) { for (NodeListener listener : listeners) { listener.nodeAdded(this, node, rel); } } protected void fireNodeRemoved(INode node, String rel) { for (NodeListener listener : listeners) { listener.nodeRemoved(this, node, rel); } } }