Skip to content

Method: isOpenTransaction(Transaction)

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: }