001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: ParticleModel.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.gui.model;
009:
010: import com.uwyn.rife.gui.model.exceptions.GuiModelException;
011: import com.uwyn.rife.gui.model.exceptions.ParticleChildAlreadyPresentException;
012: import com.uwyn.rife.gui.model.exceptions.ParticlePropertyAlreadyPresentException;
013: import com.uwyn.rife.gui.model.exceptions.ParticlePropertyInvalidNameException;
014: import com.uwyn.rife.gui.model.exceptions.ParticlePropertyNotOrphanException;
015: import java.util.ArrayList;
016: import java.util.Collection;
017: import java.util.HashSet;
018:
019: public abstract class ParticleModel {
020: private ParticleModel mParent = null;
021: private ArrayList<ParticleModel> mChildren = null;
022: private ArrayList<ParticlePropertyModel> mProperties = null;
023: private HashSet<ParticleModelListener> mListeners = null;
024: private String mDescription = null;
025:
026: protected final Object mParentMonitor = new Object();
027: protected final Object mChildrenMonitor = new Object();
028: protected final Object mPropertiesMonitor = new Object();
029: protected final Object mListenersMonitor = new Object();
030:
031: protected ParticleModel() {
032: initialize();
033: }
034:
035: private void initialize() {
036: synchronized (mChildrenMonitor) {
037: mChildren = new ArrayList<ParticleModel>();
038: }
039: synchronized (mPropertiesMonitor) {
040: mProperties = new ArrayList<ParticlePropertyModel>();
041: }
042: synchronized (mListenersMonitor) {
043: mListeners = new HashSet<ParticleModelListener>();
044: }
045:
046: assert 0 == mChildren.size();
047: assert 0 == mProperties.size();
048: assert 0 == mListeners.size();
049: }
050:
051: public String getDescription() {
052: return mDescription;
053: }
054:
055: public void setDescription(String description) {
056: mDescription = description;
057: }
058:
059: protected void addChild(ParticleModel child)
060: throws GuiModelException {
061: if (null == child)
062: throw new IllegalArgumentException("child can't be null.");
063:
064: if (null == child.findConflictingParticle(this )) {
065: boolean result = false;
066:
067: synchronized (mChildrenMonitor) {
068: result = mChildren.add(child);
069: }
070:
071: if (result) {
072: child.setParent(this );
073: fireChildAdded(child);
074: }
075: } else {
076: throw new ParticleChildAlreadyPresentException(this , child);
077: }
078:
079: assert mChildren.contains(child);
080: assert this == child.getParent();
081: }
082:
083: protected ParticleModel findConflictingParticle(
084: ParticleModel parentParticle) {
085: if (null == parentParticle)
086: throw new IllegalArgumentException(
087: "parentParticle can't be null.");
088:
089: for (ParticleModel sibling : parentParticle
090: .getChildren(getClass())) {
091: if (sibling.equals(this )) {
092: return sibling;
093: }
094: }
095:
096: return null;
097: }
098:
099: Collection<ParticleModel> getChildren() {
100: synchronized (mChildrenMonitor) {
101: return mChildren;
102: }
103: }
104:
105: public <ChildType extends ParticleModel> Collection<ChildType> getChildren(
106: Class<ChildType> type) {
107: ArrayList<ChildType> result = new ArrayList<ChildType>();
108:
109: synchronized (mChildrenMonitor) {
110: for (ParticleModel child : mChildren) {
111: if (type.isInstance(child)) {
112: result.add((ChildType) child);
113: }
114: }
115: }
116:
117: return result;
118: }
119:
120: public int countChildren() {
121: synchronized (mChildrenMonitor) {
122: return mChildren.size();
123: }
124: }
125:
126: public int countChildren(Class type) {
127: if (null == type)
128: throw new IllegalArgumentException("type can't be null.");
129:
130: int result = 0;
131:
132: synchronized (mChildrenMonitor) {
133: for (ParticleModel child : mChildren) {
134: if (type.isInstance(child)) {
135: result++;
136: }
137: }
138: }
139:
140: assert result >= 0;
141:
142: return result;
143: }
144:
145: protected boolean setParent(ParticleModel parent) {
146: synchronized (mParentMonitor) {
147: if (parent != mParent) {
148: mParent = parent;
149: fireParentChanged();
150:
151: return true;
152: }
153: }
154:
155: return false;
156: }
157:
158: public ParticleModel getParent() {
159: synchronized (mParentMonitor) {
160: return mParent;
161: }
162: }
163:
164: public boolean removeChild(ParticleModel child) {
165: if (null == child)
166: throw new IllegalArgumentException("child can't be null.");
167:
168: boolean result = false;
169:
170: synchronized (mChildrenMonitor) {
171: result = mChildren.remove(child);
172: }
173:
174: if (result) {
175: child.setParent(null);
176: fireChildRemoved(child);
177: }
178:
179: return result;
180: }
181:
182: public boolean containsChild(ParticleModel particle) {
183: if (null == particle)
184: throw new IllegalArgumentException(
185: "particle can't be null.");
186:
187: for (ParticleModel property : getChildren(particle.getClass())) {
188: if (property.equals(particle)) {
189: return true;
190: }
191: }
192:
193: return false;
194: }
195:
196: protected boolean addProperty(ParticlePropertyModel property)
197: throws GuiModelException {
198: assert property != null;
199:
200: synchronized (mPropertiesMonitor) {
201: if (ParticlePropertyModel.isValidName(this , property
202: .getClass(), property.getName())) {
203: if (property.getParticle() != null) {
204: throw new ParticlePropertyNotOrphanException(
205: property);
206: } else if (mProperties.contains(property)) {
207: throw new ParticlePropertyAlreadyPresentException(
208: this , property);
209: } else {
210: mProperties.add(property);
211: property.setParticle(this );
212: firePropertyAdded(property);
213: }
214: } else {
215: throw new ParticlePropertyInvalidNameException(this ,
216: property);
217: }
218: }
219:
220: assert mProperties.contains(property);
221: assert this == property.getParticle();
222:
223: return true;
224: }
225:
226: public boolean containsProperty(
227: ParticlePropertyModel propertyToCheck) {
228: if (null == propertyToCheck)
229: throw new IllegalArgumentException(
230: "propertyToCheck can't be null.");
231:
232: for (ParticlePropertyModel property : getProperties(propertyToCheck
233: .getClass())) {
234: if (property.equals(propertyToCheck)) {
235: return true;
236: }
237: }
238:
239: return false;
240: }
241:
242: public ParticlePropertyModel getProperty(
243: Class<? extends ParticlePropertyModel> type, String name) {
244: if (null == type)
245: throw new IllegalArgumentException("type can't be null.");
246: if (null == name)
247: throw new IllegalArgumentException("name can't be null.");
248: if (0 == name.length())
249: throw new IllegalArgumentException("name can't be empty.");
250:
251: for (ParticlePropertyModel property : getProperties(type)) {
252: if (property.getName().equals(name)) {
253: return property;
254: }
255: }
256:
257: return null;
258: }
259:
260: Collection<ParticlePropertyModel> getProperties() {
261: synchronized (mPropertiesMonitor) {
262: return mProperties;
263: }
264: }
265:
266: public <PropertyType extends ParticlePropertyModel> Collection<PropertyType> getProperties(
267: Class<PropertyType> type) {
268: ArrayList<PropertyType> result = new ArrayList<PropertyType>();
269:
270: for (ParticlePropertyModel property : getProperties()) {
271: if (type.isInstance(property)) {
272: result.add((PropertyType) property);
273: }
274: }
275:
276: assert result != null;
277:
278: return result;
279: }
280:
281: public int countProperties() {
282: int result = 0;
283:
284: synchronized (mPropertiesMonitor) {
285: result = mProperties.size();
286: }
287:
288: assert result >= 0;
289:
290: return result;
291: }
292:
293: public int countProperties(Class type) {
294: if (null == type)
295: throw new IllegalArgumentException("type can't be null.");
296:
297: int result = 0;
298:
299: synchronized (mPropertiesMonitor) {
300: for (ParticlePropertyModel property : mProperties) {
301: if (type.isInstance(property)) {
302: result++;
303: }
304: }
305: }
306:
307: assert result >= 0;
308:
309: return result;
310: }
311:
312: public boolean renameProperty(ParticlePropertyModel property,
313: String newName) throws GuiModelException {
314: if (null == property)
315: throw new IllegalArgumentException(
316: "property can't be null.");
317: if (null == newName)
318: throw new IllegalArgumentException("newName can't be null.");
319: if (0 == newName.length())
320: throw new IllegalArgumentException(
321: "newName can't be empty.");
322:
323: if (property.isValidName(newName)) {
324: if (!property.getName().equals(newName)) {
325: property.setName(newName);
326: firePropertyRenamed(property);
327: } else {
328: return false;
329: }
330: } else {
331: throw new ParticlePropertyInvalidNameException(this ,
332: property);
333: }
334:
335: assert property.getName().equals(newName);
336:
337: return true;
338: }
339:
340: public boolean removeProperty(ParticlePropertyModel property)
341: throws GuiModelException {
342: if (null == property)
343: throw new IllegalArgumentException(
344: "property can't be null.");
345:
346: boolean result = false;
347:
348: synchronized (mPropertiesMonitor) {
349: result = mProperties.remove(property);
350: }
351:
352: if (result) {
353: property.setParticle(null);
354: firePropertyRemoved(property);
355: } else {
356: return false;
357: }
358:
359: assert !containsProperty(property);
360: assert property.getParticle() != this ;
361:
362: return true;
363: }
364:
365: public boolean addParticleListener(ParticleModelListener listener) {
366: if (null == listener)
367: throw new IllegalArgumentException(
368: "listener can't be null.");
369:
370: boolean result = false;
371:
372: synchronized (mListenersMonitor) {
373: if (!mListeners.contains(listener)) {
374: result = mListeners.add(listener);
375: } else {
376: result = true;
377: }
378: }
379:
380: assert mListeners.contains(listener);
381:
382: return result;
383: }
384:
385: public boolean removeParticleListener(ParticleModelListener listener) {
386: if (null == listener)
387: throw new IllegalArgumentException(
388: "listener can't be null.");
389:
390: boolean result = false;
391:
392: synchronized (mListenersMonitor) {
393: result = mListeners.remove(listener);
394: }
395:
396: assert !mListeners.contains(listener);
397:
398: return result;
399: }
400:
401: private void fireParentChanged() {
402: synchronized (mListenersMonitor) {
403: for (ParticleModelListener listener : mListeners) {
404: listener.parentChanged();
405: }
406: }
407: }
408:
409: private void fireChildAdded(ParticleModel child) {
410: assert child != null;
411:
412: synchronized (mListenersMonitor) {
413: for (ParticleModelListener listener : mListeners) {
414: listener.childAdded(child);
415: }
416: }
417: }
418:
419: private void fireChildRemoved(ParticleModel child) {
420: assert child != null;
421:
422: synchronized (mListenersMonitor) {
423: for (ParticleModelListener listener : mListeners) {
424: listener.childRemoved(child);
425: }
426: }
427: }
428:
429: private void firePropertyAdded(ParticlePropertyModel property) {
430: assert property != null;
431:
432: synchronized (mListenersMonitor) {
433: for (ParticleModelListener listener : mListeners) {
434: listener.propertyAdded(property);
435: }
436: }
437: }
438:
439: private void firePropertyRenamed(ParticlePropertyModel property) {
440: assert property != null;
441:
442: synchronized (mListenersMonitor) {
443: for (ParticleModelListener listener : mListeners) {
444: listener.propertyRenamed(property);
445: }
446: }
447: }
448:
449: private void firePropertyRemoved(ParticlePropertyModel property) {
450: assert property != null;
451:
452: synchronized (mListenersMonitor) {
453: for (ParticleModelListener listener : mListeners) {
454: listener.propertyRemoved(property);
455: }
456: }
457: }
458:
459: public String toString() {
460: return toString(0);
461: }
462:
463: public String toString(int level) {
464: if (level < 0)
465: throw new IllegalArgumentException(
466: "level should be at least 0.");
467:
468: String output = "";
469: String indent = "";
470:
471: for (int i = 0; i < level; i++) {
472: indent += " ";
473: }
474:
475: output += indent + getClass() + "\n";
476:
477: Collection<ParticlePropertyModel> properties = getProperties();
478: if (properties.size() > 0) {
479: output += indent + "PROPERTIES\n";
480: for (ParticlePropertyModel property : properties) {
481: output += indent + property.getClass() + "="
482: + property.getName() + "\n";
483: }
484: }
485:
486: Collection<ParticleModel> children = getChildren();
487: if (children.size() > 0) {
488: output += indent + "CHILDREN\n";
489: for (ParticleModel child : children) {
490: output += child.toString(level + 1) + "\n";
491: }
492: }
493:
494: return output;
495: }
496: }
|