Skip to content

Method: checkIfStringIsCorrect(Collection)

1: package de.fhdw.wtf.persistence.facade;
2:
3: import java.sql.CallableStatement;
4: import java.sql.ResultSet;
5: import java.sql.SQLException;
6: import java.util.Collection;
7: import java.util.Iterator;
8: import java.util.List;
9: import java.util.Vector;
10:
11: import oracle.jdbc.OracleCallableStatement;
12: import oracle.jdbc.OracleTypes;
13: import oracle.sql.ARRAY;
14: import oracle.sql.ArrayDescriptor;
15: import de.fhdw.wtf.persistence.exception.ClassFacadeUninitializedException;
16: import de.fhdw.wtf.persistence.exception.InitializingDatabaseContractViolationException;
17: import de.fhdw.wtf.persistence.exception.OtherSQLException;
18: import de.fhdw.wtf.persistence.exception.PersistenceException;
19: import de.fhdw.wtf.persistence.exception.SpecializationCycleDetected;
20: import de.fhdw.wtf.persistence.meta.Association;
21: import de.fhdw.wtf.persistence.meta.IntegerType;
22: import de.fhdw.wtf.persistence.meta.MapAssociation;
23: import de.fhdw.wtf.persistence.meta.StringType;
24: import de.fhdw.wtf.persistence.meta.Type;
25: import de.fhdw.wtf.persistence.meta.UnidirectionalAssociation;
26: import de.fhdw.wtf.persistence.meta.UserType;
27: import de.fhdw.wtf.persistence.utils.IntegerConstants;
28:
29: /**
30: * A class to represent an implementation of the ClassFacade Interface for the Oracle Database. Supports a Database
31: * Initializer.
32: */
33: public class OracleClassFacadeImplementation implements ClassFacade {
34:         
35:         /**
36:          * A flag to determine, if the ClassFacade was initialized,e.g. TypeManager is filled with information and base
37:          * types are initialized.
38:          */
39:         private boolean initialized;
40:         
41:         /**
42:          * The Type Manager which stores the Model Item informations.
43:          */
44:         private TypeManagerImplementation typeManager;
45:         
46:         /**
47:          * The Oracle Database Manager, which is needed to call the Database.
48:          */
49:         private final OracleDatabaseManager database;
50:         
51:         /**
52:          * Constructor for a new OracleClassFacadeImplementation.
53:          *
54:          * @param database
55:          * The OracleDatabaseManager, which has to be connected.
56:          */
57:         public OracleClassFacadeImplementation(final OracleDatabaseManager database) {
58:                 this.database = database;
59:                 this.initialized = false;
60:                 this.typeManager = TypeManagerImplementation.getInstance();
61:         }
62:         
63:         @Override
64:         public UserType createUserType(final String name, final boolean abs, final boolean transaction)
65:                         throws PersistenceException {
66:                 final UserType result = new UserType(IDManager.instance().pullNextUnusedTypeID(name), name, abs, transaction);
67:                 try (final CallableStatement call =
68:                                 this.database.getConnection().prepareCall(
69:                                                 "begin " + this.database.getSchemaName() + ".classfacade.createUserType(?,?,?,?); end;")) {
70:                         call.setLong(1, result.getId());
71:                         call.setString(2, result.getName());
72:                         call.setInt(IntegerConstants.THREE, result.isAbs() ? 1 : 0);
73:                         call.setInt(IntegerConstants.FOUR, result.isTrans() ? 1 : 0);
74:                         call.execute();
75:                 } catch (final SQLException e) {
76:                         throw new OtherSQLException(e);
77:                 }
78:                 this.typeManager.saveType(result);
79:                 return result;
80:         }
81:         
82:         @Override
83:         public UnidirectionalAssociation createUnidirectionalAssociation(final String name,
84:                         final boolean essential,
85:                         final boolean unique,
86:                         final UserType owner,
87:                         final Type target) throws PersistenceException {
88:                 final UnidirectionalAssociation result =
89:                                 new UnidirectionalAssociation(IDManager.instance().pullNextUnusedAssociationID(name), name, owner,
90:                                                 target, essential, unique);
91:                 try (final CallableStatement call =
92:                                 this.database.getConnection().prepareCall(
93:                                                 "begin " + this.database.getSchemaName()
94:                                                                 + ".classfacade.createUnidirAssociation(?,?,?,?,?,?); end;")) {
95:                         call.setLong(1, result.getId());
96:                         call.setString(2, result.getName());
97:                         call.setLong(IntegerConstants.THREE, result.getOwner().getId());
98:                         call.setLong(IntegerConstants.FOUR, result.getTarget().getId());
99:                         call.setInt(IntegerConstants.FIVE, result.isEssential() ? 1 : 0);
100:                         call.setInt(IntegerConstants.SIX, result.isUnique() ? 1 : 0);
101:                         call.execute();
102:                 } catch (final SQLException e) {
103:                         throw new OtherSQLException(e);
104:                 }
105:                 this.typeManager.saveAssociation(result);
106:                 return result;
107:         }
108:         
109:         @Override
110:         public MapAssociation createMapAssociation(final String name,
111:                         final boolean essential,
112:                         final UserType owner,
113:                         final Type target,
114:                         final Type keyType) throws PersistenceException {
115:                 final MapAssociation result =
116:                                 new MapAssociation(IDManager.instance().pullNextUnusedAssociationID(name), name, owner, target,
117:                                                 keyType, essential);
118:                 try (final CallableStatement call =
119:                                 this.database.getConnection().prepareCall(
120:                                                 "begin " + this.database.getSchemaName()
121:                                                                 + ".classfacade.createMapAssociation(?,?,?,?,?,?,?); end;")) {
122:                         call.setLong(1, result.getId());
123:                         call.setString(2, result.getName());
124:                         call.setLong(IntegerConstants.THREE, result.getOwner().getId());
125:                         call.setLong(IntegerConstants.FOUR, result.getTarget().getId());
126:                         call.setInt(IntegerConstants.FIVE, result.isEssential() ? 1 : 0);
127:                         call.setInt(IntegerConstants.SIX, 1);
128:                         call.setLong(IntegerConstants.SEVEN, result.getKeyType().getId());
129:                         call.execute();
130:                 } catch (final SQLException e) {
131:                         throw new OtherSQLException(e);
132:                 }
133:                 this.typeManager.saveAssociation(result);
134:                 return result;
135:         }
136:         
137:         @Override
138:         public void createSpecializationBetween(final UserType ancestor, final Type descendant) throws PersistenceException {
139:                 try (final CallableStatement call =
140:                                 this.database.getConnection().prepareCall(
141:                                                 "begin " + this.database.getSchemaName() + ".classfacade.createSpecialization(?,?); end;")) {
142:                         call.setLong(1, ancestor.getId());
143:                         call.setLong(2, descendant.getId());
144:                         call.execute();
145:                 } catch (final SQLException e) {
146:                         throw new OtherSQLException(e);
147:                 }
148:         }
149:         
150:         @Override
151:         public void initialize() throws PersistenceException {
152:                 try (final CallableStatement call =
153:                                 this.database.getConnection().prepareCall(
154:                                                 "begin " + this.database.getSchemaName() + ".classfacade.initialize; end;")) {
155:                         call.execute();
156:                 } catch (final SQLException e) {
157:                         throw new OtherSQLException(e);
158:                 }
159:                 
160:                 try (final CallableStatement call =
161:                                 this.database.getConnection().prepareCall(
162:                                                 "begin ? :=" + this.database.getSchemaName() + ".classfacade.getMaxIdFromType; end;")) {
163:                         call.registerOutParameter(1, OracleTypes.NUMBER);
164:                         call.execute();
165:                         if (IDManager.getMaxBaseTypeID() != call.getLong(1)) {
166:                                 throw new InitializingDatabaseContractViolationException();
167:                         }
168:                 } catch (final SQLException e) {
169:                         throw new OtherSQLException(e);
170:                 }
171:                 
172:                 try (final CallableStatement call =
173:                                 this.database.getConnection().prepareCall(
174:                                                 "begin ? :=" + this.database.getSchemaName() + ".classfacade.getMaxIdFromAssociation; end;")) {
175:                         call.registerOutParameter(1, OracleTypes.NUMBER);
176:                         call.execute();
177:                         if (IDManager.getMaxAssociationContractID() != call.getLong(1)) {
178:                                 throw new InitializingDatabaseContractViolationException();
179:                         }
180:                 } catch (final SQLException e) {
181:                         throw new OtherSQLException(e);
182:                 }
183:                 
184:                 this.initializeBaseTypes();
185:                 this.finalizeSpecialization();
186:                 this.initialized = true;
187:         }
188:         
189:         @Override
190:         public boolean isSuperClassTo(final Type ancestor, final Type descendant) throws PersistenceException {
191:                 try (final CallableStatement call =
192:                                 this.database.getConnection().prepareCall(
193:                                                 "begin ?:=" + this.database.getSchemaName() + ".classfacade.isSuperclassTo(?,?); end;")) {
194:                         call.registerOutParameter(1, OracleTypes.NUMBER);
195:                         call.setLong(2, ancestor.getId());
196:                         call.setLong(IntegerConstants.THREE, descendant.getId());
197:                         call.execute();
198:                         return call.getInt(1) == 1 ? true : false;
199:                 } catch (final SQLException e) {
200:                         e.printStackTrace();
201:                         throw new OtherSQLException(e);
202:                 }
203:         }
204:         
205:         @Override
206:         public void clear() throws PersistenceException {
207:                 try (final CallableStatement call =
208:                                 this.database.getConnection().prepareCall(
209:                                                 "begin " + this.database.getSchemaName() + ".classfacade.clearAll; end;")) {
210:                         call.execute();
211:                 } catch (final SQLException e) {
212:                         throw new OtherSQLException(e);
213:                 }
214:         }
215:         
216:         @Override
217:         public void finalizeSpecialization() throws PersistenceException {
218:                 try (final CallableStatement call =
219:                                 this.database.getConnection().prepareCall(
220:                                                 "begin " + this.database.getSchemaName() + ".classfacade.finalizeSpecialization; end;")) {
221:                         call.execute();
222:                 } catch (final SQLException e) {
223:                         if (e.getErrorCode() == SpecializationCycleDetected.ERRORCODE) {
224:                                 throw new SpecializationCycleDetected(e);
225:                         }
226:                         e.printStackTrace();
227:                         throw new OtherSQLException(e);
228:                 }
229:         }
230:         
231:         @Override
232:         public void renameType(final Long typeId, final String newName) throws PersistenceException {
233:                 try (final CallableStatement call =
234:                                 this.database.getConnection().prepareCall(
235:                                                 "begin " + this.database.getSchemaName() + ".classfacade.renameType(?,?); end;")) {
236:                         call.setLong(1, typeId);
237:                         call.setString(2, newName);
238:                         call.execute();
239:                 } catch (final SQLException e) {
240:                         e.printStackTrace();
241:                         throw new OtherSQLException(e);
242:                 }
243:         }
244:         
245:         @Override
246:         public void renameAssociation(final Long associationId, final String newName) throws PersistenceException {
247:                 try (final CallableStatement call =
248:                                 this.database.getConnection().prepareCall(
249:                                                 "begin " + this.database.getSchemaName() + ".classfacade.renameAssociation(?,?); end;")) {
250:                         call.setLong(1, associationId);
251:                         call.setString(2, newName);
252:                         call.execute();
253:                 } catch (final SQLException e) {
254:                         e.printStackTrace();
255:                         throw new OtherSQLException(e);
256:                 }
257:         }
258:         
259:         @Override
260:         public void deleteAssociation(final Long assoId) throws PersistenceException {
261:                 this.typeManager.deleteAssociation(assoId);
262:                 try (final CallableStatement call =
263:                                 this.database.getConnection().prepareCall(
264:                                                 "begin " + this.database.getSchemaName() + ".classfacade.deleteAssociation(?); end;")) {
265:                         call.setLong(1, assoId);
266:                         call.execute();
267:                 } catch (final SQLException e) {
268:                         e.printStackTrace();
269:                         throw new OtherSQLException(e);
270:                 }
271:         }
272:         
273:         @Override
274:         public void updateLinksToNewAssociation(final Long assoId, final Collection<Long> newAssociationIds)
275:                         throws PersistenceException {
276:                 try (final CallableStatement call =
277:                                 this.database.getConnection().prepareCall(
278:                                                 "begin " + this.database.getSchemaName() + ".classfacade.pushDownLinks(?,?); end;")) {
279:                         call.setLong(1, assoId);
280:                         final ArrayDescriptor des =
281:                                         ArrayDescriptor.createDescriptor(
282:                                                         this.database.getSchemaName().toUpperCase() + ".ARRAY_INT",
283:                                                         this.database.getConnection());
284:                         final Long[] newAssos = newAssociationIds.toArray(new Long[newAssociationIds.size()]);
285:                         final ARRAY arrayNewAssociation = new ARRAY(des, this.database.getConnection(), newAssos);
286:                         call.setArray(2, arrayNewAssociation);
287:                         call.execute();
288:                 } catch (final SQLException e) {
289:                         e.printStackTrace();
290:                         throw new OtherSQLException(e);
291:                 }
292:         }
293:         
294:         @Override
295:         public void deleteUserType(final Long typeId) throws PersistenceException {
296:                 this.typeManager.deleteType(typeId);
297:                 try (final CallableStatement call =
298:                                 this.database.getConnection().prepareCall(
299:                                                 "begin " + this.database.getSchemaName() + ".classfacade.deleteUserTypeAndSpec(?); end;")) {
300:                         call.setLong(1, typeId);
301:                         call.execute();
302:                 } catch (final SQLException e) {
303:                         e.printStackTrace();
304:                         throw new OtherSQLException(e);
305:                 }
306:         }
307:         
308:         @Override
309:         public void moveLinksAndCreateObjects(final List<Long> oldAssoIds,
310:                         final Association newAsso,
311:                         final UserType newType,
312:                         final List<Long> newAssoIds) throws PersistenceException {
313:                 try (final CallableStatement call =
314:                                 this.database.getConnection().prepareCall(
315:                                                 "begin " + this.database.getSchemaName()
316:                                                                 + ".classfacade.moveLinksAndCreateObjects(?,?,?,?); end;")) {
317:                         // TODO Implement database function!
318:                         final ArrayDescriptor des =
319:                                         ArrayDescriptor.createDescriptor(
320:                                                         this.database.getSchemaName().toUpperCase() + ".ARRAY_INT",
321:                                                         this.database.getConnection());
322:                         final Long[] oldAssosA = oldAssoIds.toArray(new Long[oldAssoIds.size()]);
323:                         final Long[] newAssosA = newAssoIds.toArray(new Long[newAssoIds.size()]);
324:                         final ARRAY arrayNewAssociations = new ARRAY(des, this.database.getConnection(), newAssosA);
325:                         final ARRAY arrayOldAssociations = new ARRAY(des, this.database.getConnection(), oldAssosA);
326:                         
327:                         call.setArray(1, arrayOldAssociations);
328:                         call.setLong(2, newAsso.getId());
329:                         call.setLong(IntegerConstants.THREE, newType.getId());
330:                         call.setArray(IntegerConstants.FOUR, arrayNewAssociations);
331:                         call.execute();
332:                 } catch (final SQLException e) {
333:                         e.printStackTrace();
334:                         throw new OtherSQLException(e);
335:                 }
336:         }
337:         
338:         @Override
339:         public TypeManager getTypeManager() throws ClassFacadeUninitializedException {
340:                 if (!this.hasBeenInitialized()) {
341:                         throw new ClassFacadeUninitializedException();
342:                 }
343:                 return this.typeManager;
344:         }
345:         
346:         private void initializeBaseTypes() {
347:                 this.typeManager.saveType(StringType.getInstance());
348:                 this.typeManager.saveType(IntegerType.getInstance());
349:         }
350:         
351:         /**
352:          * A private method to check if an Object exists in the types Collection with the type information (id, name) of the
353:          * String Type from the contract and removes this object from the types Collection, if it exists.
354:          *
355:          * @param types
356:          * A Collection of Types.
357:          * @return Provides true if an Object with the string type information exists.
358:          */
359:         private boolean checkIfStringIsCorrect(final Collection<Type> types) {
360:                 final Iterator<Type> i = types.iterator();
361:•                while (i.hasNext()) {
362:                         final Type current = i.next();
363:•                        if (current.getId() == 1 && current.getName().equals(StringType.STRING_NAME)) {
364:                                 i.remove();
365:                                 return true;
366:                         }
367:                 }
368:                 return false;
369:         }
370:         
371:         /**
372:          * A private method to check if an Object exists in the types Collection with the type information (id, name) of the
373:          * Integer Type from the contract and removes this object from the types Collection, if it exists.
374:          *
375:          * @param types
376:          * A Collection of Types.
377:          * @return Provides true if an Object with the integer type information exists.
378:          */
379:         private boolean checkIfIntegerIsCorrect(final Collection<Type> types) {
380:                 final Iterator<Type> i = types.iterator();
381:                 while (i.hasNext()) {
382:                         final Type current = i.next();
383:                         if (current.getId() == 2 && current.getName().equals(IntegerType.INTEGER_NAME)) {
384:                                 i.remove();
385:                                 return true;
386:                         }
387:                 }
388:                 return false;
389:         }
390:         
391:         @Override
392:         public boolean hasBeenInitialized() {
393:                 return this.initialized;
394:         }
395:         
396:         @Override
397:         public void initializeForRuntime() throws PersistenceException {
398:                 this.typeManager = TypeManagerImplementation.getInstance();
399:                 final Collection<Type> types = new Vector<>();
400:                 try (final CallableStatement call =
401:                                 this.database.getConnection().prepareCall(
402:                                                 "begin ?:= " + this.database.getSchemaName() + ".classfacade.getAllTypes; end;")) {
403:                         call.registerOutParameter(1, OracleTypes.CURSOR);
404:                         call.execute();
405:                         
406:                         try (final ResultSet result = ((OracleCallableStatement) call).getCursor(1)) {
407:                                 while (result.next()) {
408:                                         types.add(new UserType(result.getLong(1), result.getString(2), result
409:                                                         .getInt(IntegerConstants.THREE) == 1 ? true : false,
410:                                                         result.getInt(IntegerConstants.FOUR) == 1 ? true : false));
411:                                 }
412:                         }
413:                 } catch (final SQLException e) {
414:                         throw new OtherSQLException(e);
415:                 }
416:                 
417:                 if (!this.checkIfStringIsCorrect(types)) {
418:                         throw new InitializingDatabaseContractViolationException();
419:                 }
420:                 if (!this.checkIfIntegerIsCorrect(types)) {
421:                         throw new InitializingDatabaseContractViolationException();
422:                 }
423:                 this.initializeBaseTypes();
424:                 for (final Type t : types) {
425:                         this.typeManager.saveType(t);
426:                 }
427:                 
428:                 try (final CallableStatement call =
429:                                 this.database.getConnection().prepareCall(
430:                                                 "begin ?:= " + this.database.getSchemaName() + ".classfacade.getAllUnidirAssociations; end;")) {
431:                         call.registerOutParameter(1, OracleTypes.CURSOR);
432:                         call.execute();
433:                         
434:                         final Collection<UnidirectionalAssociation> unidirectionalAssociations = new Vector<>();
435:                         try (final ResultSet result = ((OracleCallableStatement) call).getCursor(1)) {
436:                                 while (result.next()) {
437:                                         unidirectionalAssociations.add(new UnidirectionalAssociation(result.getLong(1),
438:                                                         result.getString(2), (UserType) this.typeManager.getTypeForId(result
439:                                                                         .getLong(IntegerConstants.THREE)), this.typeManager.getTypeForId(result
440:                                                                         .getLong(IntegerConstants.FOUR)), result.getInt(IntegerConstants.FIVE) == 1 ? true
441:                                                                         : false, result.getInt(IntegerConstants.SIX) == 1 ? true : false));
442:                                 }
443:                         }
444:                         final Iterator<UnidirectionalAssociation> i = unidirectionalAssociations.iterator();
445:                         while (i.hasNext()) {
446:                                 final UnidirectionalAssociation current = i.next();
447:                                 this.typeManager.saveAssociation(current);
448:                         }
449:                 } catch (final SQLException e) {
450:                         throw new OtherSQLException(e);
451:                 }
452:                 
453:                 try (final CallableStatement call =
454:                                 this.database.getConnection().prepareCall(
455:                                                 "begin ?:= " + this.database.getSchemaName() + ".classfacade.getAllMapAssociations; end;")) {
456:                         call.registerOutParameter(1, OracleTypes.CURSOR);
457:                         call.execute();
458:                         
459:                         final Collection<MapAssociation> mapAssociations = new Vector<>();
460:                         try (final ResultSet result = ((OracleCallableStatement) call).getCursor(1)) {
461:                                 while (result.next()) {
462:                                         mapAssociations.add(new MapAssociation(result.getLong(1), result.getString(2),
463:                                                         (UserType) this.typeManager.getTypeForId(result.getLong(IntegerConstants.THREE)),
464:                                                         this.typeManager.getTypeForId(result.getLong(IntegerConstants.FOUR)), this.typeManager
465:                                                                         .getTypeForId(result.getLong(IntegerConstants.FIVE)), result
466:                                                                         .getInt(IntegerConstants.SIX) == 1 ? true : false));
467:                                 }
468:                         }
469:                         final Iterator<MapAssociation> i = mapAssociations.iterator();
470:                         while (i.hasNext()) {
471:                                 final MapAssociation current = i.next();
472:                                 this.typeManager.saveAssociation(current);
473:                         }
474:                 } catch (final SQLException e) {
475:                         throw new OtherSQLException(e);
476:                 }
477:                 
478:                 this.initialized = true;
479:                 // TODO set the lastSetTypeId and the lastSetAssociationId correctly
480:         }
481:         
482: }