View Javadoc

1   /*
2    *  Copyright (C) 2003-2005 SINTEF
3    *  Author:  fredrik dot vraalsen at sintef dot no
4    *  Webpage: http://coras.sourceforge.net/
5    *
6    *  This program is free software; you can redistribute it and/or
7    *  modify it under the terms of the GNU Lesser General Public License
8    *  as published by the Free Software Foundation; either version 2.1
9    *  of the License, or (at your option) any later version.
10   *
11   *  This program is distributed in the hope that it will be useful,
12   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   *  Lesser General Public License for more details.
15   *
16   *  You should have received a copy of the GNU Lesser General Public
17   *  License along with this program; if not, write to the Free
18   *  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19   *  02111-1307 USA
20   */
21  package no.sintef.assetrepository;
22  
23  import java.rmi.RemoteException;
24  import java.util.ArrayList;
25  import java.util.Collection;
26  import java.util.Collections;
27  import java.util.HashMap;
28  import java.util.Hashtable;
29  import java.util.Iterator;
30  import java.util.Map;
31  import java.util.Observable;
32  
33  import no.sintef.assetrepository.interfaces.AssetRepresentationPK;
34  import no.sintef.assetrepository.interfaces.AssetRepresentationValue;
35  import no.sintef.assetrepository.interfaces.AssetServices;
36  import no.sintef.assetrepository.interfaces.AssetServicesUtil;
37  import no.sintef.assetrepository.interfaces.AssetVersionPK;
38  import no.sintef.assetrepository.interfaces.AssetVersionValue;
39  import no.sintef.assetrepository.interfaces.VersionedAssetPK;
40  import no.sintef.assetrepository.interfaces.VersionedAssetValue;
41  import no.sintef.lock.LockException;
42  import no.sintef.lock.LockRequiredException;
43  
44  /***
45   * @author fvr
46   *
47   * TODO To change the template for this generated type comment go to
48   * Window - Preferences - Java - Code Style - Code Templates
49   */
50  public class Asset extends Observable {
51  
52      private static final Object synchronizer = new Object();
53      
54      private static AssetServices _services = null;
55      private static String jndiUrl = "jnp://localhost:10099";
56      
57      private VersionedAssetValue asset = null;
58      private AssetVersionValue assetVersion = null;
59      private boolean dirty = false;
60      private boolean checkedOut = false;
61  
62      private ArrayList representations = null;
63      
64      public static Asset createRootAsset(String type, String name, String description, Map properties, String annotation, Representation[] representations) throws LockException {
65          return createAsset(null, type, name, description, properties, annotation, representations);
66      }
67      
68      public static Asset getAssetById(String id) {
69          Asset result = null;
70          try {
71              VersionedAssetValue assetValue = getAssetServices().getVersionedAsset(new VersionedAssetPK(id));
72              result = new Asset(assetValue);
73          } catch (RemoteException e) {
74              // TODO Auto-generated catch block
75              e.printStackTrace();
76          }
77          return result;
78      }
79      
80      public static Collection getAssetsByType(String type) {
81          Collection result = new ArrayList();
82          try {
83              Collection assets = getAssetServices().getAssetsByType(type);
84              for (Iterator i = assets.iterator(); i.hasNext();) {
85                  Asset asset = new Asset((VersionedAssetValue) i.next());
86                  result.add(asset);
87              }
88          } catch (RemoteException e) {
89              // TODO Auto-generated catch block
90              e.printStackTrace();
91          } catch (RepositoryException e) {
92              // TODO Auto-generated catch block
93              e.printStackTrace();
94          }
95          return result;
96      }
97      
98      private Asset(VersionedAssetValue asset) {
99          super();
100         if (asset == null) {
101             throw new IllegalArgumentException("asset is null");
102         }
103         this.asset = asset;
104         loadVersion(asset.getBaseVersion());
105         makeClean();
106     }
107 
108     public boolean isDeleted() {
109     	return asset.getDeletionDate() != null;
110     }
111     
112 	/***
113 	 * @return
114 	 * @throws RepositoryException
115 	 * @throws LockException
116 	 * @throws RemoteException
117 	 */
118 	public void markAsDeleted() throws LockException {
119 		try {
120 			getAssetServices().markAssetAsDeleted(asset.getPrimaryKey());
121 			checkedOut = false; // done by services.markAssetAsDeleted
122 			reloadAsset(false);
123 		} catch (RemoteException e) {
124 			// TODO Auto-generated catch block
125 			e.printStackTrace();
126 		} catch (RepositoryException e) {
127 			// TODO Auto-generated catch block
128 			e.printStackTrace();
129 		}
130 	}
131 
132     public synchronized void reloadAsset(boolean forceLoadBaseVersion) {
133         if (checkedOut) {
134             throw new IllegalStateException("asset cannot be reloaded while it is checked out");
135         }
136         try {
137             VersionedAssetValue newAsset = getAssetServices().getVersionedAsset(asset.getPrimaryKey());
138             AssetVersionPK oldBaseVersionPk = asset.getBaseVersion();
139             AssetVersionPK oldAssetVersionPk = assetVersion.getPrimaryKey();
140             AssetVersionPK newBaseVersionPk = newAsset.getBaseVersion();
141             
142             // update the local AssetValue with checked out status so that the
143             // equality test below won't automatically fail
144             asset.setCheckedOutBy(newAsset.getCheckedOutBy());
145             asset.setCheckedOutDate(newAsset.getCheckedOutDate());
146             
147             boolean changed = !equals(asset, newAsset);
148 
149             asset = newAsset;
150             
151             if (forceLoadBaseVersion ||
152                     (equals(oldBaseVersionPk, oldAssetVersionPk)
153                             && !equals(oldBaseVersionPk, newBaseVersionPk))) {
154                 // FIXME may trigger assetChanged() twice!?
155                 loadVersion(newBaseVersionPk); // Calls assetChanged
156             } 
157             // FIXME change to else if, loadVersion will always trigger
158             // assetChanged if asset != newAsset !?!?
159             if (changed) {
160                 assetChanged(); // FIXME may trigger assetChanged twice!?
161             }
162             makeClean();
163         } catch (RemoteException e) {
164             // TODO Auto-generated catch block
165             e.printStackTrace();
166         }
167     }
168 
169     public synchronized void checkOut() throws LockException {
170         try {
171             getAssetServices().checkOut(assetVersion.getAsset());
172             reloadAsset(true);
173             checkedOut = true;
174         } catch (RemoteException e) {
175             // TODO Auto-generated catch block
176             e.printStackTrace();
177         } catch (RepositoryException e) {
178             // TODO Auto-generated catch block
179             e.printStackTrace();
180         }
181     }
182 
183     public synchronized void unCheckOut() throws LockException {
184         try {
185             getAssetServices().unCheckOut(assetVersion.getAsset());
186             checkedOut = false;
187             reloadAsset(true);
188         } catch (RemoteException e) {
189             // TODO Auto-generated catch block
190             e.printStackTrace();
191         } catch (RepositoryException e) {
192             // TODO Auto-generated catch block
193             e.printStackTrace();
194         }
195     }
196 
197     public synchronized void checkIn(String annotation) throws LockException {
198         try {
199             AssetServices services = getAssetServices();
200 
201             ArrayList representationPks = new ArrayList();
202             Representation[] representations = getRepresentations();
203             for (int i = 0; i < representations.length; i++) {
204                 AssetRepresentationValue value = representations[i].getRepresentation();
205                 try {
206                     if (value.getId() == null) {
207                         AssetRepresentationPK pk = services.createAssetRepresentation(value);
208                         value.setPrimaryKey(pk);
209                     }
210                     representationPks.add(value.getPrimaryKey());
211                 } catch (Exception e) {
212                     // TODO Auto-generated catch block
213                     e.printStackTrace();
214                 }
215             }
216             assetVersion.setRepresentations(representationPks);
217 
218             assetVersion.setAnnotation(annotation);
219             services.checkIn(assetVersion.getAsset(), assetVersion);
220             checkedOut = false;
221             reloadAsset(true);
222         } catch (RemoteException e) {
223             // TODO Auto-generated catch block
224             e.printStackTrace();
225         } catch (RepositoryException e) {
226             // TODO Auto-generated catch block
227             e.printStackTrace();
228         }
229     }
230 
231     public boolean isDirty() {
232         return dirty;
233     }
234     
235     public String getId() {
236         VersionedAssetPK pk = asset.getPrimaryKey();
237         return pk.getId();
238     }
239     
240     public String getName() {
241         return assetVersion.getName();
242     }
243     public synchronized void setName(String newName) throws LockRequiredException {
244         if (!equals(getName(), newName)) {
245             assertCheckedOut();
246             assetVersion.setName(newName);
247             assetChanged();
248         }
249     }
250 
251     public String getDescription() {
252         return assetVersion.getDescription();
253     }
254     public synchronized void setDescription(String newDescription) throws LockRequiredException {
255         if (!equals(getDescription(), newDescription)) {
256             assertCheckedOut();
257             assetVersion.setDescription(newDescription);
258             assetChanged();
259         }
260     }
261 
262     public String getOwner() {
263         return assetVersion.getOwner();
264     }
265     public synchronized void setOwner(String newOwner) throws LockRequiredException {
266         if (!equals(getOwner(), newOwner)) {
267             assertCheckedOut();
268             assetVersion.setOwner(newOwner);
269             assetChanged();
270         }
271     }
272 
273     public synchronized Asset createChildAsset(String type, String name, String description, Map properties, String annotation, Representation[] representations) throws LockException {
274         return createAsset(this, type, name, description, properties, annotation, representations);
275     }
276 
277     public String getProperty(String key) {
278         return (String) assetVersion.getProperties().get(key);
279     }
280     public synchronized void setProperty(String key, String value) throws LockRequiredException {
281         if (!equals(getProperty(key), value)) {
282             assertCheckedOut();
283             assetVersion.getProperties().put(key, value);
284             assetChanged();
285         }
286     }
287     
288     public Collection getChildIds() {
289         Collection result = new ArrayList();
290         Collection childPks = assetVersion.getChilds();
291         for (Iterator i = childPks.iterator(); i.hasNext();) {
292             VersionedAssetPK childPk = (VersionedAssetPK) i.next();
293             result.add(childPk.getId());
294         }
295         return Collections.unmodifiableCollection(result);
296     }
297     /*
298     protected synchronized void addChild(VersionedAssetPK childPk) throws LockRequiredException {
299         assertCheckedOut();
300         if (assetVersion.getChilds().add(childPk)) {
301             assetChanged();
302         }
303     }
304     protected synchronized void removeChild(VersionedAssetPK childPk) throws LockRequiredException {
305         assertCheckedOut();
306         if (assetVersion.getChilds().remove(childPk)) {
307             assetChanged();
308         }
309     }
310     */
311 
312     public Representation[] getRepresentations() {
313         if (representations == null) {
314         	// FIXME not thread safe?
315             loadRepresentations();
316         }
317         return (Representation[]) representations.toArray(new Representation[0]);
318         /*
319         AssetRepresentationValue[] representations = assetVersion.getRepresentations();
320         if (representations == null) {
321             return new Representation[0];
322         }
323         Representation[] result = new Representation[representations.length];
324         for (int i = 0; i < representations.length; i++) {
325             result[i] = new Representation(representations[i]);
326         }
327         return result;
328         */
329     }
330     
331     private synchronized void loadRepresentations() {
332         if (representations != null) {
333             return;
334         }
335         Collection representationPks = assetVersion.getRepresentations();
336         representations = new ArrayList();
337         for (Iterator i = representationPks.iterator(); i.hasNext();) {
338             AssetRepresentationPK representationPk = (AssetRepresentationPK) i.next();
339             try {
340                 AssetRepresentationValue value = getAssetServices().getAssetRepresentation(representationPk);
341                 representations.add(new Representation(value));
342             } catch (Exception e) {
343                 e.printStackTrace();
344             }
345         }
346     }
347 
348     public synchronized void addRepresentation(Representation representation) throws LockRequiredException {
349         assertCheckedOut();
350         if (representations == null) {
351             loadRepresentations();
352         }
353         representations.add(representation);
354         // AssetRepresentationValue representationValue = representation.getRepresentation();
355         // assetVersion.addRepresentation(representationValue);
356         assetChanged();
357     }
358     public synchronized void removeRepresentation(Representation representation) throws LockRequiredException {
359         assertCheckedOut();
360         if (representations == null) {
361             loadRepresentations();
362         }
363         representations.remove(representation);
364         // AssetRepresentationValue representationValue = representation.getRepresentation();
365         // assetVersion.removeRepresentation(representationValue);
366         assetChanged();
367     }
368     /*
369     public void updateRepresentation(Representation representation) throws LockRequiredException {
370         assertCheckedOut();
371         AssetRepresentationValue representationValue = representation.getRepresentation();
372         assetVersion.updateRepresentation(representationValue);
373         assetChanged();
374     }
375     */
376     private synchronized void loadVersion(AssetVersionPK versionPk) {
377         if (versionPk == null) {
378             throw new IllegalArgumentException("asset version primary key is null");
379         }
380         if (checkedOut) {
381             throw new IllegalStateException("asset version cannot be loaded while asset is checked out");
382         }
383         if (assetVersion != null && versionPk.equals(assetVersion.getPrimaryKey())) {
384             return; // Nothing to do
385         }
386         try {
387             AssetServices services = getAssetServices();
388             /*
389             VersionHistoryValue versionHistory = services.getVersionHistory(asset.getVersionHistory());
390             if (!versionHistory.getVersions().contains(versionPk)) {
391             */
392             if (!asset.getVersionHistory().getVersions().contains(versionPk)) {
393                 throw new IllegalArgumentException("asset version is not part of version history");
394             }
395             AssetVersionValue newAssetVersion = services.getAssetVersion(versionPk);
396             setAssetVersion(newAssetVersion);
397             makeClean();
398         } catch (RemoteException e) {
399             // TODO Auto-generated catch block
400             e.printStackTrace();
401         }
402     }
403 
404     /***
405      * @param newAssetVersion
406      * @throws LockRequiredException
407      */
408     private void setAssetVersion(AssetVersionValue newAssetVersion) {
409         if (!equals(assetVersion, newAssetVersion)) {
410             assetVersion = newAssetVersion;
411             representations = null;
412             assetChanged();
413         }
414     }
415     
416     /***
417      * 
418      */
419     private void assetChanged() {
420         makeDirty();
421         setChanged();
422         notifyObservers();
423     }
424     
425     private void assertCheckedOut() throws LockRequiredException {
426         if (checkedOut == false) {
427             throw new LockRequiredException("Asset must be checked out from repository before modification");
428         }
429     }
430     
431     /***
432      * 
433      */
434     private synchronized void makeDirty() {
435         dirty = true;
436     }
437 
438     private synchronized void makeClean() {
439         dirty = false;
440     }
441 
442     private static Asset createAsset(Asset parent, String type, String name, String description, Map properties, String annotation, Representation[] representations) throws LockException {
443         try {
444             AssetVersionValue assetVersion = new AssetVersionValue();
445             assetVersion.setName(name);
446             assetVersion.setDescription(description);
447             assetVersion.setAnnotation(annotation);
448             assetVersion.setProperties(properties != null ? properties : new HashMap());
449 
450             assetVersion.setChilds(new ArrayList());
451             assetVersion.setNextVersions(new ArrayList());
452             assetVersion.setPreviousVersions(new ArrayList());
453 
454             /*
455             assetVersion.clearRepresentations();
456             assetVersion.cleanRepresentation();
457             */
458             ArrayList representationPks = new ArrayList();
459             if (representations != null) {
460                 for (int i = 0; i < representations.length; i++) {
461                     // assetVersion.addRepresentation(representations[i].getRepresentation());
462                     AssetRepresentationValue value = representations[i].getRepresentation();
463                     try {
464                         if (value.getId() == null) {
465                             AssetRepresentationPK pk = getAssetServices().createAssetRepresentation(value);
466                             value.setPrimaryKey(pk);
467                         }
468                         representationPks.add(value.getPrimaryKey());
469                     } catch (Exception e) {
470                         // TODO Auto-generated catch block
471                         e.printStackTrace();
472                     }
473                 }
474             }
475             assetVersion.setRepresentations(representationPks);
476             
477             VersionedAssetPK parentPk = null;
478             if (parent != null) {
479                 if (!equals(parent.asset.getBaseVersion(), parent.assetVersion.getPrimaryKey())) {
480                     throw new IllegalStateException("child can only be created in base version");
481                 }
482                 parentPk = parent.asset.getPrimaryKey();	
483             }
484             AssetServices services = getAssetServices();
485             VersionedAssetPK childPk = services.createVersionedAsset(type, parentPk, assetVersion);
486             Asset child = new Asset(services.getVersionedAsset(childPk));
487             if (parent != null) {
488                 parent.checkedOut = false; // Done by services.createAsset
489                 parent.reloadAsset(true);
490             }
491             return child;
492         } catch (RemoteException e) {
493             // TODO Auto-generated catch block
494             e.printStackTrace();
495         } catch (RepositoryException e) {
496             // TODO Auto-generated catch block
497             e.printStackTrace();
498         }
499         return null;
500     }
501 
502     public static final void setJndiUrl(String hostname, int port) {
503     	jndiUrl = "jnp://" + hostname + ":" + port;
504     	_services = null;
505     }
506     
507     private static final AssetServices getAssetServices() {
508         if (_services != null) {
509             return _services;
510         }
511         synchronized (synchronizer) {
512             if (_services == null) {
513                 try {
514                 	Hashtable environment = new Hashtable();
515                 	environment.put("java.naming.provider.url", jndiUrl);
516                     _services = AssetServicesUtil.getHome(environment).create();
517                 } catch (Exception e) {
518                     // TODO Auto-generated catch block
519                     e.printStackTrace();
520                 }
521             }
522             return _services;
523         }
524     }
525 
526     /***
527      * @param a
528      * @param b
529      * @return
530      */
531     private static final boolean equals(Object a, Object b) {
532         return (a == b) || (a != null && a.equals(b));
533     }
534 
535 }