View Javadoc
1   package de.fhdw.wtf.persistence.facade;
2   
3   import java.math.BigInteger;
4   import java.sql.SQLException;
5   import java.util.Collection;
6   import java.util.Date;
7   import java.util.HashMap;
8   import java.util.HashSet;
9   import java.util.Iterator;
10  import java.util.LinkedList;
11  import java.util.Map;
12  import java.util.regex.Matcher;
13  import java.util.regex.Pattern;
14  
15  import de.fhdw.wtf.persistence.exception.BaseTypeNotFoundException;
16  import de.fhdw.wtf.persistence.exception.InvalidLinkException;
17  import de.fhdw.wtf.persistence.exception.NotInstantiatableException;
18  import de.fhdw.wtf.persistence.exception.NotValidInputException;
19  import de.fhdw.wtf.persistence.exception.ObjectNotFoundException;
20  import de.fhdw.wtf.persistence.exception.PersistenceException;
21  import de.fhdw.wtf.persistence.meta.AdhocTransaction;
22  import de.fhdw.wtf.persistence.meta.Association;
23  import de.fhdw.wtf.persistence.meta.IntegerType;
24  import de.fhdw.wtf.persistence.meta.IntegerValue;
25  import de.fhdw.wtf.persistence.meta.Link;
26  import de.fhdw.wtf.persistence.meta.MapAssociation;
27  import de.fhdw.wtf.persistence.meta.MapLink;
28  import de.fhdw.wtf.persistence.meta.Object;
29  import de.fhdw.wtf.persistence.meta.StringType;
30  import de.fhdw.wtf.persistence.meta.StringValue;
31  import de.fhdw.wtf.persistence.meta.Transaction;
32  import de.fhdw.wtf.persistence.meta.Type;
33  import de.fhdw.wtf.persistence.meta.UnidirectionalAssociation;
34  import de.fhdw.wtf.persistence.meta.UnidirectionalLink;
35  import de.fhdw.wtf.persistence.meta.UserObject;
36  import de.fhdw.wtf.persistence.meta.UserType;
37  import de.fhdw.wtf.persistence.utils.Tuple;
38  
39  /**
40   * The class that should be used as the object facade if you do not use a database in the background.
41   * 
42   * @author hfw413hy
43   *
44   */
45  public class NoDatabaseObjectFacadeImplementation implements ObjectFacade {
46  	
47  	/**
48  	 * Represents the id which will be given to the first thing with an identifier which has been created by this
49  	 * ObjectFacade. Will be set during the ObjectFacades instantiation or during an execution of the clear-operation.
50  	 */
51  	private static final long INITIAL_NEXT_ID = 1;
52  	
53  	/**
54  	 * This ClassFacade is needed to perform consistency checks in regard to the model layer of the meta-model.
55  	 */
56  	private final ClassFacade classFacade;
57  	
58  	/**
59  	 * This field contains the next identifier for something that can be created within this ObjectFacade.
60  	 */
61  	private long nextId;
62  	
63  	/**
64  	 * Maps an id to its corresponding instance of UserObject.
65  	 */
66  	private final Map<Long, UserObject> idToUserObject;
67  	
68  	/**
69  	 * Stores all UserTypes (values) which are instances of a UserType (the key).
70  	 */
71  	private final Map<UserType, Collection<UserObject>> userTypeMappingToUserObjects;
72  	
73  	/**
74  	 * Stores the Information "ID -> Value".
75  	 */
76  	private final Map<Long, BigInteger> integerValues;
77  	
78  	/**
79  	 * Stores the Information "Value -> ID".
80  	 */
81  	private final Map<BigInteger, Long> inverseIntegerValues;
82  	
83  	/**
84  	 * Stores the Information "ID -> String".
85  	 */
86  	private final Map<Long, String> stringValues;
87  	
88  	/**
89  	 * Stores the Information "String -> ID".
90  	 */
91  	private final Map<String, Long> inverseStringValues;
92  	
93  	/**
94  	 * A map consisting of link-targets (keys) and collections of tuples with the targets corresponding links and their
95  	 * owners (values).
96  	 */
97  	private final Map<Object, Collection<Tuple<UnidirectionalLink, UserObject>>> targetMappingToUnidirectionalLinksWithOwners;
98  	
99  	/**
100 	 * A map consisting of link-owners (keys) and collections of tuples with the owners corresponding links and their
101 	 * targets (values).
102 	 */
103 	private final Map<UserObject, Collection<Tuple<UnidirectionalLink, Object>>> ownerMappingToUnidirectionalLinksWithTargets;
104 	
105 	/**
106 	 * Stores the Information "Owner (of the MapLink) -> MapLink". The MapLink contains information about the
107 	 * MapAssociation, the Owner, the Target and the Key.
108 	 */
109 	private final HashMap<UserObject, Collection<MapLink>> ownerMappingToMapLinks;
110 	
111 	/**
112 	 * Stores the Information "Target (in a MapLink) -> MapLink". The MapLink contains information about the
113 	 * MapAssociation, the Owner, the Target and the Key.
114 	 */
115 	private final HashMap<Object, Collection<MapLink>> targetMappingToMapLinks;
116 	
117 	/**
118 	 * Stores the Information "Association -> Collection of StringValue/UserObject". This is important to improve the
119 	 * "find"-Method.
120 	 */
121 	private final HashMap<UnidirectionalAssociation, Collection<Tuple<UserObject, StringValue>>> associationToStringValue;
122 	
123 	/**
124 	 * Stores the Information "Association -> Collection of IntegerValue/UserObject". This is important to improve the
125 	 * "find"-Method.
126 	 */
127 	private final HashMap<UnidirectionalAssociation, Collection<Tuple<UserObject, IntegerValue>>> associationToIntegerValue;
128 	
129 	/**
130 	 * Constructor for instances of NoDatabaseObjectFacadeImplementation.
131 	 * 
132 	 * @param classFacade
133 	 *            is needed to perform consistency checks in regard to the model layer of the meta-model. It must have
134 	 *            been initialized to function correctly within this ObjectFacade.
135 	 */
136 	public NoDatabaseObjectFacadeImplementation(final ClassFacade classFacade) {
137 		super();
138 		IntegerValue.setObjectFacade(this);
139 		StringValue.setObjectFacade(this);
140 		this.classFacade = classFacade;
141 		this.nextId = NoDatabaseObjectFacadeImplementation.INITIAL_NEXT_ID;
142 		this.userTypeMappingToUserObjects = new HashMap<>();
143 		this.integerValues = new HashMap<>();
144 		this.stringValues = new HashMap<>();
145 		this.inverseIntegerValues = new HashMap<>();
146 		this.inverseStringValues = new HashMap<>();
147 		this.idToUserObject = new HashMap<>();
148 		this.targetMappingToUnidirectionalLinksWithOwners = new HashMap<>();
149 		this.ownerMappingToUnidirectionalLinksWithTargets = new HashMap<>();
150 		this.ownerMappingToMapLinks = new HashMap<>();
151 		this.targetMappingToMapLinks = new HashMap<>();
152 		this.associationToStringValue = new HashMap<>();
153 		this.associationToIntegerValue = new HashMap<>();
154 	}
155 	
156 	@Override
157 	public void clear() throws PersistenceException {
158 		this.nextId = NoDatabaseObjectFacadeImplementation.INITIAL_NEXT_ID;
159 		this.userTypeMappingToUserObjects.clear();
160 		this.integerValues.clear();
161 		this.stringValues.clear();
162 		this.inverseIntegerValues.clear();
163 		this.inverseStringValues.clear();
164 		this.idToUserObject.clear();
165 		this.ownerMappingToUnidirectionalLinksWithTargets.clear();
166 		this.targetMappingToUnidirectionalLinksWithOwners.clear();
167 		this.ownerMappingToMapLinks.clear();
168 		this.targetMappingToMapLinks.clear();
169 		this.associationToStringValue.clear();
170 		this.associationToIntegerValue.clear();
171 	}
172 	
173 	@Override
174 	public Collection<UserObject> find(final Association association, final String searchPatternOracle, final Date date)
175 			throws PersistenceException {
176 		// Replacing oracle wildcards against standard (perl?) regex wildcards
177 		// TODO: Currently only replacing % against * -- Take a closer look to the complete oracle LIKE
178 		// syntax and translate to corresponding standard regular expression wildcards.
179 		
180 		final String searchPatternRegex = searchPatternOracle.replaceAll("\\*", "\\\\*").replaceAll("%+", ".*");
181 		final Pattern searchPattern = Pattern.compile(searchPatternRegex);
182 		
183 		final HashSet<UserObject> result = new HashSet<>();
184 		if (!this.associationToStringValue.containsKey(association)) {
185 			return result;
186 		}
187 		
188 		final Iterator<Tuple<UserObject, StringValue>> it = this.associationToStringValue.get(association).iterator();
189 		while (it.hasNext()) {
190 			final Tuple<UserObject, StringValue> current = it.next();
191 			final String target = current.getSecond().getValue();
192 			
193 			final Matcher targetSearchMatcher = searchPattern.matcher(target);
194 			if (targetSearchMatcher.matches()) {
195 				result.add(current.getFirst());
196 			}
197 		}
198 		return result;
199 	}
200 	
201 	@Override
202 	public Collection<UserObject> find(final Association association, final BigInteger integer, final Date date)
203 			throws PersistenceException {
204 		final HashSet<UserObject> result = new HashSet<>();
205 		if (!this.associationToIntegerValue.containsKey(association)) {
206 			return result;
207 		}
208 		
209 		final Iterator<Tuple<UserObject, IntegerValue>> it = this.associationToIntegerValue.get(association).iterator();
210 		while (it.hasNext()) {
211 			final Tuple<UserObject, IntegerValue> current = it.next();
212 			final BigInteger target = current.getSecond().getValue();
213 			if (integer.equals(target)) {
214 				result.add(current.getFirst());
215 			}
216 		}
217 		return result;
218 	}
219 	
220 	@Override
221 	public Collection<Tuple<UnidirectionalLink, Object>> get(final UserObject owner,
222 			final UnidirectionalAssociation association,
223 			final Date date) throws PersistenceException {
224 		return this.get(owner, association);
225 	}
226 	
227 	@Override
228 	public Collection<Object> get(final UserObject owner,
229 			final MapAssociation association,
230 			final String key,
231 			final Date date) throws PersistenceException {
232 		final Collection<Object> result = new LinkedList<>();
233 		if (!this.ownerMappingToMapLinks.containsKey(owner)) {
234 			return result;
235 		}
236 		final Iterator<MapLink> it = this.ownerMappingToMapLinks.get(owner).iterator();
237 		while (it.hasNext()) {
238 			final MapLink currentMapLink = it.next();
239 			if (currentMapLink.getInstanceOf().equals(association) && currentMapLink.getKey() instanceof StringValue) {
240 				if (((StringValue) currentMapLink.getKey()).getValue().equals(key)) {
241 					result.add(currentMapLink.getTarget());
242 				}
243 			}
244 		}
245 		if (result.isEmpty()) {
246 			throw new ObjectNotFoundException();
247 		}
248 		return result;
249 	}
250 	
251 	@Override
252 	public Collection<Object> get(final UserObject owner,
253 			final MapAssociation association,
254 			final BigInteger key,
255 			final Date date) throws PersistenceException {
256 		final Collection<Object> result = new LinkedList<>();
257 		if (!this.ownerMappingToMapLinks.containsKey(owner)) {
258 			return result;
259 		}
260 		final Iterator<MapLink> it = this.ownerMappingToMapLinks.get(owner).iterator();
261 		while (it.hasNext()) {
262 			final MapLink currentMapLink = it.next();
263 			if (currentMapLink.getInstanceOf().equals(association) && currentMapLink.getKey() instanceof IntegerValue) {
264 				if (((IntegerValue) currentMapLink.getKey()).getValue().equals(key)) {
265 					result.add(currentMapLink.getTarget());
266 				}
267 			}
268 		}
269 		if (result.isEmpty()) {
270 			throw new ObjectNotFoundException();
271 		}
272 		return result;
273 	}
274 	
275 	@Override
276 	public Collection<Object> get(final UserObject owner,
277 			final MapAssociation association,
278 			final UserObject key,
279 			final Date date) throws PersistenceException {
280 		if (key == null) {
281 			throw new NotValidInputException("");
282 		}
283 		final Collection<Object> result = new LinkedList<>();
284 		if (!this.ownerMappingToMapLinks.containsKey(owner)) {
285 			return result;
286 		}
287 		final Iterator<MapLink> it = this.ownerMappingToMapLinks.get(owner).iterator();
288 		while (it.hasNext()) {
289 			final MapLink currentMapLink = it.next();
290 			if (currentMapLink.getInstanceOf().equals(association) && currentMapLink.getKey() instanceof UserObject) {
291 				if (currentMapLink.getKey().equals(key)) {
292 					result.add(currentMapLink.getTarget());
293 				}
294 			}
295 		}
296 		if (result.isEmpty()) {
297 			throw new ObjectNotFoundException();
298 		}
299 		return result;
300 	}
301 	
302 	@Override
303 	public Collection<Tuple<UnidirectionalLink, UserObject>> inverseGet(final UserObject target,
304 			final UnidirectionalAssociation association,
305 			final Date date) throws PersistenceException {
306 		return this.inverseGet(target, association);
307 	}
308 	
309 	@Override
310 	public Collection<Tuple<UserObject, Object>> inverseGet(final UserObject target,
311 			final MapAssociation association,
312 			final Date date) throws PersistenceException {
313 		final Collection<Tuple<UserObject, Object>> result = new LinkedList<>();
314 		if (!this.targetMappingToMapLinks.containsKey(target)) {
315 			return result;
316 		}
317 		final Iterator<MapLink> it = this.targetMappingToMapLinks.get(target).iterator();
318 		while (it.hasNext()) {
319 			final MapLink currentMapLink = it.next();
320 			if (currentMapLink.getInstanceOf().equals(association)) {
321 				result.add(new Tuple<>(currentMapLink.getOwner(), currentMapLink.getKey()));
322 			}
323 		}
324 		return result;
325 	}
326 	
327 	@Override
328 	public Collection<Tuple<UserObject, Object>> inverseGet(final String target,
329 			final MapAssociation association,
330 			final Date date) throws PersistenceException {
331 		final Collection<Tuple<UserObject, Object>> result = new LinkedList<>();
332 		final Iterator<Object> itMain = this.targetMappingToMapLinks.keySet().iterator();
333 		while (itMain.hasNext()) {
334 			final Object ob = itMain.next();
335 			if (!(ob instanceof StringValue)) {
336 				continue;
337 			}
338 			final StringValue val = (StringValue) ob;
339 			if (!val.getValue().equals(target)) {
340 				continue;
341 			}
342 			final Iterator<MapLink> it = this.targetMappingToMapLinks.get(val).iterator();
343 			while (it.hasNext()) {
344 				final MapLink currentMapLink = it.next();
345 				if (currentMapLink.getInstanceOf().equals(association)) {
346 					result.add(new Tuple<>(currentMapLink.getOwner(), currentMapLink.getKey()));
347 				}
348 			}
349 		}
350 		return result;
351 	}
352 	
353 	@Override
354 	public Collection<Tuple<UserObject, Object>> inverseGet(final BigInteger target,
355 			final MapAssociation association,
356 			final Date date) throws PersistenceException {
357 		final Collection<Tuple<UserObject, Object>> result = new LinkedList<>();
358 		final Iterator<Object> itMain = this.targetMappingToMapLinks.keySet().iterator();
359 		while (itMain.hasNext()) {
360 			final Object ob = itMain.next();
361 			if (!(ob instanceof IntegerValue)) {
362 				continue;
363 			}
364 			final IntegerValue val = (IntegerValue) ob;
365 			if (!val.getValue().equals(target)) {
366 				continue;
367 			}
368 			final Iterator<MapLink> it = this.targetMappingToMapLinks.get(val).iterator();
369 			while (it.hasNext()) {
370 				final MapLink currentMapLink = it.next();
371 				if (currentMapLink.getInstanceOf().equals(association)) {
372 					result.add(new Tuple<>(currentMapLink.getOwner(), currentMapLink.getKey()));
373 				}
374 			}
375 		}
376 		return result;
377 	}
378 	
379 	@Override
380 	public Collection<UserObject> find(final Association assoc, final String str, final Transaction trans)
381 			throws PersistenceException {
382 		return this.find(assoc, str, new Date());
383 	}
384 	
385 	@Override
386 	public Collection<UserObject> find(final Association association,
387 			final BigInteger integer,
388 			final Transaction transaction) throws PersistenceException {
389 		return this.find(association, integer, new Date());
390 	}
391 	
392 	@Override
393 	public Collection<Tuple<UnidirectionalLink, Object>> get(final UserObject owner,
394 			final UnidirectionalAssociation association,
395 			final Transaction transaction) throws PersistenceException {
396 		return this.get(owner, association);
397 	}
398 	
399 	/**
400 	 * Provides a collection of Tuples of Links and Objects. The Links are instances of the UnidirectionalAssociation
401 	 * association. And the Objects are the owner of the Links. type(owner) has to be is sub type of the owner of the
402 	 * UnidirectionalAssociation association.
403 	 * 
404 	 * @param owner
405 	 *            the owner of the links.
406 	 * @param association
407 	 *            the type of the links.
408 	 * @return a list with tuples consisting the links and their targets.
409 	 */
410 	private Collection<Tuple<UnidirectionalLink, Object>> get(final UserObject owner,
411 			final UnidirectionalAssociation association) {
412 		final Collection<Tuple<UnidirectionalLink, Object>> result = new LinkedList<>();
413 		if (!this.ownerMappingToUnidirectionalLinksWithTargets.containsKey(owner)) {
414 			return result;
415 		}
416 		final Iterator<Tuple<UnidirectionalLink, Object>> allLinksForOwner =
417 				this.ownerMappingToUnidirectionalLinksWithTargets.get(owner).iterator();
418 		while (allLinksForOwner.hasNext()) {
419 			final Tuple<UnidirectionalLink, Object> currentTuple = allLinksForOwner.next();
420 			if (currentTuple.getFirst().getInstanceOf().equals(association)) {
421 				result.add(currentTuple);
422 			}
423 		}
424 		return result;
425 	}
426 	
427 	@Override
428 	public Collection<Tuple<MapLink, Object>> get(final UserObject owner,
429 			final MapAssociation association,
430 			final String key,
431 			final Transaction transaction) throws PersistenceException {
432 		final Collection<Tuple<MapLink, Object>> result = new HashSet<>();
433 		if (!this.ownerMappingToMapLinks.containsKey(owner)) {
434 			throw new ObjectNotFoundException();
435 		}
436 		final Iterator<MapLink> it = this.ownerMappingToMapLinks.get(owner).iterator();
437 		while (it.hasNext()) {
438 			final MapLink currentMapLink = it.next();
439 			if (currentMapLink.getInstanceOf().equals(association)) {
440 				if (((StringValue) currentMapLink.getKey()).getValue().equals(key)) {
441 					result.add(new Tuple<>(currentMapLink, currentMapLink.getTarget()));
442 				}
443 			}
444 		}
445 		if (result.isEmpty()) {
446 			throw new ObjectNotFoundException();
447 		}
448 		return result;
449 	}
450 	
451 	@Override
452 	public Collection<Tuple<MapLink, Object>> get(final UserObject owner,
453 			final MapAssociation association,
454 			final BigInteger key,
455 			final Transaction transaction) throws PersistenceException {
456 		final Collection<Tuple<MapLink, Object>> result = new HashSet<>();
457 		if (!this.ownerMappingToMapLinks.containsKey(owner)) {
458 			return result;
459 		}
460 		final Iterator<MapLink> it = this.ownerMappingToMapLinks.get(owner).iterator();
461 		while (it.hasNext()) {
462 			final MapLink currentMapLink = it.next();
463 			if (currentMapLink.getInstanceOf().equals(association)) {
464 				if (((IntegerValue) currentMapLink.getKey()).getValue().equals(key)) {
465 					result.add(new Tuple<>(currentMapLink, currentMapLink.getTarget()));
466 				}
467 			}
468 		}
469 		return result;
470 	}
471 	
472 	@Override
473 	public Collection<Tuple<MapLink, Object>> get(final UserObject owner,
474 			final MapAssociation association,
475 			final UserObject key,
476 			final Transaction transaction) throws PersistenceException {
477 		if (key == null) {
478 			throw new NotValidInputException("");
479 		}
480 		final Collection<Tuple<MapLink, Object>> result = new HashSet<>();
481 		if (!this.ownerMappingToMapLinks.containsKey(owner)) {
482 			return result;
483 		}
484 		final Iterator<MapLink> it = this.ownerMappingToMapLinks.get(owner).iterator();
485 		while (it.hasNext()) {
486 			final MapLink currentMapLink = it.next();
487 			if (currentMapLink.getInstanceOf().equals(association)) {
488 				if (currentMapLink.getKey().equals(key)) {
489 					result.add(new Tuple<>(currentMapLink, currentMapLink.getTarget()));
490 				}
491 			}
492 		}
493 		return result;
494 	}
495 	
496 	@Override
497 	public Collection<Tuple<UnidirectionalLink, UserObject>> inverseGet(final UserObject target,
498 			final UnidirectionalAssociation association,
499 			final Transaction transaction) throws PersistenceException {
500 		return this.inverseGet(target, association);
501 	}
502 	
503 	/**
504 	 * Provides a collection of Tuples of Links and User Objects. The Links are instances of the
505 	 * UnidirectionalAssociation association. And the User Objects are the targets of the Links. type(target) has to be
506 	 * is sub type of the target of the UnidirectionalAssociation association.
507 	 * 
508 	 * @param target
509 	 *            the target of the links.
510 	 * @param association
511 	 *            the type of the links.
512 	 * @return tuples with all links of type association; with the target target as first component and the links owner
513 	 *         as second component.
514 	 */
515 	private Collection<Tuple<UnidirectionalLink, UserObject>> inverseGet(final UserObject target,
516 			final UnidirectionalAssociation association) {
517 		final Collection<Tuple<UnidirectionalLink, UserObject>> result = new LinkedList<>();
518 		if (!this.targetMappingToUnidirectionalLinksWithOwners.containsKey(target)) {
519 			return result;
520 		}
521 		final Iterator<Tuple<UnidirectionalLink, UserObject>> allLinksForTarget =
522 				this.targetMappingToUnidirectionalLinksWithOwners.get(target).iterator();
523 		while (allLinksForTarget.hasNext()) {
524 			final Tuple<UnidirectionalLink, UserObject> currentTuple = allLinksForTarget.next();
525 			if (currentTuple.getFirst().getInstanceOf().equals(association)) {
526 				result.add(currentTuple);
527 			}
528 		}
529 		return result;
530 	}
531 	
532 	@Override
533 	public Collection<Tuple<UserObject, Object>> inverseGet(final UserObject target,
534 			final MapAssociation association,
535 			final Transaction transaction) throws PersistenceException {
536 		return this.inverseGet(target, association, new Date());
537 	}
538 	
539 	@Override
540 	public Collection<Tuple<UserObject, Object>> inverseGet(final String target,
541 			final MapAssociation association,
542 			final Transaction transaction) throws PersistenceException {
543 		return this.inverseGet(target, association, new Date());
544 	}
545 	
546 	@Override
547 	public Collection<Tuple<UserObject, Object>> inverseGet(final BigInteger target,
548 			final MapAssociation association,
549 			final Transaction transaction) throws PersistenceException {
550 		return this.inverseGet(target, association, new Date());
551 	}
552 	
553 	@Override
554 	public boolean isInConflict(final Transaction before, final Transaction after) throws PersistenceException {
555 		// We do not support transactions!
556 		return false;
557 	}
558 	
559 	@Override
560 	public boolean isOpenTransaction(final Transaction transaction) throws PersistenceException {
561 		// We do not support transactions!
562 		return true;
563 	}
564 	
565 	@Override
566 	public UserObject create(final UserType type, final Transaction transaction) throws PersistenceException {
567 		if (type.isAbs()) {
568 			throw new NotInstantiatableException(new SQLException());
569 		}
570 		final UserObject result = UserObject.init(this.getAndIncrementNextId(), type);
571 		this.idToUserObject.put(result.getId(), result);
572 		this.mapUserTypeToEmptyListIfNotExists(type);
573 		this.userTypeMappingToUserObjects.get(type).add(result);
574 		return result;
575 	}
576 	
577 	@Override
578 	public void delete(final UserObject object, final Transaction transaction) throws PersistenceException {
579 		// ID -> UserObject
580 		this.idToUserObject.remove(object.getId());
581 		
582 		// UserType -> UserObject
583 		this.userTypeMappingToUserObjects.get(object.getInstanceOf()).remove(object);
584 		
585 		// Owner of a Link
586 		this.ownerMappingToUnidirectionalLinksWithTargets.remove(object);
587 		
588 		// Target of a Link
589 		this.targetMappingToUnidirectionalLinksWithOwners.remove(object);
590 		
591 		// Owner of a MapLink
592 		this.ownerMappingToMapLinks.remove(object);
593 		
594 		// Target of a MapLink
595 		this.targetMappingToMapLinks.remove(object);
596 		
597 		this.deleteFromFindMap(object.getInstanceOf(), object.getId());
598 	}
599 	
600 	private void deleteFromFindMap(final Type type, final long id) throws PersistenceException {
601 		// TODO: Remove from associationToStringValue
602 		// TODO: Remove from associationToIntegerValue
603 	}
604 	
605 	@Override
606 	public UnidirectionalLink set(final UserObject owner,
607 			final UnidirectionalAssociation association,
608 			final UserObject target,
609 			final Transaction transaction) throws PersistenceException {
610 		this.checkAssociationUnidirectional(association, owner.getInstanceOf(), target.getInstanceOf());
611 		return this.set(owner, association, target);
612 	}
613 	
614 	@Override
615 	public UnidirectionalLink set(final UserObject owner,
616 			final UnidirectionalAssociation association,
617 			final BigInteger target,
618 			final Transaction transaction) throws PersistenceException {
619 		this.checkAssociationUnidirectional(association, owner.getInstanceOf(), IntegerType.getInstance());
620 		return this.set(owner, association, new IntegerValue(target));
621 	}
622 	
623 	@Override
624 	public UnidirectionalLink set(final UserObject owner,
625 			final UnidirectionalAssociation association,
626 			final String target,
627 			final Transaction transaction) throws PersistenceException {
628 		this.checkAssociationUnidirectional(association, owner.getInstanceOf(), StringType.getInstance());
629 		return this.set(owner, association, new StringValue(target));
630 	}
631 	
632 	/**
633 	 * Creates a new UnidirectionalLink of type association consisting of an owner and its target.
634 	 * 
635 	 * @param owner
636 	 *            the owner of the link.
637 	 * @param association
638 	 *            the type of the link.
639 	 * @param target
640 	 *            the target of the link.
641 	 * @return a new UnidirectionalLink of type association consisting of an owner and its target.
642 	 * @throws PersistenceException
643 	 *             if the type of owner is not a descendant of the associations owner-type and that the type of the
644 	 *             target is not a descendant of the associations target-type. Throws an exception if the check is
645 	 *             negative.
646 	 * 
647 	 */
648 	private UnidirectionalLink set(final UserObject owner,
649 			final UnidirectionalAssociation association,
650 			final Object target) throws PersistenceException {
651 		this.throwInvalidLinkExceptionIfWrongTypeForLink(owner, association, target);
652 		final UnidirectionalLink result =
653 				new UnidirectionalLink(this.getAndIncrementNextId(), owner, target, association);
654 		final Tuple<UnidirectionalLink, Object> tupleForOwner = new Tuple<>(result, target);
655 		if (!this.ownerMappingToUnidirectionalLinksWithTargets.containsKey(owner)) {
656 			this.ownerMappingToUnidirectionalLinksWithTargets.put(
657 					owner,
658 					new LinkedList<Tuple<UnidirectionalLink, Object>>());
659 		}
660 		final Tuple<UnidirectionalLink, UserObject> tupleForTarget = new Tuple<>(result, owner);
661 		if (!this.targetMappingToUnidirectionalLinksWithOwners.containsKey(target)) {
662 			this.targetMappingToUnidirectionalLinksWithOwners.put(
663 					target,
664 					new LinkedList<Tuple<UnidirectionalLink, UserObject>>());
665 		}
666 		if (association.isUnique()) {
667 			this.deleteAllOwnerUnidirectionalLinksWhichAreInstanceOf(owner, association);
668 			this.deleteAllTargetUnidirectionalLinksWhichAreInstanceOf(target, association);
669 		}
670 		this.ownerMappingToUnidirectionalLinksWithTargets.get(owner).add(tupleForOwner);
671 		this.targetMappingToUnidirectionalLinksWithOwners.get(target).add(tupleForTarget);
672 		
673 		// Used to improve the performance of "find" (String)
674 		if (target instanceof StringValue) {
675 			if (!this.associationToStringValue.containsKey(association)) {
676 				this.associationToStringValue.put(association, new LinkedList<Tuple<UserObject, StringValue>>());
677 			}
678 			this.associationToStringValue.get(association).add(new Tuple<>(owner, (StringValue) target));
679 		}
680 		if (target instanceof IntegerValue) {
681 			if (!this.associationToIntegerValue.containsKey(association)) {
682 				this.associationToIntegerValue.put(association, new LinkedList<Tuple<UserObject, IntegerValue>>());
683 			}
684 			this.associationToIntegerValue.get(association).add(new Tuple<>(owner, (IntegerValue) target));
685 		}
686 		
687 		return result;
688 	}
689 	
690 	/**
691 	 * Deletes all links with the target target which are type of association from the
692 	 * targetMappingToUnidirectionalLinksWithOwners-map.
693 	 * 
694 	 * @param target
695 	 *            the target of those links
696 	 * @param association
697 	 *            the type of those links
698 	 */
699 	private void deleteAllTargetUnidirectionalLinksWhichAreInstanceOf(final Object target,
700 			final UnidirectionalAssociation association) {
701 		if (this.targetMappingToUnidirectionalLinksWithOwners.containsKey(target)) {
702 			final Iterator<Tuple<UnidirectionalLink, UserObject>> allLinks =
703 					this.targetMappingToUnidirectionalLinksWithOwners.get(target).iterator();
704 			while (allLinks.hasNext()) {
705 				if (allLinks.next().getFirst().getInstanceOf().equals(association)) {
706 					allLinks.remove();
707 				}
708 			}
709 		}
710 	}
711 	
712 	/**
713 	 * Deletes all links with the owner owner which are type of association from the
714 	 * ownerMappingToUnidirectionalLinksWithTargets-map.
715 	 * 
716 	 * @param owner
717 	 *            the owner of those links
718 	 * @param association
719 	 *            the type of those links
720 	 */
721 	private void deleteAllOwnerUnidirectionalLinksWhichAreInstanceOf(final UserObject owner,
722 			final UnidirectionalAssociation association) {
723 		if (this.ownerMappingToUnidirectionalLinksWithTargets.containsKey(owner)) {
724 			final Iterator<Tuple<UnidirectionalLink, Object>> allLinks =
725 					this.ownerMappingToUnidirectionalLinksWithTargets.get(owner).iterator();
726 			while (allLinks.hasNext()) {
727 				if (allLinks.next().getFirst().getInstanceOf().equals(association)) {
728 					allLinks.remove();
729 				}
730 			}
731 		}
732 	}
733 	
734 	@Override
735 	public MapLink put(final UserObject owner,
736 			final MapAssociation association,
737 			final UserObject target,
738 			final String key,
739 			final Transaction transaction) throws PersistenceException {
740 		return this.putInternal(owner, association, target, new StringValue(key));
741 	}
742 	
743 	@Override
744 	public MapLink put(final UserObject owner,
745 			final MapAssociation association,
746 			final BigInteger target,
747 			final String key,
748 			final Transaction transaction) throws PersistenceException {
749 		return this.putInternal(owner, association, new IntegerValue(target), new StringValue(key));
750 	}
751 	
752 	@Override
753 	public MapLink put(final UserObject owner,
754 			final MapAssociation association,
755 			final String target,
756 			final String key,
757 			final Transaction transaction) throws PersistenceException {
758 		return this.putInternal(owner, association, new StringValue(target), new StringValue(key));
759 	}
760 	
761 	@Override
762 	public MapLink put(final UserObject owner,
763 			final MapAssociation association,
764 			final UserObject target,
765 			final BigInteger key,
766 			final Transaction transaction) throws PersistenceException {
767 		return this.putInternal(owner, association, target, new IntegerValue(key));
768 	}
769 	
770 	@Override
771 	public MapLink put(final UserObject owner,
772 			final MapAssociation association,
773 			final BigInteger target,
774 			final BigInteger key,
775 			final Transaction transaction) throws PersistenceException {
776 		return this.putInternal(owner, association, new IntegerValue(target), new IntegerValue(key));
777 	}
778 	
779 	@Override
780 	public MapLink put(final UserObject owner,
781 			final MapAssociation association,
782 			final String target,
783 			final BigInteger key,
784 			final Transaction transaction) throws PersistenceException {
785 		return this.putInternal(owner, association, new StringValue(target), new IntegerValue(key));
786 	}
787 	
788 	@Override
789 	public MapLink put(final UserObject owner,
790 			final MapAssociation association,
791 			final UserObject target,
792 			final UserObject key,
793 			final Transaction transaction) throws PersistenceException {
794 		return this.putInternal(owner, association, target, key);
795 	}
796 	
797 	@Override
798 	public MapLink put(final UserObject owner,
799 			final MapAssociation association,
800 			final BigInteger target,
801 			final UserObject key,
802 			final Transaction transaction) throws PersistenceException {
803 		return this.putInternal(owner, association, new IntegerValue(target), key);
804 	}
805 	
806 	@Override
807 	public MapLink put(final UserObject owner,
808 			final MapAssociation association,
809 			final String target,
810 			final UserObject key,
811 			final Transaction transaction) throws PersistenceException {
812 		return this.putInternal(owner, association, new StringValue(target), key);
813 	}
814 	
815 	private MapLink putInternal(final UserObject owner,
816 			final MapAssociation association,
817 			final Object target,
818 			final Object key) throws PersistenceException {
819 		this.checkAssociationMap(association, owner.getInstanceOf(), target.getInstanceOf(), key.getInstanceOf());
820 		
821 		if (!this.ownerMappingToMapLinks.containsKey(owner)) {
822 			this.ownerMappingToMapLinks.put(owner, new LinkedList<MapLink>());
823 		}
824 		if (!this.targetMappingToMapLinks.containsKey(target)) {
825 			this.targetMappingToMapLinks.put(target, new LinkedList<MapLink>());
826 		}
827 		
828 		// TODO Check "isUnique()"? IMPORTANT!!!
829 		
830 		final MapLink result = new MapLink(this.getAndIncrementNextId(), owner, target, key, association);
831 		
832 		this.ownerMappingToMapLinks.get(owner).add(result);
833 		this.targetMappingToMapLinks.get(target).add(result);
834 		
835 		return result;
836 	}
837 	
838 	@Override
839 	public void unset(final Link link, final Transaction transaction) throws PersistenceException {
840 		// We do not support transactions!
841 	}
842 	
843 	@Override
844 	public void commit(final Transaction transaction) throws PersistenceException {
845 		// We do not support transactions!
846 	}
847 	
848 	@Override
849 	public void rollback(final Transaction transaction) throws PersistenceException {
850 		// We do not support transactions!
851 	}
852 	
853 	@Override
854 	public void savePoint(final Transaction transaction) throws PersistenceException {
855 		// We do not support transactions!
856 	}
857 	
858 	@Override
859 	public void rollbackToSavePoint(final Transaction transaction) throws PersistenceException {
860 		// We do not support transactions!
861 	}
862 	
863 	@Override
864 	public BigInteger getIntForId(final long id) throws PersistenceException {
865 		if (!this.integerValues.containsKey(id)) {
866 			throw new BaseTypeNotFoundException();
867 		}
868 		return this.integerValues.get(id);
869 	}
870 	
871 	@Override
872 	public String getStringForId(final long id) throws PersistenceException {
873 		if (!this.stringValues.containsKey(id)) {
874 			throw new BaseTypeNotFoundException();
875 		}
876 		return this.stringValues.get(id);
877 	}
878 	
879 	@Override
880 	public long getIdForString(final String string) throws PersistenceException {
881 		if (!this.inverseStringValues.containsKey(string)) {
882 			final long newId = this.getAndIncrementNextId();
883 			this.stringValues.put(newId, string);
884 			this.inverseStringValues.put(string, newId);
885 		}
886 		return this.inverseStringValues.get(string);
887 	}
888 	
889 	@Override
890 	public long getIdForInteger(final BigInteger integer) throws PersistenceException {
891 		if (!this.inverseIntegerValues.containsKey(integer)) {
892 			final long newId = this.getAndIncrementNextId();
893 			this.integerValues.put(newId, integer);
894 			this.inverseIntegerValues.put(integer, newId);
895 		}
896 		return this.inverseIntegerValues.get(integer);
897 	}
898 	
899 	@Override
900 	public Transaction provideAdhocTransaction() throws PersistenceException {
901 		return new AdhocTransaction(this.getAndIncrementNextId());
902 	}
903 	
904 	@Override
905 	public TypeManager getTypeManager() {
906 		return TypeManagerImplementation.getInstance();
907 	}
908 	
909 	@Override
910 	public Collection<UserObject> findAllObjects(final UserType type, final Transaction transaction)
911 			throws PersistenceException {
912 		this.mapUserTypeToEmptyListIfNotExists(type);
913 		return this.userTypeMappingToUserObjects.get(type);
914 	}
915 	
916 	@Override
917 	public UserObject checkUserObjectOut(final long id, final Transaction transaction) throws PersistenceException {
918 		if (!this.idToUserObject.containsKey(id)) {
919 			throw new ObjectNotFoundException();
920 		}
921 		return this.idToUserObject.get(id);
922 	}
923 	
924 	/**
925 	 * Adds the mapping from a given type to an empty collection if the type doesn't exists as key in the
926 	 * userTypeMappingToUserObjects-collection.
927 	 * 
928 	 * @param type
929 	 *            the given type.
930 	 */
931 	private void mapUserTypeToEmptyListIfNotExists(final UserType type) {
932 		if (!this.userTypeMappingToUserObjects.containsKey(type)) {
933 			this.userTypeMappingToUserObjects.put(type, new LinkedList<UserObject>());
934 		}
935 	}
936 	
937 	/**
938 	 * @return Returns the next free id.
939 	 */
940 	private long getAndIncrementNextId() {
941 		final long result = this.nextId;
942 		this.nextId++;
943 		return result;
944 	}
945 	
946 	/**
947 	 * Checks if the given components of a new UnidirectionalLink will match the association.
948 	 * 
949 	 * @param association
950 	 *            The given UnidirectionalAssociation where the user wants to create an instance
951 	 * @param owner
952 	 *            The new owner of this Link instance
953 	 * @param target
954 	 *            The new target of this Link instance
955 	 * @throws PersistenceException
956 	 *             A InvalidLinkException will be thrown if the types do not match
957 	 */
958 	private void checkAssociationUnidirectional(final UnidirectionalAssociation association,
959 			final Type owner,
960 			final Type target) throws PersistenceException {
961 		if (!association.getOwner().isTheSameAs(owner)
962 				&& !this.classFacade.isSuperClassTo(association.getOwner(), owner)) {
963 			throw new InvalidLinkException(new SQLException());
964 		}
965 		
966 		if (!association.getTarget().isTheSameAs(target)
967 				&& !this.classFacade.isSuperClassTo(association.getTarget(), target)) {
968 			throw new InvalidLinkException(new SQLException());
969 		}
970 	}
971 	
972 	/**
973 	 * Checks if the given components of a new MapLink will match the association.
974 	 * 
975 	 * @param association
976 	 *            The given MapAssociation where the user wants to create an MapLink instance
977 	 * @param owner
978 	 *            The new owner of this MapLink instance
979 	 * @param target
980 	 *            The new target of this MapLink instance
981 	 * @param key
982 	 *            The new key of this MapLink instance
983 	 * @throws PersistenceException
984 	 *             A InvalidLinkException will be thrown if the types do not match
985 	 */
986 	private void checkAssociationMap(final MapAssociation association,
987 			final Type owner,
988 			final Type target,
989 			final Type key) throws PersistenceException {
990 		if (!association.getOwner().isTheSameAs(owner)
991 				&& !this.classFacade.isSuperClassTo(association.getOwner(), owner)
992 				&& !this.classFacade.isSuperClassTo(owner, association.getOwner())) {
993 			throw new InvalidLinkException(null);
994 		}
995 		
996 		if (!association.getTarget().isTheSameAs(target)
997 				&& !this.classFacade.isSuperClassTo(association.getTarget(), target)
998 				&& !this.classFacade.isSuperClassTo(target, association.getTarget())) {
999 			throw new InvalidLinkException(new SQLException());
1000 		}
1001 		
1002 		if (!association.getKeyType().isTheSameAs(key)
1003 				&& !this.classFacade.isSuperClassTo(association.getKeyType(), key)
1004 				&& !this.classFacade.isSuperClassTo(key, association.getKeyType())) {
1005 			throw new InvalidLinkException(new SQLException());
1006 		}
1007 	}
1008 	
1009 	/**
1010 	 * Checks if the type of owner is a descendant of the associations owner-type and that the type of the target is a
1011 	 * descendant of the associations target-type. Throws an exception if the check is negative.
1012 	 * 
1013 	 * @param owner
1014 	 *            the potential owner of a link.
1015 	 * @param association
1016 	 *            the type of a potential link consisting of owner and an instance of targetType.
1017 	 * @param target
1018 	 *            the potential target of a link.
1019 	 * @throws PersistenceException
1020 	 *             if the check mentioned above is negative.
1021 	 */
1022 	private void throwInvalidLinkExceptionIfWrongTypeForLink(final UserObject owner,
1023 			final UnidirectionalAssociation association,
1024 			final Object target) throws PersistenceException {
1025 		if (!this.classFacade.isSuperClassTo(association.getTarget(), target.getInstanceOf())
1026 				|| !this.classFacade.isSuperClassTo(association.getOwner(), owner.getInstanceOf())) {
1027 			throw new InvalidLinkException(new SQLException());
1028 		}
1029 	}
1030 	
1031 }