/* * Copyright 2001-2008 Geert Bevin (gbevin[remove] at uwyn dot com) * Licensed under the Apache License, Version 2.0 (the "License") * $Id: ParticleModel.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.gui.model; import com.uwyn.rife.gui.model.exceptions.GuiModelException; import com.uwyn.rife.gui.model.exceptions.ParticleChildAlreadyPresentException; import com.uwyn.rife.gui.model.exceptions.ParticlePropertyAlreadyPresentException; import com.uwyn.rife.gui.model.exceptions.ParticlePropertyInvalidNameException; import com.uwyn.rife.gui.model.exceptions.ParticlePropertyNotOrphanException; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; public abstract class ParticleModel { private ParticleModel mParent = null; private ArrayList<ParticleModel> mChildren = null; private ArrayList<ParticlePropertyModel> mProperties = null; private HashSet<ParticleModelListener> mListeners = null; private String mDescription = null; protected final Object mParentMonitor = new Object(); protected final Object mChildrenMonitor = new Object(); protected final Object mPropertiesMonitor = new Object(); protected final Object mListenersMonitor = new Object(); protected ParticleModel() { initialize(); } private void initialize() { synchronized (mChildrenMonitor) { mChildren = new ArrayList<ParticleModel>(); } synchronized (mPropertiesMonitor) { mProperties = new ArrayList<ParticlePropertyModel>(); } synchronized (mListenersMonitor) { mListeners = new HashSet<ParticleModelListener>(); } assert 0 == mChildren.size(); assert 0 == mProperties.size(); assert 0 == mListeners.size(); } public String getDescription() { return mDescription; } public void setDescription(String description) { mDescription = description; } protected void addChild(ParticleModel child) throws GuiModelException { if (null == child) throw new IllegalArgumentException("child can't be null."); if (null == child.findConflictingParticle(this)) { boolean result = false; synchronized (mChildrenMonitor) { result = mChildren.add(child); } if (result) { child.setParent(this); fireChildAdded(child); } } else { throw new ParticleChildAlreadyPresentException(this, child); } assert mChildren.contains(child); assert this == child.getParent(); } protected ParticleModel findConflictingParticle(ParticleModel parentParticle) { if (null == parentParticle) throw new IllegalArgumentException("parentParticle can't be null."); for (ParticleModel sibling : parentParticle.getChildren(getClass())) { if (sibling.equals(this)) { return sibling; } } return null; } Collection<ParticleModel> getChildren() { synchronized (mChildrenMonitor) { return mChildren; } } public <ChildType extends ParticleModel> Collection<ChildType> getChildren(Class<ChildType> type) { ArrayList<ChildType> result = new ArrayList<ChildType>(); synchronized (mChildrenMonitor) { for (ParticleModel child : mChildren) { if (type.isInstance(child)) { result.add((ChildType)child); } } } return result; } public int countChildren() { synchronized (mChildrenMonitor) { return mChildren.size(); } } public int countChildren(Class type) { if (null == type) throw new IllegalArgumentException("type can't be null."); int result = 0; synchronized (mChildrenMonitor) { for (ParticleModel child : mChildren) { if (type.isInstance(child)) { result++; } } } assert result >= 0; return result; } protected boolean setParent(ParticleModel parent) { synchronized (mParentMonitor) { if (parent != mParent) { mParent = parent; fireParentChanged(); return true; } } return false; } public ParticleModel getParent() { synchronized (mParentMonitor) { return mParent; } } public boolean removeChild(ParticleModel child) { if (null == child) throw new IllegalArgumentException("child can't be null."); boolean result = false; synchronized (mChildrenMonitor) { result = mChildren.remove(child); } if (result) { child.setParent(null); fireChildRemoved(child); } return result; } public boolean containsChild(ParticleModel particle) { if (null == particle) throw new IllegalArgumentException("particle can't be null."); for (ParticleModel property : getChildren(particle.getClass())) { if (property.equals(particle)) { return true; } } return false; } protected boolean addProperty(ParticlePropertyModel property) throws GuiModelException { assert property != null; synchronized (mPropertiesMonitor) { if (ParticlePropertyModel.isValidName(this, property.getClass(), property.getName())) { if (property.getParticle() != null) { throw new ParticlePropertyNotOrphanException(property); } else if (mProperties.contains(property)) { throw new ParticlePropertyAlreadyPresentException(this, property); } else { mProperties.add(property); property.setParticle(this); firePropertyAdded(property); } } else { throw new ParticlePropertyInvalidNameException(this, property); } } assert mProperties.contains(property); assert this == property.getParticle(); return true; } public boolean containsProperty(ParticlePropertyModel propertyToCheck) { if (null == propertyToCheck) throw new IllegalArgumentException("propertyToCheck can't be null."); for (ParticlePropertyModel property : getProperties(propertyToCheck.getClass())) { if (property.equals(propertyToCheck)) { return true; } } return false; } public ParticlePropertyModel getProperty(Class<? extends ParticlePropertyModel> type, String name) { if (null == type) throw new IllegalArgumentException("type can't be null."); if (null == name) throw new IllegalArgumentException("name can't be null."); if (0 == name.length()) throw new IllegalArgumentException("name can't be empty."); for (ParticlePropertyModel property : getProperties(type)) { if (property.getName().equals(name)) { return property; } } return null; } Collection<ParticlePropertyModel> getProperties() { synchronized (mPropertiesMonitor) { return mProperties; } } public <PropertyType extends ParticlePropertyModel> Collection<PropertyType> getProperties(Class<PropertyType> type) { ArrayList<PropertyType> result = new ArrayList<PropertyType>(); for (ParticlePropertyModel property : getProperties()) { if (type.isInstance(property)) { result.add((PropertyType)property); } } assert result != null; return result; } public int countProperties() { int result = 0; synchronized (mPropertiesMonitor) { result = mProperties.size(); } assert result >= 0; return result; } public int countProperties(Class type) { if (null == type) throw new IllegalArgumentException("type can't be null."); int result = 0; synchronized (mPropertiesMonitor) { for (ParticlePropertyModel property : mProperties) { if (type.isInstance(property)) { result++; } } } assert result >= 0; return result; } public boolean renameProperty(ParticlePropertyModel property, String newName) throws GuiModelException { if (null == property) throw new IllegalArgumentException("property can't be null."); if (null == newName) throw new IllegalArgumentException("newName can't be null."); if (0 == newName.length()) throw new IllegalArgumentException("newName can't be empty."); if (property.isValidName(newName)) { if (!property.getName().equals(newName)) { property.setName(newName); firePropertyRenamed(property); } else { return false; } } else { throw new ParticlePropertyInvalidNameException(this, property); } assert property.getName().equals(newName); return true; } public boolean removeProperty(ParticlePropertyModel property) throws GuiModelException { if (null == property) throw new IllegalArgumentException("property can't be null."); boolean result = false; synchronized (mPropertiesMonitor) { result = mProperties.remove(property); } if (result) { property.setParticle(null); firePropertyRemoved(property); } else { return false; } assert !containsProperty(property); assert property.getParticle() != this; return true; } public boolean addParticleListener(ParticleModelListener listener) { if (null == listener) throw new IllegalArgumentException("listener can't be null."); boolean result = false; synchronized (mListenersMonitor) { if (!mListeners.contains(listener)) { result = mListeners.add(listener); } else { result = true; } } assert mListeners.contains(listener); return result; } public boolean removeParticleListener(ParticleModelListener listener) { if (null == listener) throw new IllegalArgumentException("listener can't be null."); boolean result = false; synchronized (mListenersMonitor) { result = mListeners.remove(listener); } assert !mListeners.contains(listener); return result; } private void fireParentChanged() { synchronized (mListenersMonitor) { for (ParticleModelListener listener : mListeners) { listener.parentChanged(); } } } private void fireChildAdded(ParticleModel child) { assert child != null; synchronized (mListenersMonitor) { for (ParticleModelListener listener : mListeners) { listener.childAdded(child); } } } private void fireChildRemoved(ParticleModel child) { assert child != null; synchronized (mListenersMonitor) { for (ParticleModelListener listener : mListeners) { listener.childRemoved(child); } } } private void firePropertyAdded(ParticlePropertyModel property) { assert property != null; synchronized (mListenersMonitor) { for (ParticleModelListener listener : mListeners) { listener.propertyAdded(property); } } } private void firePropertyRenamed(ParticlePropertyModel property) { assert property != null; synchronized (mListenersMonitor) { for (ParticleModelListener listener : mListeners) { listener.propertyRenamed(property); } } } private void firePropertyRemoved(ParticlePropertyModel property) { assert property != null; synchronized (mListenersMonitor) { for (ParticleModelListener listener : mListeners) { listener.propertyRemoved(property); } } } public String toString() { return toString(0); } public String toString(int level) { if (level < 0) throw new IllegalArgumentException("level should be at least 0."); String output = ""; String indent = ""; for (int i = 0; i < level; i++) { indent += " "; } output += indent+getClass()+"\n"; Collection<ParticlePropertyModel> properties = getProperties(); if (properties.size() > 0) { output += indent+"PROPERTIES\n"; for (ParticlePropertyModel property : properties) { output += indent+property.getClass()+"="+property.getName()+"\n"; } } Collection<ParticleModel> children = getChildren(); if (children.size() > 0) { output += indent+"CHILDREN\n"; for (ParticleModel child : children) { output += child.toString(level+1)+"\n"; } } return output; } }