View Javadoc
1   package de.fhdw.wtf.persistence.facade;
2   
3   import java.sql.SQLException;
4   import java.util.Collection;
5   import java.util.Iterator;
6   import java.util.List;
7   
8   import de.fhdw.wtf.persistence.exception.ClassFacadeUninitializedException;
9   import de.fhdw.wtf.persistence.exception.DuplicateUserTypeException;
10  import de.fhdw.wtf.persistence.exception.NotDeletableException;
11  import de.fhdw.wtf.persistence.exception.NotValidOperationException;
12  import de.fhdw.wtf.persistence.exception.PersistenceException;
13  import de.fhdw.wtf.persistence.exception.SpecializationCycleDetected;
14  import de.fhdw.wtf.persistence.exception.TypeOrAssociationNotFoundException;
15  import de.fhdw.wtf.persistence.meta.Association;
16  import de.fhdw.wtf.persistence.meta.IntegerType;
17  import de.fhdw.wtf.persistence.meta.MapAssociation;
18  import de.fhdw.wtf.persistence.meta.Specialization;
19  import de.fhdw.wtf.persistence.meta.StringType;
20  import de.fhdw.wtf.persistence.meta.Type;
21  import de.fhdw.wtf.persistence.meta.TypeVisitorException;
22  import de.fhdw.wtf.persistence.meta.UnidirectionalAssociation;
23  import de.fhdw.wtf.persistence.meta.UserType;
24  
25  /**
26   * A class to represent an implementation of the ClassFacade Interface for the usage without a database.
27   */
28  public class NoDatabaseClassFacadeImplementation implements ClassFacade {
29  	
30  	/**
31  	 * Represents the id which will be given to the first thing with an identifier which has been created by this
32  	 * ClassFacade. Will be set during the ClassFacades instantiation or during an execution of the clear-operation.
33  	 */
34  	private static final long INITIAL_NEXT_ID = 3;
35  	
36  	/**
37  	 * Message for the NotValidOperationException in regard to the attempt of renaming a base-type.
38  	 */
39  	private static final String RENAMING_BASE_TYPE_MESSAGE = "Renaming a BaseType is not supported!";
40  	
41  	/**
42  	 * The Type Manager which stores the Model Item informations.
43  	 */
44  	private final TypeManagerImplementation typeManager;
45  	
46  	/**
47  	 * This field contains the next identifier for something that can be created within this ClassFacade.
48  	 */
49  	private long nextId;
50  	
51  	/**
52  	 * Creates a new class-facade for usage with the no-database.
53  	 */
54  	public NoDatabaseClassFacadeImplementation() {
55  		this.typeManager = TypeManagerImplementation.getInstance();
56  		this.initializeBaseTypes();
57  		this.nextId = NoDatabaseClassFacadeImplementation.INITIAL_NEXT_ID;
58  	}
59  	
60  	@Override
61  	public UserType createUserType(final String name, final boolean abs, final boolean transaction)
62  			throws DuplicateUserTypeException {
63  		try {
64  			this.typeManager.getTypeforName(name);
65  			throw new DuplicateUserTypeException(name);
66  		} catch (final TypeOrAssociationNotFoundException e) {
67  			final UserType userType = new UserType(this.getAndIncrementNextId(), name, abs, transaction);
68  			this.typeManager.saveType(userType);
69  			this.typeManager.saveSpecialization(new Specialization(userType, userType));
70  			return userType;
71  		}
72  	}
73  	
74  	@Override
75  	public UnidirectionalAssociation createUnidirectionalAssociation(final String name,
76  			final boolean essential,
77  			final boolean unique,
78  			final UserType owner,
79  			final Type target) throws PersistenceException {
80  		final UnidirectionalAssociation association =
81  				new UnidirectionalAssociation(this.getAndIncrementNextId(), name, owner, target, essential, unique);
82  		this.typeManager.saveAssociation(association);
83  		return association;
84  	}
85  	
86  	@Override
87  	public MapAssociation createMapAssociation(final String name,
88  			final boolean essential,
89  			final UserType owner,
90  			final Type target,
91  			final Type keyType) throws PersistenceException {
92  		final MapAssociation association =
93  				new MapAssociation(this.getAndIncrementNextId(), name, owner, target, keyType, essential);
94  		this.typeManager.saveAssociation(association);
95  		return association;
96  	}
97  	
98  	@Override
99  	public void createSpecializationBetween(final UserType ancestor, final Type descendant) throws PersistenceException {
100 		final Collection<Specialization> allSpecializations = this.typeManager.getAllSpecializations();
101 		if (allSpecializations.contains(new Specialization(descendant, ancestor))) {
102 			throw new SpecializationCycleDetected(new SQLException());
103 		}
104 		final Iterator<Specialization> allSpecializationsIterator = allSpecializations.iterator();
105 		while (allSpecializationsIterator.hasNext()) {
106 			final Specialization current = allSpecializationsIterator.next();
107 			final boolean notReflexive = !current.getAncestor().isTheSameAs(current.getDescendant());
108 			if (notReflexive && ancestor.isTheSameAs(current.getDescendant())) {
109 				this.typeManager.saveSpecialization(new Specialization(current.getAncestor(), descendant));
110 			} else if (notReflexive && descendant.isTheSameAs(current.getAncestor())) {
111 				this.typeManager.saveSpecialization(new Specialization(ancestor, current.getDescendant()));
112 			}
113 		}
114 		this.typeManager.saveSpecialization(new Specialization(ancestor, descendant));
115 	}
116 	
117 	@Override
118 	public boolean isSuperClassTo(final Type ancestor, final Type descendant) throws PersistenceException {
119 		final Iterator<Specialization> allSpecializations = this.typeManager.getAllSpecializations().iterator();
120 		while (allSpecializations.hasNext()) {
121 			final Specialization current = allSpecializations.next();
122 			if (current.getAncestor().getId() == ancestor.getId()
123 					&& current.getDescendant().getId() == descendant.getId()) {
124 				return true;
125 			}
126 		}
127 		return false;
128 	}
129 	
130 	@Override
131 	public void finalizeSpecialization() throws PersistenceException {
132 		// No need to finalize the specialization because the transitive closure is ensured by the create method for
133 		// specializations while the reflexive closure is ensured by the create method for UserTypes.
134 	}
135 	
136 	@Override
137 	public void clear() throws PersistenceException {
138 		this.typeManager.clear();
139 		this.initializeBaseTypes();
140 		this.nextId = NoDatabaseClassFacadeImplementation.INITIAL_NEXT_ID;
141 	}
142 	
143 	@Override
144 	public void renameType(final Long typeId, final String newName) throws PersistenceException {
145 		final Type type = this.getTypeManager().getTypeForId(typeId);
146 		type.accept(new TypeVisitorException<PersistenceException>() {
147 			
148 			@Override
149 			public void handleUserType(final UserType argument) throws PersistenceException {
150 				NoDatabaseClassFacadeImplementation.this.deleteUserType(typeId);
151 				NoDatabaseClassFacadeImplementation.this.typeManager.saveType(new UserType(argument.getId(), newName,
152 						argument.isAbs(), argument.isTrans()));
153 			}
154 			
155 			@Override
156 			public void handleBaseType(final Type t) throws NotValidOperationException {
157 				throw new NotValidOperationException(NoDatabaseClassFacadeImplementation.RENAMING_BASE_TYPE_MESSAGE);
158 			}
159 		});
160 	}
161 	
162 	@Override
163 	public void renameAssociation(final Long assoId, final String newName) throws PersistenceException {
164 		try {
165 			final UnidirectionalAssociation association = this.typeManager.getUnidirectionalAssociationForId(assoId);
166 			this.deleteAssociation(assoId);
167 			this.typeManager.saveAssociation(new UnidirectionalAssociation(association.getId(), newName, association
168 					.getOwner(), association.getTarget(), association.isEssential(), association.isUnique()));
169 		} catch (final TypeOrAssociationNotFoundException exception) {
170 			final MapAssociation association = this.typeManager.getMapAssociationForId(assoId);
171 			this.deleteAssociation(assoId);
172 			this.typeManager.saveAssociation(new MapAssociation(association.getId(), newName, association.getOwner(),
173 					association.getTarget(), association.getKeyType(), association.isEssential()));
174 		}
175 	}
176 	
177 	@Override
178 	public void deleteAssociation(final Long associationId) throws PersistenceException {
179 		this.typeManager.deleteAssociation(associationId);
180 	}
181 	
182 	@Override
183 	public void deleteUserType(final Long typeId) throws PersistenceException {
184 		final Type type = this.getTypeManager().getTypeForId(typeId);
185 		type.accept(new TypeVisitorException<NotDeletableException>() {
186 			@Override
187 			public void handleUserType(final UserType argument) throws NotDeletableException {
188 				try {
189 					NoDatabaseClassFacadeImplementation.this.typeManager.deleteType(typeId);
190 					final Iterator<Specialization> allSpecializations =
191 							NoDatabaseClassFacadeImplementation.this.typeManager.getAllSpecializations().iterator();
192 					while (allSpecializations.hasNext()) {
193 						final Specialization current = allSpecializations.next();
194 						if (current.getAncestor().isTheSameAs(argument)
195 								|| current.getDescendant().isTheSameAs(argument)) {
196 							NoDatabaseClassFacadeImplementation.this.typeManager.deleteSpecialization(current);
197 						}
198 					}
199 				} catch (final TypeOrAssociationNotFoundException e) {
200 					// Should not happen because the type was already found.
201 					throw new Error();
202 				}
203 			}
204 			
205 			@Override
206 			public void handleBaseType(final Type t) throws NotDeletableException {
207 				throw new NotDeletableException();
208 			}
209 		});
210 	}
211 	
212 	@Override
213 	public void updateLinksToNewAssociation(final Long associationId, final Collection<Long> newAssociationIds)
214 			throws PersistenceException {
215 		
216 		// -------------------------------------------------------------
217 		// TODO Auto-generated method stub
218 		// It seems to be a refactoring method.
219 		// -------------------------------------------------------------
220 		
221 		// FOR i IN 1 .. newAssociations.COUNT
222 		// LOOP
223 		// UPDATE Link l SET l.instance_of=newAssociations (i)
224 		// WHERE l.instance_of=oldAssociation AND
225 		// ISSuperClassTo(
226 		// (SELECT a.owner FROM Association a
227 		// WHERE a.id=newAssociations (i)),
228 		// (SELECT o.instance_of FROM Object o
229 		// WHERE o.id=l.owner)
230 		// ) > 0;
231 		// END LOOP;
232 		
233 		// final ObjectFacade objectFacade = NoDatabaseManager.getInstance().getObjectFacade();
234 		// final Iterator<Long> newAssociationIdsIterator = newAssociationIds.iterator();
235 		// while (newAssociationIdsIterator.hasNext()) {
236 		// // TODO
237 		// }
238 	}
239 	
240 	@Override
241 	public void moveLinksAndCreateObjects(final List<Long> oldAssoIds,
242 			final Association newAsso,
243 			final UserType newType,
244 			final List<Long> newAssoIds) throws PersistenceException {
245 		// TODO Auto-generated method stub
246 		// It seems to be a refactoring method.
247 		// It is still not implemented in the oracle database.
248 	}
249 	
250 	/**
251 	 * Adds all BaseTypes and there respective reflexive specialization-pairs to the TypeManager of this ClassFacade.
252 	 */
253 	private void initializeBaseTypes() {
254 		this.typeManager.saveType(StringType.getInstance());
255 		this.typeManager.saveSpecialization(new Specialization(StringType.getInstance(), StringType.getInstance()));
256 		this.typeManager.saveType(IntegerType.getInstance());
257 		this.typeManager.saveSpecialization(new Specialization(IntegerType.getInstance(), IntegerType.getInstance()));
258 	}
259 	
260 	@Override
261 	public void initialize() throws PersistenceException {
262 		// Initialization measurements are not needed in this implementation because model informations are not being
263 		// saved longer than one runtime-session.
264 	}
265 	
266 	@Override
267 	public void initializeForRuntime() throws PersistenceException {
268 		// Initialization measurements are not needed in this implementation because model informations are not being
269 		// saved longer than one runtime-session.
270 	}
271 	
272 	@Override
273 	public boolean hasBeenInitialized() {
274 		// No further initialization is needed in this implementation and thus every instance of this ClassFacade is
275 		// already initialized after its constructor-call.
276 		return true;
277 	}
278 	
279 	@Override
280 	public TypeManager getTypeManager() throws ClassFacadeUninitializedException {
281 		return this.typeManager;
282 	}
283 	
284 	/**
285 	 * @return Returns the next free id.
286 	 */
287 	private long getAndIncrementNextId() {
288 		final long result = this.nextId;
289 		this.nextId++;
290 		return result;
291 	}
292 	
293 }