View Javadoc
1   package de.fhdw.wtf.context.model.collections;
2   
3   import java.util.Iterator;
4   import java.util.Vector;
5   
6   import de.fhdw.wtf.context.core.TransactionManager;
7   import de.fhdw.wtf.context.exception.FrameworkException;
8   import de.fhdw.wtf.context.model.AnyType;
9   import de.fhdw.wtf.context.model.Anything;
10  import de.fhdw.wtf.context.model.Int;
11  import de.fhdw.wtf.context.model.Str;
12  import de.fhdw.wtf.context.model.collections.functors.Predicate;
13  import de.fhdw.wtf.context.model.collections.functors.Procedure;
14  import de.fhdw.wtf.persistence.meta.Object;
15  import de.fhdw.wtf.persistence.meta.UnidirectionalLink;
16  import de.fhdw.wtf.persistence.meta.UserObject;
17  import de.fhdw.wtf.persistence.utils.Tuple;
18  
19  /**
20   * A class to represent a mutable list of objects with persistence integration. It also represents an
21   * UnidirectionalAssociation therefore all changes on this collection will directly affect the associated owner object.
22   * 
23   * @param <T>
24   *            Any Type T, which is subtype of Anything.
25   */
26  public class PersistentListWithLinks<T extends Anything> implements MutableCollection<T> {
27  	
28  	/**
29  	 * A collection of Links which is used to operate on this association.
30  	 */
31  	private final java.util.Collection<Tuple<UnidirectionalLink, Object>> unidirectionalLinks;
32  	
33  	/**
34  	 * The name of the association to which this collection belongs.
35  	 */
36  	private final String associationName;
37  	
38  	/**
39  	 * The owner object of this association.
40  	 */
41  	private final UserObject owner;
42  	
43  	/**
44  	 * Creates a new PersistentListWithLinks object.
45  	 * 
46  	 * @param unidirectionalLinks
47  	 *            The unidirectionalLinks, which are the elements to the association.
48  	 * @param associationName
49  	 *            The name of the association.
50  	 * @param owner
51  	 *            The owner of the association.
52  	 */
53  	public PersistentListWithLinks(final java.util.Collection<Tuple<UnidirectionalLink, Object>> unidirectionalLinks,
54  			final String associationName,
55  			final UserObject owner) {
56  		super();
57  		this.unidirectionalLinks = unidirectionalLinks;
58  		this.associationName = associationName;
59  		this.owner = owner;
60  	}
61  	
62  	@Override
63  	public Collection<T> union(final Collection<? extends T> otherCollection) {
64  		if (otherCollection instanceof ImmutableCollection) {
65  			this.addImmutableCollection((ImmutableCollection<? extends T>) otherCollection);
66  		} else if (otherCollection instanceof MutableCollection) {
67  			this.addMutableCollection((MutableCollection<? extends T>) otherCollection);
68  		} else {
69  			throw new FrameworkException("Collection is not supported");
70  		}
71  		return this;
72  	}
73  	
74  	/**
75  	 * Adds the elements of a MutableCollection to this list.
76  	 * 
77  	 * @param otherCollection
78  	 *            The MutableCollection.
79  	 */
80  	private void addMutableCollection(final MutableCollection<? extends T> otherCollection) {
81  		final Iterator<? extends T> iterator = otherCollection.iterator();
82  		while (iterator.hasNext()) {
83  			final T current = iterator.next();
84  			this.insert(current);
85  		}
86  	}
87  	
88  	/**
89  	 * Adds the elements of an ImmutableCollection to this list.
90  	 * 
91  	 * @param otherCollection
92  	 *            The ImmutableCollection.
93  	 */
94  	private void addImmutableCollection(final ImmutableCollection<? extends T> otherCollection) {
95  		if (!otherCollection.isEmpty()) {
96  			this.insert(otherCollection.front());
97  			this.addImmutableCollection(otherCollection.tail());
98  		}
99  	}
100 	
101 	@Override
102 	public boolean contains(final T element) {
103 		final Iterator<T> iterator = this.iterator();
104 		while (iterator.hasNext()) {
105 			final T current = iterator.next();
106 			if (element.equals(current)) {
107 				return true;
108 			}
109 		}
110 		return false;
111 	}
112 	
113 	@Override
114 	public void insert(final T element) {
115 		if (element instanceof AnyType) {
116 			final AnyType toAdd = (AnyType) element;
117 			final UnidirectionalLink nw =
118 					TransactionManager.getContext().set(this.owner, this.associationName, toAdd.getObject());
119 			this.unidirectionalLinks.add(new Tuple<>(nw, nw.getTarget()));
120 		} else if (element instanceof Int) {
121 			final Int toAdd = (Int) element;
122 			final UnidirectionalLink nw =
123 					TransactionManager.getContext().set(this.owner, this.associationName, toAdd.getVal());
124 			this.unidirectionalLinks.add(new Tuple<>(nw, nw.getTarget()));
125 		} else if (element instanceof Str) {
126 			final Str toAdd = (Str) element;
127 			final UnidirectionalLink nw =
128 					TransactionManager.getContext().set(this.owner, this.associationName, toAdd.toString());
129 			this.unidirectionalLinks.add(new Tuple<>(nw, nw.getTarget()));
130 		} else {
131 			throw new FrameworkException("Type to insert is not known");
132 		}
133 		
134 	}
135 	
136 	@Override
137 	public void apply(final Procedure<T> procedure) {
138 		final Iterator<T> iterator = this.iterator();
139 		while (iterator.hasNext()) {
140 			final T current = iterator.next();
141 			procedure.op(current);
142 		}
143 	}
144 	
145 	@Override
146 	public void remove(final Predicate<T> predicate) {
147 		final Iterator<T> iterator = this.iterator();
148 		while (iterator.hasNext()) {
149 			final T current = iterator.next();
150 			if (predicate.p(current)) {
151 				iterator.remove();
152 			}
153 		}
154 	}
155 	
156 	@Override
157 	public Iterator<T> iterator() {
158 		return new PersistenceIteratorWithLink<>(this.unidirectionalLinks);
159 	}
160 	
161 	@Override
162 	public boolean isEmpty() {
163 		return this.unidirectionalLinks.isEmpty();
164 	}
165 	
166 	@Override
167 	public ImmutableCollection<T> copy() {
168 		ImmutableCollection<T> result = new ImmutableList<>();
169 		final Iterator<T> iterator = this.iterator();
170 		while (iterator.hasNext()) {
171 			final T current = iterator.next();
172 			result = result.add(current);
173 		}
174 		return result;
175 	}
176 	
177 	@Override
178 	public String toString() {
179 		final Vector<T> result = new Vector<>();
180 		final Iterator<T> i = this.iterator();
181 		while (i.hasNext()) {
182 			final T current = i.next();
183 			result.add(current);
184 		}
185 		return result.toString();
186 	}
187 	
188 	@Override
189 	public boolean equals(final java.lang.Object obj) {
190 		if (obj instanceof MutableCollection<?>) {
191 			try {
192 				@SuppressWarnings("unchecked")
193 				final MutableCollection<T> other = (MutableCollection<T>) obj;
194 				final Iterator<T> thisIterator = this.iterator();
195 				while (thisIterator.hasNext()) {
196 					final T current = thisIterator.next();
197 					if (!other.contains(current)) {
198 						return false;
199 					}
200 				}
201 				final Iterator<T> otherIterator = other.iterator();
202 				while (otherIterator.hasNext()) {
203 					final T current = otherIterator.next();
204 					if (!this.contains(current)) {
205 						return false;
206 					}
207 				}
208 				return true;
209 			} catch (final ClassCastException e) {
210 				return false;
211 			}
212 		}
213 		return false;
214 	}
215 	
216 	@Override
217 	public int hashCode() {
218 		return this.copy().hashCode();
219 	}
220 }