View Javadoc

1   /*
2    wsmo4j - a WSMO API and Reference Implementation
3   
4    Copyright (c) 2004-2005, OntoText Lab. / SIRMA
5   
6    This library is free software; you can redistribute it and/or modify it under
7    the terms of the GNU Lesser General Public License as published by the Free
8    Software Foundation; either version 2.1 of the License, or (at your option)
9    any later version.
10   This library is distributed in the hope that it will be useful, but WITHOUT
11   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12   FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
13   details.
14   You should have received a copy of the GNU Lesser General Public License along
15   with this library; if not, write to the Free Software Foundation, Inc.,
16   59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17   */
18  
19  package com.ontotext.wsmo4j.factory;
20  
21  import org.wsmo.common.*;
22  import org.wsmo.locator.Locator;
23  import org.wsmo.common.exception.SynchronisationException;
24  
25  import java.util.*;
26  import java.lang.reflect.Proxy;
27  
28  /**
29   * <p>Title: </p>
30   * <p>Description: </p>
31   * <p>Copyright: Copyright (c) 2004-2005</p>
32   * <p>Company: Ontotext Lab., Sirma AI</p>
33   * @author unascribed
34   * @version 1.0
35   */
36  
37  final class EntityRegistry implements Locator {
38  
39      private static WeakHashMap <Identifier, WeakHashMap> weakMap = new WeakHashMap  <Identifier, WeakHashMap>();
40  
41      //private static ReferenceQueue weakMapQueue = new ReferenceQueue();
42  
43      private static EntityRegistry theOnlyInstance = new EntityRegistry();
44  
45      private EntityRegistry() {
46          //Factory.setDefaultLocator(this);
47      }
48  
49      static EntityRegistry get() {
50          return theOnlyInstance;
51      }
52  
53      /**
54       * Method tries to find in the internal registry if there is object for a 
55       * given iri of fiven type available
56       * @param uri identifier to search for
57       * @param clazz supported interface from by the object
58       * @return Entity or null if it's not found
59       */
60      static Entity isRegistered(Identifier uri, Class clazz) {
61          if (!clazz.isInterface()) {
62              throw new RuntimeException("supply an Interface as clazz parameter!");
63          }
64  
65          WeakHashMap innerMap = null;
66          synchronized(weakMap) {
67              try {
68                  innerMap = weakMap.get(uri);
69              }
70              catch (ClassCastException e) {
71                  throw new RuntimeException("Invalid entry type. WeakHashMap expected!");
72              }
73  
74              if (innerMap != null) {
75                  Object entity = null;
76                  Set keySet = innerMap.keySet();
77                  for (Iterator i = keySet.iterator(); i.hasNext();) {
78                      entity = i.next();
79                      
80                      // for proxy instances try to match every supported interface to clazz
81                      if (entity instanceof Proxy) {
82                          Object invocHandler = Proxy.getInvocationHandler(entity);
83                          if (invocHandler instanceof IDReference) {
84                              IDReference ref = (IDReference) invocHandler;
85                              Class[] supportedIfaces = ref.getSupportedInterfaces();
86                              for (int j = 0; j < supportedIfaces.length; j++) {
87                                  if (supportedIfaces[j].isAssignableFrom(clazz)) {
88                                      return (Entity) entity;
89                                  }
90                              }
91                          }
92                      }
93                      
94                      // for Entity object find if it's instances of the specified interface
95                      if (clazz.isInstance(entity)) {
96                          return (Entity) entity;
97                      }
98                  }
99              }
100         }
101 
102         return null;
103     }
104 
105     static void registerEntity(Entity entity) {
106         synchronized (weakMap) {
107             WeakHashMap innerMap = null;
108             try {
109                 innerMap = weakMap.get(entity.getIdentifier());
110             }
111             catch (ClassCastException e) {
112                 throw new RuntimeException("Invalid entry type. WeakHashMap expected!");
113             }
114             if (innerMap == null) {
115                 innerMap = new WeakHashMap();
116                 weakMap.put(entity.getIdentifier(), innerMap);
117             }
118             /* We may have attributes with type _"http://www.wsmo.org/wsml/wsml-syntax" target="alexandria_uri">http://www.wsmo.org/wsml/wsml-syntax#goal"
119              * If this check is enabled, we cannot set attribute value to goal instace
120              * However, if it is not, there would exist 2 objects of different type with the same IRI
121              */
122             else if (entity instanceof TopEntity) {
123                 Iterator iterator = innerMap.keySet().iterator();
124                 if (iterator.hasNext()) {
125                     StringBuffer errorMsg = getEntityType((Entity) innerMap.keySet().iterator().next());
126                     throw new RuntimeException("IRI " + entity.getIdentifier().toString() + 
127                         " is already registered as [" + errorMsg + "]. " +
128                         "Metamodeling is disallowed for TopEntity objects!");
129                 }
130             }
131 			
132             
133             innerMap.put(entity, null);
134         }
135     }
136     
137     // Helper method to get the supported types of an Entity/Proxy to Entity as String
138     private static StringBuffer getEntityType(Entity entity) {
139         StringBuffer resultStr = new StringBuffer();
140         if (entity instanceof Proxy == false) {
141             resultStr.append(entity.getClass().getName());
142             return resultStr;
143         }
144         if (Proxy.getInvocationHandler(entity) instanceof IDReference) {
145             IDReference ref = (IDReference) Proxy.getInvocationHandler(entity);
146             for(int i = 0; i < ref.getSupportedInterfaces().length; i++) {
147                 resultStr.append(ref.getSupportedInterfaces()[i].getName());
148                 if (i+1 < ref.getSupportedInterfaces().length) {
149                     resultStr.append(", ");
150                 }
151             }
152         }
153         return resultStr;
154     }
155 
156     /**
157      * Attempts to find an entity based on its IRI.
158      * @param id The ID of the entity to find
159      * @return The entity corresponding to the supplied ID or <i>null</i> if none found
160      * @throws org.wsmo.common.exception.SynchronisationException
161      * @see #setNext(Locator loc)
162      */
163     public Entity lookup(Identifier id, Class clazz) throws SynchronisationException {
164         Entity temp = isRegistered(id, clazz);
165         if (temp != null) {
166             if (temp instanceof Proxy) {
167                 Object ref = Proxy.getInvocationHandler(temp);
168                 if (ref instanceof IDReference) {
169                     if (((IDReference)ref).isResolved())
170                         return temp;
171                 }
172             }
173             else {
174                 return temp;
175             }
176         }
177         return null;
178     }
179 
180     public Set <Entity> lookup(Identifier id) throws SynchronisationException {
181         throw new UnsupportedOperationException("Use lookup(Identifier, Class) instead!");
182     }
183 }