1 package de.fhdw.wtf.persistence.facade;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileNotFoundException;
6 import java.io.FileOutputStream;
7 import java.io.IOException;
8 import java.sql.CallableStatement;
9 import java.sql.ResultSet;
10 import java.sql.SQLException;
11 import java.util.Iterator;
12 import java.util.Properties;
13
14 import oracle.jdbc.OracleCallableStatement;
15 import oracle.jdbc.OracleTypes;
16 import de.fhdw.wtf.persistence.exception.IDContractViolationException;
17 import de.fhdw.wtf.persistence.exception.IDNotFoundForNameException;
18 import de.fhdw.wtf.persistence.exception.IDPersistenceFilesNotFound;
19 import de.fhdw.wtf.persistence.exception.OtherSQLException;
20 import de.fhdw.wtf.persistence.exception.PersistenceException;
21 import de.fhdw.wtf.persistence.meta.IntegerType;
22 import de.fhdw.wtf.persistence.meta.StringType;
23
24
25
26
27
28
29
30
31
32
33
34 public final class IDManager {
35
36
37
38
39
40 private static final long MAX_BASE_TYPES = 2;
41
42
43
44
45
46 private static final long MAX_CONTRACT_ASSOCIATION_ID = 0;
47
48
49 public static final String TYPE_IDS_FILENAME = "types.properties";
50
51
52
53
54 public static final String ASSOCIATION_IDS_FILENAME = "associations.properties";
55
56 private static IDManager instance = null;
57 private final Properties typeNameIdRelation;
58 private final Properties associationNameIdRelation;
59 private long currentlyUsedTypeMaxId;
60 private long currentlyUsedAssociationMaxId;
61
62 private IDManager() {
63 this.typeNameIdRelation = new Properties();
64 this.associationNameIdRelation = new Properties();
65 this.currentlyUsedAssociationMaxId = getMaxAssociationContractID();
66 this.currentlyUsedTypeMaxId = getMaxBaseTypeID();
67 }
68
69
70
71
72
73 private void recalibrateMaxTypeID() {
74 final Iterator<String> it = this.typeNameIdRelation.stringPropertyNames().iterator();
75 while (it.hasNext()) {
76 final String currentKey = it.next();
77 final Long currentId = Long.parseLong(this.typeNameIdRelation.getProperty(currentKey));
78 if (this.currentlyUsedTypeMaxId < currentId) {
79 this.currentlyUsedTypeMaxId = currentId;
80 }
81 }
82
83 }
84
85
86
87
88
89 private void recalibrateMaxAssociationID() {
90 final Iterator<String> it = this.associationNameIdRelation.stringPropertyNames().iterator();
91 while (it.hasNext()) {
92 final String currentKey = it.next();
93 final Long currentId = Long.parseLong(this.associationNameIdRelation.getProperty(currentKey));
94 if (this.currentlyUsedAssociationMaxId < currentId) {
95 this.currentlyUsedAssociationMaxId = currentId;
96 }
97 }
98 }
99
100
101
102
103
104
105
106
107
108
109
110
111 public void initializeRelationsFromFile(final String typeIdsFilename, final String associationIdsFilename)
112 throws FileNotFoundException, IOException {
113 final File fileType = new File(typeIdsFilename);
114 final File fileAssociation = new File(associationIdsFilename);
115
116 if (fileType.exists() && !fileType.isDirectory() && fileAssociation.exists() && !fileAssociation.isDirectory()) {
117 try (final FileInputStream fileTypeInputStream = new FileInputStream(fileType);
118 final FileInputStream fileAssociationInputStream = new FileInputStream(fileAssociation)) {
119 this.typeNameIdRelation.load(fileTypeInputStream);
120 this.associationNameIdRelation.load(fileAssociationInputStream);
121 }
122 } else {
123 throw new IDPersistenceFilesNotFound();
124 }
125 this.typeNameIdRelation.setProperty(StringType.STRING_NAME, Long.toString(StringType.String_ID));
126 this.typeNameIdRelation.setProperty(IntegerType.INTEGER_NAME, Long.toString(IntegerType.Integer_ID));
127 this.recalibrateMaxTypeID();
128 this.recalibrateMaxAssociationID();
129
130 }
131
132
133
134
135
136
137
138
139 public void initializeRelationsFromDatabase() throws PersistenceException, SQLException {
140 final OracleDatabaseManager database = OracleDatabaseManager.getInstance();
141 try {
142 database.getConnection();
143 } catch (final PersistenceException e) {
144 database.connect();
145 }
146
147 try (final CallableStatement call =
148 database.getConnection().prepareCall(
149 "begin ?:= " + database.getSchemaName() + ".classfacade.getAllTypes; end;")) {
150 call.registerOutParameter(1, OracleTypes.CURSOR);
151 call.execute();
152
153 try (final ResultSet result = ((OracleCallableStatement) call).getCursor(1)) {
154 while (result.next()) {
155 this.typeNameIdRelation.setProperty(result.getString(2), Long.toString(result.getLong(1)));
156 }
157 }
158 } catch (final SQLException e) {
159 throw new OtherSQLException(e);
160 }
161
162 try (final CallableStatement call =
163 database.getConnection().prepareCall(
164 "begin ?:= " + database.getSchemaName() + ".classfacade.getAllUnidirAssociations; end;")) {
165 call.registerOutParameter(1, OracleTypes.CURSOR);
166 call.execute();
167
168 try (final ResultSet result = ((OracleCallableStatement) call).getCursor(1)) {
169 while (result.next()) {
170 this.associationNameIdRelation.setProperty(result.getString(2), Long.toString(result.getLong(1)));
171 }
172 }
173 } catch (final SQLException e) {
174 throw new OtherSQLException(e);
175 }
176
177 try (final CallableStatement call =
178 database.getConnection().prepareCall(
179 "begin ?:= " + database.getSchemaName() + ".classfacade.getAllMapAssociations; end;")) {
180 call.registerOutParameter(1, OracleTypes.CURSOR);
181 call.execute();
182
183 try (final ResultSet result = ((OracleCallableStatement) call).getCursor(1)) {
184 while (result.next()) {
185 this.associationNameIdRelation.setProperty(result.getString(2), Long.toString(result.getLong(1)));
186 }
187 }
188 } catch (final SQLException e) {
189 throw new OtherSQLException(e);
190 }
191
192 this.typeNameIdRelation.setProperty(StringType.STRING_NAME, Long.toString(StringType.String_ID));
193 this.typeNameIdRelation.setProperty(IntegerType.INTEGER_NAME, Long.toString(IntegerType.Integer_ID));
194 this.recalibrateMaxTypeID();
195 this.recalibrateMaxAssociationID();
196 }
197
198
199
200
201
202
203 public static synchronized IDManager instance() {
204 if (instance == null) {
205 instance = new IDManager();
206 }
207 return instance;
208 }
209
210
211
212
213
214 public void clearInformation() {
215 this.typeNameIdRelation.clear();
216 this.associationNameIdRelation.clear();
217 this.currentlyUsedAssociationMaxId = getMaxAssociationContractID();
218 this.currentlyUsedTypeMaxId = getMaxBaseTypeID();
219
220 }
221
222
223
224
225
226 public static long getMaxBaseTypeID() {
227 return MAX_BASE_TYPES;
228 }
229
230
231
232
233
234 public static long getMaxAssociationContractID() {
235 return MAX_CONTRACT_ASSOCIATION_ID;
236 }
237
238
239
240
241
242
243
244
245
246
247 public void persistIDRelationsToFile(final String typeIdsFilename, final String associationIdsFilename)
248 throws IOException {
249 try (FileOutputStream file = new FileOutputStream(typeIdsFilename)) {
250 this.typeNameIdRelation.store(file, "");
251 file.flush();
252 }
253
254 try (FileOutputStream file = new FileOutputStream(associationIdsFilename)) {
255 this.associationNameIdRelation.store(file, "");
256 file.flush();
257 }
258 }
259
260
261
262
263
264
265
266
267 public synchronized long pullNextUnusedTypeID(final String typeName) {
268 if (typeName.equals(StringType.STRING_NAME) || typeName.equals(IntegerType.INTEGER_NAME)) {
269 throw new IDContractViolationException();
270 }
271
272 this.currentlyUsedTypeMaxId += 1;
273 this.typeNameIdRelation.setProperty(typeName, Long.toString(this.currentlyUsedTypeMaxId));
274 return this.currentlyUsedTypeMaxId;
275 }
276
277
278
279
280
281
282
283
284 public synchronized long pullNextUnusedAssociationID(final String associationName) {
285 this.currentlyUsedAssociationMaxId += 1;
286 this.associationNameIdRelation.setProperty(associationName, Long.toString(this.currentlyUsedAssociationMaxId));
287 return this.currentlyUsedAssociationMaxId;
288 }
289
290
291
292
293
294
295
296
297
298
299 public long findIdForType(final String typeName) throws IDNotFoundForNameException {
300 if (!this.typeNameIdRelation.containsKey(typeName)) {
301 throw new IDNotFoundForNameException();
302 }
303 return Long.parseLong(this.typeNameIdRelation.getProperty(typeName));
304 }
305
306
307
308
309
310
311
312
313
314
315 public long findIdForAssociation(final String associationName) throws IDNotFoundForNameException {
316 if (!this.associationNameIdRelation.containsKey(associationName)) {
317 throw new IDNotFoundForNameException();
318 }
319 return Long.parseLong(this.associationNameIdRelation.getProperty(associationName));
320 }
321 }