View Javadoc

1   /*
2    *  UnBBayes
3    *  Copyright (C) 2002, 2008 Universidade de Brasilia - http://www.unb.br
4    *
5    *  This file is part of UnBBayes.
6    *
7    *  UnBBayes is free software: you can redistribute it and/or modify
8    *  it under the terms of the GNU General Public License as published by
9    *  the Free Software Foundation, either version 3 of the License, or
10   *  (at your option) any later version.
11   *
12   *  UnBBayes is distributed in the hope that it will be useful,
13   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   *  GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License
18   *  along with UnBBayes.  If not, see <http://www.gnu.org/licenses/>.
19   *
20   */
21  package unbbayes.prs;
22  
23  import java.awt.Color;
24  import java.awt.Point;
25  import java.awt.geom.Point2D;
26  import java.io.Serializable;
27  import java.util.ArrayList;
28  import java.util.Collection;
29  import java.util.List;
30  
31  import unbbayes.prs.bn.ExplanationPhrase;
32  import unbbayes.prs.bn.IRandomVariable;
33  import unbbayes.prs.bn.ProbabilisticNode;
34  import unbbayes.prs.exception.InvalidParentException;
35  import unbbayes.util.ArrayMap;
36  import unbbayes.util.Debug;
37  import unbbayes.util.SerializablePoint2D;
38  
39  /**
40   * A class representing a generic node containing graphical/visual information.
41   * @author Michael 
42   * @author Rommel Carvalho (rommel.caralho@gmail.com)
43   * 
44   * @version 04/18/2009
45   * @author Shou Matsumoto
46   * 		   Refactor: interface extraction -> INode
47   */
48  public abstract class Node implements Serializable, 
49                                        Comparable<Node>, INode{
50  
51  	/**
52  	 * 
53  	 */
54  	private static final long serialVersionUID = 6852804931629660275L;
55  	
56  	private String description;
57  	protected String name;
58  	protected String label;
59  
60  	//by young	
61  	public static Point DEFAULT_SIZE = new Point(80,60); 
62  	
63  	protected SerializablePoint2D position;
64  	//by young	
65  	protected Color backColor;
66  	//by young
67  	protected SerializablePoint2D size = new SerializablePoint2D(DEFAULT_SIZE.getX(), DEFAULT_SIZE.getY());
68  	protected SerializablePoint2D sizeVariable = new SerializablePoint2D();
69  	protected boolean sizeIsVariable = false;
70  
71  	protected ArrayList<Node> parents;
72  	private ArrayList<Node> children;
73  	protected List<String> states;
74  	private ArrayList<Node> adjacents;
75  	private boolean bSelected;
76  	private String explanationDescription;
77  	private ArrayMap<String, ExplanationPhrase> phrasesMap;
78  	private int informationType;
79  	public int infoestados[];
80  
81      //by young
82   	public static final String DISPLAY_MODE_ELLIPSE		= "Display Mode Ellipse";
83   	public static final String DISPLAY_MODE_BAR			= "Display Mode BAR";
84   	private String m_displayMode = DISPLAY_MODE_ELLIPSE;
85    
86  
87  	public static final int PROBABILISTIC_NODE_TYPE = 0;
88  	public static final int UTILITY_NODE_TYPE = 1;
89  	public static final int DECISION_NODE_TYPE = 2;
90  
91  	public static final int DESCRIPTION_TYPE = 3;
92  	public static final int EXPLANATION_TYPE = 4;
93  	
94  	public static final int CONTINUOUS_NODE_TYPE = 5;
95  
96  	/**
97  	 * Holds the mean of the values for each class if this is a numeric
98  	 * attribute node
99  	 */
100 	protected double[] mean;
101 
102 	/**
103 	 * Holds the standard deviation of the values for each class if this is a
104 	 * numeric attribute node.
105 	 */
106 	protected double[] standardDeviation;
107 
108 	/**
109 	 * Builds a new node and makes the expected
110 	 * initializations.
111 	 */
112 	public Node() {
113 		name = "";
114 		label = ""; // text inside node
115 		description = "";
116 		explanationDescription = "";
117 		adjacents = new ArrayList<Node>();
118 		parents = new SetList<Node>();
119 		children = new SetList<Node>();
120 		states = new ArrayList<String>();
121 
122 		// width
123 		size.x = DEFAULT_SIZE.getX();
124 		// height
125 		size.y = DEFAULT_SIZE.getY();
126 
127 		position = new SerializablePoint2D();
128 		bSelected = false;
129 		phrasesMap = new ArrayMap<String, ExplanationPhrase>();
130 		informationType = DESCRIPTION_TYPE;
131 		
132 		//by young
133 		setColor(Color.white); 
134 	}
135 
136 	public static Point getDefaultSize(){
137 		return DEFAULT_SIZE;
138 	}
139 	
140 	
141 
142 	/**
143 	 * Returns the type of information of this node.
144 	 * 
145 	 * @return Type of the information.
146 	 */
147 	public int getInformationType() {
148 		return informationType;
149 	}
150 
151 	/**
152 	 * Modify the node's type of information.
153 	 * The types can be:
154 	 * 		DESCRIPTION_TYPE: for description nodes.
155 	 * 		EXPLANATION_TYPE: for explanation nodes.
156 	 * @param informationType
157 	 *            type of information
158 	 * @throws Exception
159 	 *            if the type of information is invalid
160 	 */
161 	public void setInformationType(int informationType) /* throws Exception */{
162 		if ((informationType > 2) && (informationType < 5)) {
163 			this.informationType = informationType;
164 			// TODO - Rommel think of a better way of doing this!
165 			if (getColor() == ProbabilisticNode.getDescriptionColor() && informationType == Node.EXPLANATION_TYPE) {
166 				this.setColor(ProbabilisticNode.getExplanationColor());
167 			}
168 		}
169 			
170 		/*
171 		 * else { throw new Exception("Valor de infroma��o inv�lido"); }
172 		 */
173 	}
174 
175 	public void addExplanationPhrase(ExplanationPhrase explanationPhrase) {
176 		phrasesMap.put(explanationPhrase.getNode(), explanationPhrase);
177 	}
178 
179 	public ExplanationPhrase getExplanationPhrase(String node) throws Exception {
180 		ExplanationPhrase ep = phrasesMap.get(node);
181 		if (ep == null) {
182 			throw new Exception("N� n�o encontrado.");
183 		} else {
184 			return (ExplanationPhrase) ep;
185 		}
186 	}
187 
188 	/**
189 	 * Changes node's description.
190 	 * 
191 	 * @param texto
192 	 *            node's description.
193 	 */
194 	public void setDescription(String texto) {
195 		this.description = texto;
196 	}
197 
198 	/**
199 	 * Set the node's name. It also causes the nodeNameChanged event to be fired.
200 	 * 
201 	 * @param name
202 	 *            Node's name.
203 	 */
204 	public void setName(String name) {
205 		NodeNameChangedEvent event = new NodeNameChangedEvent(this.name, name);
206 		this.name = name;
207 		this.nameChanged(event);
208 	}
209 
210 	/**
211 	 * Set the node's label (text of the node).
212 	 * 
213 	 * @param label
214 	 *            Node's label.
215 	 */
216 	public void setLabel(String label) {
217 		this.label = label;
218 	}
219 
220 	/**
221 	 * Return the node's label (text of the node).
222 	 * 
223 	 */
224 	public String getLabel() {
225 		return label;
226 	}
227 	
228 	//by young
229 	public String updateLabel()
230 	{
231 		return label;
232 	}
233 
234 	/**
235 	 * Sets a new list of children.
236 	 * @param children
237 	 * 			List of nodes representing the children.
238 	 */
239 	public void setChildren(ArrayList<Node> children) {
240 		this.children = children;
241 	}
242 	
243 	
244 
245 	/**
246 	 * Sets a new list of parents.
247 	 * @param parents
248 	 * 			List of nodes representing the parents.
249 	 */
250 	public void setParents(ArrayList<Node> parents) {
251 		this.parents = parents;
252 	}
253 	
254 	public void addChild(Node child) throws InvalidParentException{
255 		if (this.children.contains(child)) {
256 			Debug.println(this.getClass(), "Attempt to insert duplicate child: " + child);
257 			return;
258 		}
259 		this.children.add(child);
260 	}
261 	
262 	public void removeChild(Node child) {
263 		this.children.remove(child);
264 	}
265 	
266 	public void addParent(Node parent) throws InvalidParentException{
267 		if (this.parents.contains(parent)) {
268 			Debug.println(this.getClass(), "Attempt to insert duplicate parent: " + parent);
269 			return;
270 		}
271 
272 		this.parents.add(parent);
273 	}
274 	
275 	public void removeParent(Node parent) {
276 		this.parents.remove(parent);
277 	}
278 
279 	public boolean isParentOf(Node child) {
280 		// boolean result=children.contains(child);
281 		boolean result = false;
282 		int j = children.size();
283 		try {
284 			for (int i = 0; i < j; i++) {
285 				result = ((result) || ((child.getName()) == (children.get(i)
286 						.getName())));
287 			}
288 		} catch (Exception ee) {
289 		}
290 		return result;
291 	}
292 
293 	public boolean isChildOf(Node parent) {
294 		// boolean result=parents.contains(parent);
295 		boolean result = false;
296 		int j = parents.size();
297 		for (int i = 0; i < j; i++) {
298 			result = ((result) || ((parent.getName()) == (parents.get(i)
299 					.getName())));
300 		}
301 		return result;
302 	}
303 
304 	/**
305 	 * Modifica a descri��o da explana��o do n�.
306 	 * Modifies the description of the explanation of the node.
307 	 * @param texto
308 	 * 			A text representing the node's explanation's description.
309 	 *            descri��o da explana��o do n�.
310 	 */
311 	public void setExplanationDescription(String text) {
312 		this.explanationDescription = text;
313 	}
314 
315 	/**
316 	 * Modifies the ArrayMap with the phrases
317 	 * @param phrasesMap
318 	 *            a new ArrayMap to be set
319 	 * @return the old phrasesMap.
320 	 */
321 	public ArrayMap<String, ExplanationPhrase> setPhrasesMap(
322 			ArrayMap<String, ExplanationPhrase> phrasesMap) {
323 		ArrayMap<String, ExplanationPhrase> old = this.phrasesMap;
324 		this.phrasesMap = phrasesMap;
325 		return old;
326 	}
327 
328 	/**
329 	 * Obtains the name of this node.
330 	 * @return node's description.
331 	 */
332 	public String getDescription() {
333 		return description;
334 	}
335 
336 	/**
337 	 * Obtains a list of adjacents.
338 	 * @return reference for this node's adjacents.
339 	 */
340 	public ArrayList<Node> getAdjacents() {
341 		return adjacents;
342 	}
343 
344 	/**
345 	 * Returns the node's literal symbol.
346 	 * 
347 	 * @return node's literal abbreviation.
348 	 */
349 	public String getName() {
350 		return name;
351 	}
352 
353 	/**
354 	 * Obtains a list of children.
355 	 * @return list of children.
356 	 */
357 	public final ArrayList<Node> getChildren() {
358 		return children;
359 	}
360 
361 	/**
362 	 * Obtains a list of parents.
363 	 * @return list of parents.
364 	 */
365 	public final ArrayList<Node> getParents() {
366 		return parents;
367 	}
368 
369 	/**
370 	 * Obtains the description of the explanation of the node.
371 	 * @return description of the explanation of the node
372 	 */
373 	public String getExplanationDescription() {
374 		return explanationDescription;
375 	}
376 
377 	/**
378 	 * Obtains the ArrayMap with the phrases.
379 	 * @return ArrayMap with the phrases.
380 	 */
381 	public ArrayMap<String, ExplanationPhrase> getPhrasesMap() {
382 		return this.phrasesMap;
383 	}
384 
385 	/**
386 	 * Used within dalgo2
387 	 */
388 	public void atualizatamanhoinfoestados() {
389 		int i = states.size();
390 		infoestados = new int[i];
391 
392 		/*
393 		 * nao precisa, pois o array eh criado sempre com o valor 0 for (int j =
394 		 * 0; j < i; j++) infoestados[j] = 0;
395 		 */
396 	}
397 	
398 	// by young2010
399 	/**
400 	 * Verifies if the node has a given state.
401 	 * @param state The state name to look for.
402 	 * @return true if the node has the given state, false otherwise.
403 	 */
404 	public boolean hasState(String state) {
405 		for (int i = 0; i < states.size(); i++) {
406 			if (states.get(i).equals(state))
407 				return true;
408 		}
409 		return false;
410 	}
411 
412 	/**
413 	 * Inserts a state with the specified name at the end of the list.
414 	 * @param state
415 	 *            Name of the state to be added.
416 	 */
417 	public void appendState(String state) {
418 		updateTables();
419 		states.add(state);
420 	}
421 
422 	/**
423 	 * Deletes the node's last inserted state (i.e the last element inside the list of states).
424 	 */
425 	public void removeLastState() {
426 		if (states.size() > 1) {
427 			updateTables();
428 			states.remove(states.size() - 1);
429 		}
430 	}
431 
432 	/**
433 	 * Used within dalgo2. It should not be used with nodes having potential table's informations.
434 	 */
435 	public void removeStateAt(int index) {
436 		states.remove(index);
437 		this.atualizatamanhoinfoestados();
438 	}
439 
440 	/**
441 	 * Replaces a state at given position to the specified position.
442 	 * @param state
443 	 * 				Name of the new state.
444 	 * @param index
445 	 * 				Position of the state being substituted. Starts with 0.
446 	 */
447 	public void setStateAt(String state, int index) {
448 		states.set(index, state);
449 	}
450 
451 	/*
452 	 * public boolean existState(String state) { int size = states.size(); for
453 	 * (int i=0; i<size; i++) { if (states.get(i).equals(state)) return true; }
454 	 * return false; }
455 	 */
456 
457 	/**
458 	 * It returns the node's quantity of states.
459 	 * @return How many states the node has.
460 	 */
461 	public final int getStatesSize() {
462 		return states.size();
463 	}
464 
465 	/**
466 	 * Returns the state of the position given by <code>index</code>
467 	 * @param index
468 	 *            position of the state to be read.
469 	 * @return Name of the state at <code>index</code>
470 	 */
471 	public final String getStateAt(int index) {
472 		return (String) (states.get(index));
473 	}
474 
475 	/**
476 	 * Builds the list of adjacent nodes.
477 	 * (the parents and children of this node)
478 	 */
479 	public void makeAdjacents() {
480 		adjacents.addAll(parents);
481 		adjacents.addAll(children);
482 	}
483 
484 	/**
485 	 * Clears the list of adjacent nodes.
486 	 */
487 	public void clearAdjacents() {
488 		adjacents.clear();
489 	}
490 
491 	/**
492 	 * This should be used to notify the tables which this variable is part of that
493 	 * there were some modification at this variable's internal structure.
494 	 */
495 	private void updateTables() {
496 		IRandomVariable aux;
497 		if (this instanceof IRandomVariable) {
498 			aux = (IRandomVariable) this;
499 			aux.getProbabilityFunction().notifyModification();
500 		}
501 
502 		for (int i = children.size() - 1; i >= 0; i--) {
503 			if (children.get(i) instanceof IRandomVariable) {
504 				aux = (IRandomVariable) children.get(i);
505 				aux.getProbabilityFunction().notifyModification();
506 			}
507 		}
508 	}
509 	
510 	 //by young
511     public void setDisplayMode(String s) 
512 	{  
513     	m_displayMode = s;
514 	}	
515 	
516 	public String getDisplayMode() 
517 	{
518 		return m_displayMode;
519 	}
520 
521 	/**
522 	 * Sets the adjacents.
523 	 * 
524 	 * @param adjacents
525 	 *            The adjacents to set
526 	 */
527 	public void setAdjacents(ArrayList<Node> adjacents) {
528 		this.adjacents = new ArrayList<Node>(adjacents);
529 	}
530 
531 	/**
532 	 * Sets the states.
533 	 * 
534 	 * @param states
535 	 *            The states to set
536 	 */
537 	public void setStates(List<String> states) {
538 		this.states = states;
539 	}
540 
541 	/**
542 	 * Prints a description of the node using "description (name)" format (without
543 	 * the quotes). It is used by the Interface's JTree when net is compiled.
544 	 * 
545 	 * @return formatted node description.
546 	 */
547 	public String toString() {
548 		return description + " (" + name + ")";
549 	}
550 
551 	/**
552 	 * @see java.lang.Object#equals(java.lang.Object)
553 	 */
554 	public boolean equals(Object obj) {
555 		
556 		if (obj == this) {
557 			return true;
558 		}
559 		
560 		if((obj != null)&&(obj instanceof Node)){
561 		   Node node = (Node) obj;
562 		   return (node.name.equals(this.name));
563 		}
564 		
565 		return false; //obj == null && this != null 
566 		
567 	}
568 
569 	public int compareTo(Node arg0) {
570 		return this.getName().compareTo(((Node)arg0).getName());	
571 	}
572 	
573 	public boolean isPointInDrawableArea(int x, int y) {
574 		double x1 = position.x;
575 		double y1 = position.y;
576 		double width = size.x / 2;
577 		double height = size.y / 2;
578 
579 		if ((x >= x1 - width) && (x <= x1 + width) && (y >= y1 - height)
580 				&& (y <= y1 + height)) {
581 			return true;
582 		}
583 
584 		return false;
585 	}
586 
587 	public boolean isSelected() {
588 		return bSelected;
589 	}
590 
591 	public void setSelected(boolean b) {
592 		bSelected = b;
593 	}
594 
595 	public Point2D.Double getPosition() {
596 		return position;
597 	}
598 
599 	public void setPosition(double x, double y) {
600 		position.setLocation(x, y);
601 	}
602 
603 	//by young
604 	public Color getColor() {
605 		return backColor;
606 	}
607  
608 	//by young
609 	public void setColor(Color c) {
610 		backColor = c;
611 	}
612 	
613 	/**
614 	 * Get the node's width.
615 	 * 
616 	 * @return Node's width.
617 	 */
618 	//by young
619 	public int getWidth() {
620 		return (int) size.x;
621 	}
622 
623 	/**
624 	 * Get the node's height.
625 	 * 
626 	 * @return The node's height.
627 	 */
628 	//by young
629 	public int getHeight() {
630 		return (int) size.y;
631 	}
632 	
633 	/**
634 	 * Get the node's width.
635 	 * 
636 	 * @return Node's width.
637 	 */
638 	//by young
639 	public static int getDefaultWidth() {
640 		return (int) DEFAULT_SIZE.x;
641 	}
642 
643 	/**
644 	 * Get the node's height.
645 	 * 
646 	 * @return The node's height.
647 	 */
648 	//by young
649 	public static int getDefaultHeight() {
650 		return (int) DEFAULT_SIZE.y;
651 	}
652 
653 	/**
654 	 * Returns the node's size (x,y) where x = width and y = height.
655 	 * 
656 	 * @return The node's size.
657 	 */
658 	//by young
659 	public Point2D.Double getSize() {
660 
661 		return size;
662 
663 	}
664 
665 	/**
666 	 * Set the node's size.
667 	 * 
668 	 * @param width
669 	 *            The node's width.
670 	 * @param height
671 	 *            The node's height.
672 	 */
673 	//by young
674 	public void setSize(double width, double height) {
675 		size.x = width;
676 		size.y = height;
677 	}
678 
679 	public void setSizeVariable(double width, double height) {
680 		sizeVariable.setLocation(width, height);
681 	}
682 
683 	public void setSizeIsVariable(boolean is) {
684 		sizeIsVariable = is;
685 	}
686 
687 	/**
688 	 * Set the mean of the values if this is a numeric attribute node.
689 	 * 
690 	 * @param mean
691 	 */
692 	public void setMean(double[] mean) {
693 		this.mean = mean;
694 	}
695 
696 	/**
697 	 * Set the mean of the values if this is a numeric attribute node.
698 	 * 
699 	 * @param mean
700 	 */
701 	public void setStandardDeviation(double[] standardDeviation) {
702 		this.standardDeviation = standardDeviation;
703 	}
704 
705 	/**
706 	 * Get the mean of the values if this is a numeric attribute node.
707 	 * 
708 	 * @param mean
709 	 */
710 	public double[] getMean() {
711 		return mean;
712 	}
713 
714 	/**
715 	 * Get the mean of the values if this is a numeric attribute node.
716 	 * 
717 	 * @param mean
718 	 */
719 	public double[] getStandardDeviation() {
720 		return standardDeviation;
721 	}
722 	
723 	/*********** NAME CHANGE LISTENER ***************/
724 	
725 	public class NodeNameChangedEvent {
726 		
727 		private String oldName;
728 		private String newName;
729 		
730 		public NodeNameChangedEvent(String oldName, String newName) {
731 			this.oldName = oldName;
732 			this.newName = newName;
733 		}
734 
735 		public String getOldName() {
736 			return oldName;
737 		}
738 
739 		public String getNewName() {
740 			return newName;
741 		}
742 	}
743 	
744 	public interface NodeNameChangedListener {
745 		public void nodeNameChanged(NodeNameChangedEvent event);
746 	}
747 	
748 	protected List<NodeNameChangedListener> nodeNameChangedListenerList = new ArrayList<NodeNameChangedListener>();
749 	
750 	public void addNodeNameChangedListener(NodeNameChangedListener listener) {
751 		nodeNameChangedListenerList.add(listener);
752 	}
753 	
754 	public void removeNodeNameChangedListener(NodeNameChangedListener listener) {
755 		nodeNameChangedListenerList.remove(listener);
756 	}
757 	
758 	protected void nameChanged(NodeNameChangedEvent event) {
759 		for (NodeNameChangedListener listener : nodeNameChangedListenerList) {
760 			listener.nodeNameChanged(event);
761 		}
762 	}
763 
764 	/* (non-Javadoc)
765 	 * @see unbbayes.prs.INode#addChildNode(unbbayes.prs.INode)
766 	 */
767 	public void addChildNode(INode child) throws InvalidParentException {
768 		this.addChild((Node)child);
769 	}
770 
771 	/* (non-Javadoc)
772 	 * @see unbbayes.prs.INode#addParentNode(unbbayes.prs.INode)
773 	 */
774 	public void addParentNode(INode parent) throws InvalidParentException {
775 		this.addParent((Node)parent);
776 	}
777 
778 	/* (non-Javadoc)
779 	 * @see unbbayes.prs.INode#getAdjacentNodeList()
780 	 */
781 	public List<INode> getAdjacentNodes() {
782 		this.makeAdjacents();
783 		return (List)this.getAdjacents();
784 	}
785 
786 	/* (non-Javadoc)
787 	 * @see unbbayes.prs.INode#getChildrenNodeList()
788 	 */
789 	public List<INode> getChildNodes() {
790 		return (List)this.getChildren();
791 	}
792 
793 	/* (non-Javadoc)
794 	 * @see unbbayes.prs.INode#getParentNodeList()
795 	 */
796 	public List<INode> getParentNodes() {
797 		return (List)this.getParents();
798 	}
799 
800 	/* (non-Javadoc)
801 	 * @see unbbayes.prs.INode#removeChildNode(unbbayes.prs.INode)
802 	 */
803 	public void removeChildNode(INode child) {
804 		this.removeChild((Node)child);
805 	}
806 
807 	/* (non-Javadoc)
808 	 * @see unbbayes.prs.INode#removeParentNode(unbbayes.prs.INode)
809 	 */
810 	public void removeParentNode(INode parent) {
811 		this.removeParent((Node)parent);
812 	}
813 
814 	/* (non-Javadoc)
815 	 * @see unbbayes.prs.INode#setChildrenNodeList(java.util.List)
816 	 */
817 	public void setChildNodes(List<INode> children) {
818 		this.setChildren (new SetList(children));
819 	}
820 
821 	/* (non-Javadoc)
822 	 * @see unbbayes.prs.INode#setParentNodeList(java.util.List)
823 	 */
824 	public void setParentNodes(List<INode> parents) {
825 		this.setParents(new SetList(parents));
826 	}
827 	
828 	/**
829 	 * This is just an ArrayList which does not allow duplicate elements
830 	 * @author Shou Matsumoto
831 	 *
832 	 */
833 	public class SetList<E> extends ArrayList<E> {
834 
835 		 /**
836 	     * Constructs an empty list with an initial capacity of ten.
837 	     */
838 		public SetList() {
839 			super();
840 		}
841 
842 		 /**
843 	     * Constructs a list containing the elements of the specified
844 	     * collection, in the order they are returned by the collection's
845 	     * iterator.  The <tt>ArrayList</tt> instance has an initial capacity of
846 	     * 110% the size of the specified collection.
847 	     *
848 	     * @param c the collection whose elements are to be placed into this list.
849 	     * @throws NullPointerException if the specified collection is null.
850 	     */
851 		public SetList(Collection c) {
852 			super(c);
853 		}
854 
855 		 /**
856 	     * Constructs an empty list with the specified initial capacity.
857 	     *
858 	     * @param   initialCapacity   the initial capacity of the list.
859 	     * @exception IllegalArgumentException if the specified initial capacity
860 	     *            is negative
861 	     */
862 		public SetList(int initialCapacity) {
863 			super(initialCapacity);
864 		}
865 
866 		/* (non-Javadoc)
867 		 * @see java.util.ArrayList#add(java.lang.Object)
868 		 */
869 		@Override
870 		public boolean add(E o) {
871 			if (this.contains(o)) {
872 				return false;
873 			}
874 			return super.add(o);
875 		}
876 
877 		/* (non-Javadoc)
878 		 * @see java.util.ArrayList#add(int, java.lang.Object)
879 		 */
880 		@Override
881 		public void add(int index, E element) {
882 			if (this.contains(element)) {
883 				return;
884 			}
885 			super.add(index, element);
886 		}
887 
888 		/* (non-Javadoc)
889 		 * @see java.util.ArrayList#addAll(java.util.Collection)
890 		 */
891 		@Override
892 		public boolean addAll(Collection<? extends E> c) {
893 			// TODO optimize
894 			boolean ret = false;
895 			for (E e : c) {
896 				ret = this.add(e) || ret;
897 			}
898 			return ret;
899 		}
900 
901 		/* (non-Javadoc)
902 		 * @see java.util.ArrayList#addAll(int, java.util.Collection)
903 		 */
904 		@Override
905 		public boolean addAll(int index, Collection<? extends E> c) {
906 			// TODO optimize
907 			int addedCount = 0;
908 			for (E e : c) {
909 				if (!this.contains(e)) {
910 					super.add(index + addedCount, e);
911 					addedCount++;
912 				}
913 			}
914 			return true;
915 		}
916 		
917 	}
918 
919 }