View Javadoc
1   package de.fhdw.wtf.persistence.facade;
2   
3   import java.io.BufferedWriter;
4   import java.io.File;
5   import java.io.FileWriter;
6   import java.io.IOException;
7   import java.io.PrintWriter;
8   import java.util.Collection;
9   import java.util.Iterator;
10  import java.util.List;
11  
12  import de.fhdw.wtf.persistence.exception.ClassFacadeUninitializedException;
13  import de.fhdw.wtf.persistence.exception.FileDeleteIOException;
14  import de.fhdw.wtf.persistence.exception.PersistenceException;
15  import de.fhdw.wtf.persistence.exception.RuntimePersistenceException;
16  import de.fhdw.wtf.persistence.meta.Association;
17  import de.fhdw.wtf.persistence.meta.MapAssociation;
18  import de.fhdw.wtf.persistence.meta.Type;
19  import de.fhdw.wtf.persistence.meta.UnidirectionalAssociation;
20  import de.fhdw.wtf.persistence.meta.UserType;
21  
22  /**
23   * This class implements a classfacade which works not directly on the database for altering operations on an existing
24   * model. All operations for model altering will be written to a pl-sql script which can be executed asynchronously on
25   * the real database later with a sql plus client. Operations which are unprovided for the model altering, i.e.
26   * initialization or clear routines, will be delegated and executed on the next instance of the classfacade-chain. You
27   * can prefix an existing classfacade implementation with this one, if you wish to use the asynchronous altering
28   * ability.
29   * 
30   */
31  public class AsynchronousAlteringOnExistingModellClassFacadeImplementation implements ClassFacade {
32  	private ClassFacade instanceToDelegateNonAlteringCalls = null;
33  	/**
34  	 * The name of the Script file.
35  	 */
36  	public static final String SCRIPT_FILE_NAME = "modelChangesScript.sql";
37  	
38  	/**
39  	 * Creates a new script file if it not already exists.
40  	 */
41  	private void createScriptFileIfNotExists() throws IOException {
42  		final File fileScript = new File(SCRIPT_FILE_NAME);
43  		if (!fileScript.exists()) {
44  			fileScript.createNewFile();
45  		}
46  	}
47  	
48  	/**
49  	 * Deletes the current change script if it already exists.
50  	 * 
51  	 * @throws IOException
52  	 *             will be thrown, when the file cannot be deleted.
53  	 * */
54  	public static void deleteScriptFileIfExists() throws IOException {
55  		final File fileScript = new File(SCRIPT_FILE_NAME);
56  		if (fileScript.exists() && !fileScript.isDirectory()) {
57  			if (!fileScript.delete()) {
58  				throw new FileDeleteIOException(fileScript);
59  			}
60  		}
61  	}
62  	
63  	public AsynchronousAlteringOnExistingModellClassFacadeImplementation(final ClassFacade instanceToDelegateNonAlteringCalls) {
64  		this.instanceToDelegateNonAlteringCalls = instanceToDelegateNonAlteringCalls;
65  	}
66  	
67  	@Override
68  	public UserType createUserType(final String name, final boolean abs, final boolean transaction)
69  			throws PersistenceException {
70  		
71  		final String theNewId = Long.toString(IDManager.instance().pullNextUnusedTypeID(name));
72  		final String absInt = abs ? "1" : "0";
73  		final String transInt = transaction ? "1" : "0";
74  		final String createUserTypeCommand =
75  				"execute " + OracleDatabaseManager.getInstance().getSchemaName() + ".classfacade.createUserType("
76  						+ theNewId + "," + "'" + name + "'" + "," + absInt + "," + transInt + ");";
77  		
78  		try {
79  			this.createScriptFileIfNotExists();
80  		} catch (final IOException e) {
81  			throw new RuntimePersistenceException(e);
82  		}
83  		
84  		try (final PrintWriter scriptWriter =
85  				new PrintWriter(new BufferedWriter(new FileWriter(SCRIPT_FILE_NAME, true)))) {
86  			scriptWriter.println(createUserTypeCommand);
87  			scriptWriter.flush();
88  		} catch (final IOException e) {
89  			// TODO Auto-generated catch block
90  			e.printStackTrace();
91  		}
92  		
93  		return new UserType(Long.parseLong(theNewId), name, abs, transaction);
94  	}
95  	
96  	@Override
97  	public UnidirectionalAssociation createUnidirectionalAssociation(final String name,
98  			final boolean essential,
99  			final boolean unique,
100 			final UserType owner,
101 			final Type target) throws PersistenceException {
102 		final String essentialInt = essential ? "1" : "0";
103 		final String uniqueInt = unique ? "1" : "0";
104 		final String theNewId = Long.toString(IDManager.instance().pullNextUnusedAssociationID(name));
105 		final String createAssociationCommand =
106 				"execute " + OracleDatabaseManager.getInstance().getSchemaName() + ".classfacade.createAssociation("
107 						+ theNewId + "," + "'" + name + "'" + "," + Long.toString(owner.getId()) + ","
108 						+ Long.toString(target.getId()) + "," + essentialInt + "," + uniqueInt + ");";
109 		
110 		try {
111 			this.createScriptFileIfNotExists();
112 		} catch (final IOException e) {
113 			throw new RuntimePersistenceException(e);
114 		}
115 		
116 		try (final PrintWriter scriptWriter =
117 				new PrintWriter(new BufferedWriter(new FileWriter(SCRIPT_FILE_NAME, true)))) {
118 			scriptWriter.println(createAssociationCommand);
119 			scriptWriter.flush();
120 		} catch (final IOException e) {
121 			// TODO Auto-generated catch block
122 			e.printStackTrace();
123 		}
124 		
125 		return new UnidirectionalAssociation(Long.parseLong(theNewId), name, owner, target, essential, unique);
126 	}
127 	
128 	@Override
129 	public MapAssociation createMapAssociation(final String name,
130 			final boolean essential,
131 			final UserType owner,
132 			final Type target,
133 			final Type keyType) throws PersistenceException {
134 		final String essentialInt = essential ? "1" : "0";
135 		final String uniqueInt = "1";
136 		final String theNewId = Long.toString(IDManager.instance().pullNextUnusedAssociationID(name));
137 		final String createAssociationThreeDigitCommand =
138 				"execute " + OracleDatabaseManager.getInstance().getSchemaName() + ".classfacade.createAssociation3("
139 						+ theNewId + "," + "'" + name + "'" + "," + Long.toString(owner.getId()) + ","
140 						+ Long.toString(target.getId()) + "," + essentialInt + "," + uniqueInt + ","
141 						+ Long.toString(keyType.getId()) + ");";
142 		
143 		try {
144 			this.createScriptFileIfNotExists();
145 		} catch (final IOException e) {
146 			throw new RuntimePersistenceException(e);
147 		}
148 		
149 		try (final PrintWriter scriptWriter =
150 				new PrintWriter(new BufferedWriter(new FileWriter(SCRIPT_FILE_NAME, true)))) {
151 			scriptWriter.println(createAssociationThreeDigitCommand);
152 			scriptWriter.flush();
153 		} catch (final IOException e) {
154 			// TODO Auto-generated catch block
155 			e.printStackTrace();
156 		}
157 		
158 		return new MapAssociation(Long.parseLong(theNewId), name, owner, target, keyType, essential);
159 	}
160 	
161 	@Override
162 	public void createSpecializationBetween(final UserType ancestor, final Type descendant) throws PersistenceException {
163 		
164 		final String createSpecializationCommand =
165 				"execute " + OracleDatabaseManager.getInstance().getSchemaName() + ".classfacade.createSpecialization("
166 						+ Long.toString(ancestor.getId()) + "," + Long.toString(descendant.getId()) + ");";
167 		
168 		try {
169 			this.createScriptFileIfNotExists();
170 		} catch (final IOException e) {
171 			throw new RuntimePersistenceException(e);
172 		}
173 		
174 		try (final PrintWriter scriptWriter =
175 				new PrintWriter(new BufferedWriter(new FileWriter(SCRIPT_FILE_NAME, true)))) {
176 			scriptWriter.println(createSpecializationCommand);
177 			scriptWriter.flush();
178 		} catch (final IOException e) {
179 			// TODO Auto-generated catch block
180 			e.printStackTrace();
181 		}
182 	}
183 	
184 	@Override
185 	public boolean isSuperClassTo(final Type ancestor, final Type descendant) throws PersistenceException {
186 		
187 		return this.instanceToDelegateNonAlteringCalls.isSuperClassTo(ancestor, descendant);
188 	}
189 	
190 	@Override
191 	public void finalizeSpecialization() throws PersistenceException {
192 		
193 		final String finalizeSpecializationCommand =
194 				"execute " + OracleDatabaseManager.getInstance().getSchemaName()
195 						+ ".classfacade.finalizeSpecialization;";
196 		
197 		try {
198 			this.createScriptFileIfNotExists();
199 		} catch (final IOException e) {
200 			throw new RuntimePersistenceException(e);
201 		}
202 		
203 		try (final PrintWriter scriptWriter =
204 				new PrintWriter(new BufferedWriter(new FileWriter(SCRIPT_FILE_NAME, true)))) {
205 			scriptWriter.println(finalizeSpecializationCommand);
206 			scriptWriter.flush();
207 		} catch (final IOException e) {
208 			// TODO Auto-generated catch block
209 			e.printStackTrace();
210 		}
211 	}
212 	
213 	@Override
214 	public void clear() throws PersistenceException {
215 		this.instanceToDelegateNonAlteringCalls.clear();
216 		
217 	}
218 	
219 	@Override
220 	public void initialize() throws PersistenceException {
221 		this.instanceToDelegateNonAlteringCalls.clear();
222 		
223 	}
224 	
225 	@Override
226 	public void initializeForRuntime() throws PersistenceException {
227 		this.instanceToDelegateNonAlteringCalls.initializeForRuntime();
228 	}
229 	
230 	@Override
231 	public boolean hasBeenInitialized() {
232 		return this.instanceToDelegateNonAlteringCalls.hasBeenInitialized();
233 	}
234 	
235 	@Override
236 	public TypeManager getTypeManager() throws ClassFacadeUninitializedException {
237 		return this.instanceToDelegateNonAlteringCalls.getTypeManager();
238 	}
239 	
240 	@Override
241 	public void renameType(final Long typeId, final String newName) throws PersistenceException {
242 		String command =
243 				"execute " + OracleDatabaseManager.getInstance().getSchemaName() + ".classfacade.renameType(%s,%s);";
244 		command = String.format(command, typeId.toString(), newName);
245 		this.writeCommandToFile(command);
246 	}
247 	
248 	@Override
249 	public void renameAssociation(final Long assoId, final String newName) throws PersistenceException {
250 		String command =
251 				"execute " + OracleDatabaseManager.getInstance().getSchemaName()
252 						+ ".classfacade.renameAssociation(%s,%s);";
253 		command = String.format(command, assoId.toString(), newName);
254 		this.writeCommandToFile(command);
255 	}
256 	
257 	@Override
258 	public void deleteAssociation(final Long associationId) throws PersistenceException {
259 		String command =
260 				"execute " + OracleDatabaseManager.getInstance().getSchemaName()
261 						+ ".classfacade.deleteAssociation(%s);";
262 		command = String.format(command, associationId.toString());
263 		this.writeCommandToFile(command);
264 	}
265 	
266 	@Override
267 	public void deleteUserType(final Long typeId) throws PersistenceException {
268 		String command =
269 				"execute " + OracleDatabaseManager.getInstance().getSchemaName()
270 						+ ".classfacade.deleteUserTypeAndSpec(%s);";
271 		command = String.format(command, typeId.toString());
272 		this.writeCommandToFile(command);
273 	}
274 	
275 	@Override
276 	public void updateLinksToNewAssociation(final Long associationId, final Collection<Long> newAssociationIds)
277 			throws PersistenceException {
278 		String command =
279 				"execute " + OracleDatabaseManager.getInstance().getSchemaName()
280 						+ ".classfacade.pushDownLinks(%s,ARRAY_INT(%s));";
281 		command = String.format(command, associationId.toString(), this.createCSVFormat(newAssociationIds));
282 		this.writeCommandToFile(command);
283 	}
284 	
285 	@Override
286 	public void moveLinksAndCreateObjects(final List<Long> oldAssoIds,
287 			final Association newAsso,
288 			final UserType newType,
289 			final List<Long> newAssoIds) throws PersistenceException {
290 		String command =
291 				"execute " + OracleDatabaseManager.getInstance().getSchemaName()
292 						+ ".classfacade.moveLinksAndCreateObjects(ARRAY_INT(%s),%s,%s,ARRAY_INT(%s));";
293 		command =
294 				String.format(command, this.createCSVFormat(oldAssoIds), Long.valueOf(newAsso.getId()).toString(), Long
295 						.valueOf(newType.getId()).toString(), this.createCSVFormat(newAssoIds));
296 		this.writeCommandToFile(command);
297 	}
298 	
299 	private String createCSVFormat(final Collection<Long> newAssociationIds) {
300 		final StringBuffer resultBuffer = new StringBuffer();
301 		final Iterator<Long> i = newAssociationIds.iterator();
302 		if (i.hasNext()) {
303 			resultBuffer.append(i.next().toString());
304 		}
305 		while (i.hasNext()) {
306 			final Long current = i.next();
307 			resultBuffer.append(",");
308 			resultBuffer.append(current.toString());
309 		}
310 		return resultBuffer.toString();
311 	}
312 	
313 	private void writeCommandToFile(final String command) {
314 		try {
315 			this.createScriptFileIfNotExists();
316 		} catch (final IOException e) {
317 			throw new RuntimePersistenceException(e);
318 		}
319 		
320 		try (final PrintWriter scriptWriter =
321 				new PrintWriter(new BufferedWriter(new FileWriter(SCRIPT_FILE_NAME, true)))) {
322 			scriptWriter.println(command);
323 			scriptWriter.flush();
324 		} catch (final IOException e) {
325 			// TODO Auto-generated catch block
326 			e.printStackTrace();
327 		}
328 	}
329 	
330 }