This project has retired. For details please refer to its Attic page.
TypeManagerImpl xref

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.chemistry.opencmis.inmemory;
20  
21  import java.util.ArrayList;
22  import java.util.Collection;
23  import java.util.HashMap;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Map.Entry;
27  
28  import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
29  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
30  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
31  import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
32  import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
33  import org.apache.chemistry.opencmis.commons.impl.Converter;
34  import org.apache.chemistry.opencmis.commons.impl.dataobjects.AbstractPropertyDefinition;
35  import org.apache.chemistry.opencmis.commons.impl.dataobjects.TypeDefinitionContainerImpl;
36  import org.apache.chemistry.opencmis.commons.impl.jaxb.CmisPropertyDefinitionType;
37  import org.apache.chemistry.opencmis.inmemory.storedobj.api.TypeManagerCreatable;
38  import org.apache.chemistry.opencmis.inmemory.types.DocumentTypeCreationHelper;
39  import org.apache.chemistry.opencmis.inmemory.types.InMemoryDocumentTypeDefinition;
40  import org.apache.chemistry.opencmis.inmemory.types.InMemoryFolderTypeDefinition;
41  import org.apache.chemistry.opencmis.inmemory.types.InMemoryPolicyTypeDefinition;
42  import org.apache.chemistry.opencmis.inmemory.types.InMemoryRelationshipTypeDefinition;
43  import org.apache.commons.logging.Log;
44  import org.apache.commons.logging.LogFactory;
45  
46  /**
47   * Class that manages a type system for a repository types can be added, the
48   * inheritance can be managed and type can be retrieved for a given type id.
49   *
50   * @author Jens
51   *
52   */
53  public class TypeManagerImpl implements TypeManagerCreatable {
54  
55      private static final Log LOG = LogFactory.getLog(TypeManagerImpl.class.getName());
56      /**
57       * map from repository id to a types map
58       */
59      private final Map<String, TypeDefinitionContainer> fTypesMap = new HashMap<String, TypeDefinitionContainer>();
60  
61      /* (non-Javadoc)
62       * @see org.apache.chemistry.opencmis.inmemory.TypeManager#getTypeById(java.lang.String)
63       */
64      public TypeDefinitionContainer getTypeById(String typeId) {
65          return fTypesMap.get(typeId);
66      }
67  
68      /* (non-Javadoc)
69       * @see org.apache.chemistry.opencmis.inmemory.TypeManager#getTypeByQueryName(java.lang.String)
70       */
71      public TypeDefinition getTypeByQueryName(String typeQueryName) {
72          for (Entry<String, TypeDefinitionContainer> entry : fTypesMap.entrySet()) {
73              if (entry.getValue().getTypeDefinition().getQueryName().equals(typeQueryName)) {
74                  return entry.getValue().getTypeDefinition();
75              }
76          }
77          return null;
78      }
79  
80      /* (non-Javadoc)
81       * @see org.apache.chemistry.opencmis.inmemory.TypeManager#getTypeDefinitionList()
82       */
83      public synchronized Collection<TypeDefinitionContainer> getTypeDefinitionList() {
84  
85          List<TypeDefinitionContainer> typeRoots = new ArrayList<TypeDefinitionContainer>();
86          // iterate types map and return a list collecting the root types:
87          for (TypeDefinitionContainer typeDef : fTypesMap.values()) {
88              if (typeDef.getTypeDefinition().getParentTypeId() == null) {
89                  typeRoots.add(typeDef);
90              }
91          }
92  
93          return typeRoots;
94      }
95  
96      /* (non-Javadoc)
97       * @see org.apache.chemistry.opencmis.inmemory.TypeManager#getRootTypes()
98       */
99      public List<TypeDefinitionContainer> getRootTypes() {
100         // just take first repository
101         List<TypeDefinitionContainer> rootTypes = new ArrayList<TypeDefinitionContainer>();
102 
103         for (TypeDefinitionContainer type : fTypesMap.values()) {
104             if (isRootType(type)) {
105                 rootTypes.add(type);
106             }
107         }
108 
109         return rootTypes;
110     }
111 
112     /**
113      * Initialize the type system with the given types. This list must not
114      * contain the CMIS default types. The default type are always contained by
115      * default.
116      *
117      * @param typesList
118      *            list of types to add to the repository
119      *
120      */
121     public void initTypeSystem(List<TypeDefinition> typesList) {
122 
123         createCmisDefaultTypes();
124 
125         // merge all types from the list and build the correct hierachy with
126         // children
127         // and property lists
128         if (null != typesList) {
129             for (TypeDefinition typeDef : typesList) {
130                 addTypeDefinition(typeDef);
131             }
132         }
133 
134     }
135 
136     /**
137      * Add a type to the type system. Add all properties from inherited types,
138      * add type to children of parent types.
139      *
140      * @param repositoryId
141      *            repository to which the type is added
142      * @param cmisType
143      *            new type to add
144      */
145     public void addTypeDefinition(TypeDefinition cmisType) {
146         
147         TypeDefinitionContainerImpl typeContainer = new TypeDefinitionContainerImpl(cmisType);
148 
149         // add new type to children of parent types
150         TypeDefinitionContainer parentTypeContainer = fTypesMap.get(cmisType.getParentTypeId());
151         parentTypeContainer.getChildren().add(typeContainer);
152 
153         // recursively add inherited properties
154         Map<String, PropertyDefinition<?>> propDefs = typeContainer.getTypeDefinition().getPropertyDefinitions();
155         addInheritedProperties(propDefs, parentTypeContainer.getTypeDefinition());
156 
157         LOG.info("Adding type definition with name " + cmisType.getLocalName() + " and id " 
158                 + cmisType.getId() + " to repository.");
159         // add type to type map
160         fTypesMap.put(cmisType.getId(), typeContainer);
161     }
162     
163     public void updateTypeDefinition(TypeDefinition typeDefinition) {
164         throw new CmisNotSupportedException("updating a type definition is not supported.");
165     }
166 
167     /**
168      * Remove a type from a type system
169      * @param typeId
170      */
171     public void deleteTypeDefinition(String typeId) {
172         fTypesMap.remove(typeId);       
173     }
174 
175 
176     /**
177      * Remove all types from the type system. After this call only the default
178      * CMIS types are present in the type system. Use this method with care, its
179      * mainly intended for unit tests
180      *
181      * @param repositoryId
182      */
183     public void clearTypeSystem() {
184         fTypesMap.clear();
185         createCmisDefaultTypes();
186     }
187 
188     /* (non-Javadoc)
189      * @see org.apache.chemistry.opencmis.inmemory.TypeManager#getPropertyIdForQueryName(org.apache.chemistry.opencmis.commons.definitions.TypeDefinition, java.lang.String)
190      */
191     public String getPropertyIdForQueryName(TypeDefinition typeDefinition, String propQueryName) {
192         for (PropertyDefinition<?> pd : typeDefinition.getPropertyDefinitions().values()) {
193             if (pd.getQueryName().equals(propQueryName)) {
194                 return pd.getId();
195             }
196         }
197         return null;
198     }
199 
200     private void addInheritedProperties(Map<String, PropertyDefinition<?>> propDefs, TypeDefinition typeDefinition) {
201 
202         if (null == typeDefinition) {
203             return;
204         }
205 
206         if (null != typeDefinition.getPropertyDefinitions())
207          {
208             addInheritedPropertyDefinitions(propDefs, typeDefinition.getPropertyDefinitions());
209         // propDefs.putAll(typeDefinition.getPropertyDefinitions());
210         }
211 
212         TypeDefinitionContainer parentTypeContainer = fTypesMap.get(typeDefinition.getParentTypeId());
213         TypeDefinition parentType = (null == parentTypeContainer ? null : parentTypeContainer.getTypeDefinition());
214         addInheritedProperties(propDefs, parentType);
215     }
216 
217     private static void addInheritedPropertyDefinitions(Map<String, PropertyDefinition<?>> propDefs,
218             Map<String, PropertyDefinition<?>> superPropDefs) {
219 
220         for (Entry<String, PropertyDefinition<?>> superProp : superPropDefs.entrySet()) {
221             PropertyDefinition<?> superPropDef = superProp.getValue();
222             PropertyDefinition<?> clone = clonePropertyDefinition(superPropDef);
223             ((AbstractPropertyDefinition<?>) clone).setIsInherited(true);
224             propDefs.put(superProp.getKey(), clone);
225         }
226     }
227 
228     private void createCmisDefaultTypes() {
229         List<TypeDefinition> typesList = DocumentTypeCreationHelper.createDefaultTypes();
230         for (TypeDefinition typeDef : typesList) {
231             TypeDefinitionContainerImpl typeContainer = new TypeDefinitionContainerImpl(typeDef);
232             fTypesMap.put(typeDef.getId(), typeContainer);
233         }
234     }
235 
236     private static boolean isRootType(TypeDefinitionContainer c) {
237         if (c.getTypeDefinition().equals(InMemoryFolderTypeDefinition.getRootFolderType())
238                 || c.getTypeDefinition().equals(InMemoryDocumentTypeDefinition.getRootDocumentType())
239                 || c.getTypeDefinition().equals(InMemoryRelationshipTypeDefinition.getRootRelationshipType())
240                 || c.getTypeDefinition().equals(InMemoryPolicyTypeDefinition.getRootPolicyType())) {
241             return true;
242         } else {
243             return false;
244         }
245     }
246 
247     private static PropertyDefinition<?> clonePropertyDefinition(PropertyDefinition<?> src) {
248         // use JAXB converter to easily clone a property definition
249         CmisPropertyDefinitionType tmp = Converter.convert(src);
250         PropertyDefinition<?> clone = Converter.convert(tmp);
251         return clone;
252     }
253 
254     // private static PropertyDefinition<?>
255     // clonePropertyDefinition2(PropertyDefinition<?> src)
256     // throws IOException, ClassNotFoundException {
257     // ByteArrayOutputStream bout = new ByteArrayOutputStream();
258     // ObjectOutputStream oout = new ObjectOutputStream(bout);
259     // oout.writeObject(src);
260     // byte[] bytes = bout.toByteArray();
261     //
262     // ByteArrayInputStream bin = new ByteArrayInputStream(bytes);
263     // ObjectInputStream oin = new ObjectInputStream(bin);
264     // PropertyDefinition<?> clone = (PropertyDefinition<?>) oin.readObject();
265     // return clone;
266     // }
267 
268 }