View Javadoc
1   /*
2    * Copyright (c) 2002-2014, Mairie de Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.document.modules.cmis.service;
35  
36  import org.apache.chemistry.opencmis.commons.PropertyIds;
37  import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
38  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
39  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionContainer;
40  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList;
41  import org.apache.chemistry.opencmis.commons.enums.*;
42  import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
43  import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
44  import org.apache.chemistry.opencmis.commons.impl.dataobjects.*;
45  import org.apache.chemistry.opencmis.commons.server.CallContext;
46  
47  import java.math.BigInteger;
48  
49  import java.util.ArrayList;
50  import java.util.HashMap;
51  import java.util.List;
52  import java.util.Map;
53  
54  
55  /**
56   * TypeManager
57   */
58  public class TypeManager
59  {
60      /**
61       *
62       */
63      public static final String DOCUMENT_TYPE_ID = BaseTypeId.CMIS_DOCUMENT.value(  );
64  
65      /**
66       *
67       */
68      public static final String FOLDER_TYPE_ID = BaseTypeId.CMIS_FOLDER.value(  );
69  
70      /**
71       *
72       */
73      public static final String RELATIONSHIP_TYPE_ID = BaseTypeId.CMIS_RELATIONSHIP.value(  );
74  
75      /**
76       *
77       */
78      public static final String POLICY_TYPE_ID = BaseTypeId.CMIS_POLICY.value(  );
79      private static final String NAMESPACE = "http://opencmis.org/fileshare";
80      private Map<String, TypeDefinitionContainerImpl> types;
81      private List<TypeDefinitionContainer> typesList;
82  
83      /**
84       *
85       */
86      public TypeManager(  )
87      {
88          setup(  );
89      }
90  
91      /**
92       * Creates the base types.
93       */
94      private void setup(  )
95      {
96          types = new HashMap<String, TypeDefinitionContainerImpl>(  );
97          typesList = new ArrayList<TypeDefinitionContainer>(  );
98  
99          // folder type
100         FolderTypeDefinitionImpl folderType = new FolderTypeDefinitionImpl(  );
101         folderType.setBaseTypeId( BaseTypeId.CMIS_FOLDER );
102         folderType.setIsControllableAcl( false );
103         folderType.setIsControllablePolicy( false );
104         folderType.setIsCreatable( true );
105         folderType.setDescription( "Folder" );
106         folderType.setDisplayName( "Folder" );
107         folderType.setIsFileable( true );
108         folderType.setIsFulltextIndexed( false );
109         folderType.setIsIncludedInSupertypeQuery( true );
110         folderType.setLocalName( "Folder" );
111         folderType.setLocalNamespace( NAMESPACE );
112         folderType.setIsQueryable( false );
113         folderType.setQueryName( "cmis:folder" );
114         folderType.setId( FOLDER_TYPE_ID );
115 
116         addBasePropertyDefinitions( folderType );
117         addFolderPropertyDefinitions( folderType );
118 
119         addTypeInteral( folderType );
120 
121         // document type
122         DocumentTypeDefinitionImpl documentType = new DocumentTypeDefinitionImpl(  );
123         documentType.setBaseTypeId( BaseTypeId.CMIS_DOCUMENT );
124         documentType.setIsControllableAcl( false );
125         documentType.setIsControllablePolicy( false );
126         documentType.setIsCreatable( true );
127         documentType.setDescription( "Document" );
128         documentType.setDisplayName( "Document" );
129         documentType.setIsFileable( true );
130         documentType.setIsFulltextIndexed( false );
131         documentType.setIsIncludedInSupertypeQuery( true );
132         documentType.setLocalName( "Document" );
133         documentType.setLocalNamespace( NAMESPACE );
134         documentType.setIsQueryable( false );
135         documentType.setQueryName( "cmis:document" );
136         documentType.setId( DOCUMENT_TYPE_ID );
137 
138         documentType.setIsVersionable( false );
139         documentType.setContentStreamAllowed( ContentStreamAllowed.ALLOWED );
140 
141         addBasePropertyDefinitions( documentType );
142         addDocumentPropertyDefinitions( documentType );
143 
144         addTypeInteral( documentType );
145 
146         // relationship types
147         RelationshipTypeDefinitionImpl relationshipType = new RelationshipTypeDefinitionImpl(  );
148         relationshipType.setBaseTypeId( BaseTypeId.CMIS_RELATIONSHIP );
149         relationshipType.setIsControllableAcl( false );
150         relationshipType.setIsControllablePolicy( false );
151         relationshipType.setIsCreatable( false );
152         relationshipType.setDescription( "Relationship" );
153         relationshipType.setDisplayName( "Relationship" );
154         relationshipType.setIsFileable( false );
155         relationshipType.setIsIncludedInSupertypeQuery( true );
156         relationshipType.setLocalName( "Relationship" );
157         relationshipType.setLocalNamespace( NAMESPACE );
158         relationshipType.setIsQueryable( false );
159         relationshipType.setQueryName( "cmis:relationship" );
160         relationshipType.setId( RELATIONSHIP_TYPE_ID );
161 
162         addBasePropertyDefinitions( relationshipType );
163 
164         // not supported - don't expose it
165         // addTypeInteral(relationshipType);
166 
167         // policy type
168         PolicyTypeDefinitionImpl policyType = new PolicyTypeDefinitionImpl(  );
169         policyType.setBaseTypeId( BaseTypeId.CMIS_POLICY );
170         policyType.setIsControllableAcl( false );
171         policyType.setIsControllablePolicy( false );
172         policyType.setIsCreatable( false );
173         policyType.setDescription( "Policy" );
174         policyType.setDisplayName( "Policy" );
175         policyType.setIsFileable( false );
176         policyType.setIsIncludedInSupertypeQuery( true );
177         policyType.setLocalName( "Policy" );
178         policyType.setLocalNamespace( NAMESPACE );
179         policyType.setIsQueryable( false );
180         policyType.setQueryName( "cmis:policy" );
181         policyType.setId( POLICY_TYPE_ID );
182 
183         addBasePropertyDefinitions( policyType );
184 
185         // not supported - don't expose it
186         // addTypeInteral(policyType);
187     }
188 
189     private static void addBasePropertyDefinitions( AbstractTypeDefinition type )
190     {
191         type.addPropertyDefinition( createPropDef( PropertyIds.BASE_TYPE_ID, "Base Type Id", "Base Type Id",
192                 PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
193 
194         type.addPropertyDefinition( createPropDef( PropertyIds.OBJECT_ID, "Object Id", "Object Id", PropertyType.ID,
195                 Cardinality.SINGLE, Updatability.READONLY, false, false ) );
196 
197         type.addPropertyDefinition( createPropDef( PropertyIds.OBJECT_TYPE_ID, "Type Id", "Type Id", PropertyType.ID,
198                 Cardinality.SINGLE, Updatability.ONCREATE, false, true ) );
199 
200         type.addPropertyDefinition( createPropDef( PropertyIds.NAME, "Name", "Name", PropertyType.STRING,
201                 Cardinality.SINGLE, Updatability.READWRITE, false, true ) );
202 
203         type.addPropertyDefinition( createPropDef( PropertyIds.CREATED_BY, "Created By", "Created By",
204                 PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
205 
206         type.addPropertyDefinition( createPropDef( PropertyIds.CREATION_DATE, "Creation Date", "Creation Date",
207                 PropertyType.DATETIME, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
208 
209         type.addPropertyDefinition( createPropDef( PropertyIds.LAST_MODIFIED_BY, "Last Modified By",
210                 "Last Modified By", PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
211 
212         type.addPropertyDefinition( createPropDef( PropertyIds.LAST_MODIFICATION_DATE, "Last Modification Date",
213                 "Last Modification Date", PropertyType.DATETIME, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
214 
215         type.addPropertyDefinition( createPropDef( PropertyIds.CHANGE_TOKEN, "Change Token", "Change Token",
216                 PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
217     }
218 
219     private static void addFolderPropertyDefinitions( FolderTypeDefinitionImpl type )
220     {
221         type.addPropertyDefinition( createPropDef( PropertyIds.PARENT_ID, "Parent Id", "Parent Id", PropertyType.ID,
222                 Cardinality.SINGLE, Updatability.READONLY, false, false ) );
223 
224         type.addPropertyDefinition( createPropDef( PropertyIds.ALLOWED_CHILD_OBJECT_TYPE_IDS,
225                 "Allowed Child Object Type Ids", "Allowed Child Object Type Ids", PropertyType.ID, Cardinality.MULTI,
226                 Updatability.READONLY, false, false ) );
227 
228         type.addPropertyDefinition( createPropDef( PropertyIds.PATH, "Path", "Path", PropertyType.STRING,
229                 Cardinality.SINGLE, Updatability.READONLY, false, false ) );
230     }
231 
232     private static void addDocumentPropertyDefinitions( DocumentTypeDefinitionImpl type )
233     {
234         type.addPropertyDefinition( createPropDef( PropertyIds.IS_IMMUTABLE, "Is Immutable", "Is Immutable",
235                 PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
236 
237         type.addPropertyDefinition( createPropDef( PropertyIds.IS_LATEST_VERSION, "Is Latest Version",
238                 "Is Latest Version", PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
239 
240         type.addPropertyDefinition( createPropDef( PropertyIds.IS_MAJOR_VERSION, "Is Major Version",
241                 "Is Major Version", PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
242 
243         type.addPropertyDefinition( createPropDef( PropertyIds.IS_LATEST_MAJOR_VERSION, "Is Latest Major Version",
244                 "Is Latest Major Version", PropertyType.BOOLEAN, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
245 
246         type.addPropertyDefinition( createPropDef( PropertyIds.VERSION_LABEL, "Version Label", "Version Label",
247                 PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, true ) );
248 
249         type.addPropertyDefinition( createPropDef( PropertyIds.VERSION_SERIES_ID, "Version Series Id",
250                 "Version Series Id", PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, true ) );
251 
252         type.addPropertyDefinition( createPropDef( PropertyIds.IS_VERSION_SERIES_CHECKED_OUT,
253                 "Is Verison Series Checked Out", "Is Verison Series Checked Out", PropertyType.BOOLEAN,
254                 Cardinality.SINGLE, Updatability.READONLY, false, false ) );
255 
256         type.addPropertyDefinition( createPropDef( PropertyIds.VERSION_SERIES_CHECKED_OUT_ID,
257                 "Version Series Checked Out Id", "Version Series Checked Out Id", PropertyType.ID, Cardinality.SINGLE,
258                 Updatability.READONLY, false, false ) );
259 
260         type.addPropertyDefinition( createPropDef( PropertyIds.VERSION_SERIES_CHECKED_OUT_BY,
261                 "Version Series Checked Out By", "Version Series Checked Out By", PropertyType.STRING,
262                 Cardinality.SINGLE, Updatability.READONLY, false, false ) );
263 
264         type.addPropertyDefinition( createPropDef( PropertyIds.CHECKIN_COMMENT, "Checkin Comment", "Checkin Comment",
265                 PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
266 
267         type.addPropertyDefinition( createPropDef( PropertyIds.CONTENT_STREAM_LENGTH, "Content Stream Length",
268                 "Content Stream Length", PropertyType.INTEGER, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
269 
270         type.addPropertyDefinition( createPropDef( PropertyIds.CONTENT_STREAM_MIME_TYPE, "MIME Type", "MIME Type",
271                 PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
272 
273         type.addPropertyDefinition( createPropDef( PropertyIds.CONTENT_STREAM_FILE_NAME, "Filename", "Filename",
274                 PropertyType.STRING, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
275 
276         type.addPropertyDefinition( createPropDef( PropertyIds.CONTENT_STREAM_ID, "Content Stream Id",
277                 "Content Stream Id", PropertyType.ID, Cardinality.SINGLE, Updatability.READONLY, false, false ) );
278     }
279 
280     /**
281      * Creates a property definition object.
282      */
283     private static PropertyDefinition<?> createPropDef( String id, String displayName, String description,
284         PropertyType datatype, Cardinality cardinality, Updatability updateability, boolean inherited, boolean required )
285     {
286         AbstractPropertyDefinition<?> result = null;
287 
288         switch ( datatype )
289         {
290             case BOOLEAN:
291                 result = new PropertyBooleanDefinitionImpl(  );
292 
293                 break;
294 
295             case DATETIME:
296                 result = new PropertyDateTimeDefinitionImpl(  );
297 
298                 break;
299 
300             case DECIMAL:
301                 result = new PropertyDecimalDefinitionImpl(  );
302 
303                 break;
304 
305             case HTML:
306                 result = new PropertyHtmlDefinitionImpl(  );
307 
308                 break;
309 
310             case ID:
311                 result = new PropertyIdDefinitionImpl(  );
312 
313                 break;
314 
315             case INTEGER:
316                 result = new PropertyIntegerDefinitionImpl(  );
317 
318                 break;
319 
320             case STRING:
321                 result = new PropertyStringDefinitionImpl(  );
322 
323                 break;
324 
325             case URI:
326                 result = new PropertyUriDefinitionImpl(  );
327 
328                 break;
329 
330             default:
331                 throw new RuntimeException( "Unknown datatype! Spec change?" );
332         }
333 
334         result.setId( id );
335         result.setLocalName( id );
336         result.setDisplayName( displayName );
337         result.setDescription( description );
338         result.setPropertyType( datatype );
339         result.setCardinality( cardinality );
340         result.setUpdatability( updateability );
341         result.setIsInherited( inherited );
342         result.setIsRequired( required );
343         result.setIsQueryable( false );
344         result.setIsOrderable( false );
345         result.setQueryName( id );
346 
347         return result;
348     }
349 
350     /**
351      * Adds a type to collection with inheriting base type properties.
352      * @param type
353      * @return
354      */
355     public boolean addType( TypeDefinition type )
356     {
357         if ( type == null )
358         {
359             return false;
360         }
361 
362         if ( type.getBaseTypeId(  ) == null )
363         {
364             return false;
365         }
366 
367         // find base type
368         TypeDefinition baseType;
369 
370         if ( type.getBaseTypeId(  ) == BaseTypeId.CMIS_DOCUMENT )
371         {
372             baseType = copyTypeDefintion( types.get( DOCUMENT_TYPE_ID ).getTypeDefinition(  ) );
373         }
374         else if ( type.getBaseTypeId(  ) == BaseTypeId.CMIS_FOLDER )
375         {
376             baseType = copyTypeDefintion( types.get( FOLDER_TYPE_ID ).getTypeDefinition(  ) );
377         }
378         else if ( type.getBaseTypeId(  ) == BaseTypeId.CMIS_RELATIONSHIP )
379         {
380             baseType = copyTypeDefintion( types.get( RELATIONSHIP_TYPE_ID ).getTypeDefinition(  ) );
381         }
382         else if ( type.getBaseTypeId(  ) == BaseTypeId.CMIS_POLICY )
383         {
384             baseType = copyTypeDefintion( types.get( POLICY_TYPE_ID ).getTypeDefinition(  ) );
385         }
386         else
387         {
388             return false;
389         }
390 
391         AbstractTypeDefinition newType = (AbstractTypeDefinition) copyTypeDefintion( type );
392 
393         // copy property definition
394         for ( PropertyDefinition<?> propDef : baseType.getPropertyDefinitions(  ).values(  ) )
395         {
396             ( (AbstractPropertyDefinition<?>) propDef ).setIsInherited( true );
397             newType.addPropertyDefinition( propDef );
398         }
399 
400         // add it
401         addTypeInteral( newType );
402 
403         return true;
404     }
405 
406     /**
407      * Adds a type to collection.
408      */
409     private void addTypeInteral( AbstractTypeDefinition type )
410     {
411         if ( type == null )
412         {
413             return;
414         }
415 
416         if ( types.containsKey( type.getId(  ) ) )
417         {
418             // can't overwrite a type
419             return;
420         }
421 
422         TypeDefinitionContainerImpl tc = new TypeDefinitionContainerImpl(  );
423         tc.setTypeDefinition( type );
424 
425         // add to parent
426         if ( type.getParentTypeId(  ) != null )
427         {
428             TypeDefinitionContainerImpl tdc = types.get( type.getParentTypeId(  ) );
429 
430             if ( tdc != null )
431             {
432                 if ( tdc.getChildren(  ) == null )
433                 {
434                     tdc.setChildren( new ArrayList<TypeDefinitionContainer>(  ) );
435                 }
436 
437                 tdc.getChildren(  ).add( tc );
438             }
439         }
440 
441         types.put( type.getId(  ), tc );
442         typesList.add( tc );
443     }
444 
445     /**
446      * CMIS getTypesChildren.
447      * @param context
448      * @param typeId
449      * @param includePropertyDefinitions
450      * @param maxItems
451      * @param skipCount
452      * @return
453      */
454     public TypeDefinitionList getTypesChildren( CallContext context, String typeId, boolean includePropertyDefinitions,
455         BigInteger maxItems, BigInteger skipCount )
456     {
457         TypeDefinitionListImpl result = new TypeDefinitionListImpl( new ArrayList<TypeDefinition>(  ) );
458 
459         int skip = ( ( skipCount == null ) ? 0 : skipCount.intValue(  ) );
460 
461         if ( skip < 0 )
462         {
463             skip = 0;
464         }
465 
466         int max = ( ( maxItems == null ) ? Integer.MAX_VALUE : maxItems.intValue(  ) );
467 
468         if ( max < 1 )
469         {
470             return result;
471         }
472 
473         if ( typeId == null )
474         {
475             if ( skip < 1 )
476             {
477                 result.getList(  ).add( copyTypeDefintion( types.get( FOLDER_TYPE_ID ).getTypeDefinition(  ) ) );
478                 max--;
479             }
480 
481             if ( ( skip < 2 ) && ( max > 0 ) )
482             {
483                 result.getList(  ).add( copyTypeDefintion( types.get( DOCUMENT_TYPE_ID ).getTypeDefinition(  ) ) );
484                 max--;
485             }
486 
487             result.setHasMoreItems( ( result.getList(  ).size(  ) + skip ) < 2 );
488             result.setNumItems( BigInteger.valueOf( 2 ) );
489         }
490         else
491         {
492             TypeDefinitionContainer tc = types.get( typeId );
493 
494             if ( ( tc == null ) || ( tc.getChildren(  ) == null ) )
495             {
496                 return result;
497             }
498 
499             for ( TypeDefinitionContainer child : tc.getChildren(  ) )
500             {
501                 if ( skip > 0 )
502                 {
503                     skip--;
504 
505                     continue;
506                 }
507 
508                 result.getList(  ).add( copyTypeDefintion( child.getTypeDefinition(  ) ) );
509 
510                 max--;
511 
512                 if ( max == 0 )
513                 {
514                     break;
515                 }
516             }
517 
518             result.setHasMoreItems( ( result.getList(  ).size(  ) + skip ) < tc.getChildren(  ).size(  ) );
519             result.setNumItems( BigInteger.valueOf( tc.getChildren(  ).size(  ) ) );
520         }
521 
522         if ( !includePropertyDefinitions )
523         {
524             for ( TypeDefinition type : result.getList(  ) )
525             {
526                 type.getPropertyDefinitions(  ).clear(  );
527             }
528         }
529 
530         return result;
531     }
532 
533     /**
534      * CMIS getTypesDescendants.
535      * @param context
536      * @param depth
537      * @param typeId
538      * @param includePropertyDefinitions
539      * @return
540      */
541     public List<TypeDefinitionContainer> getTypesDescendants( CallContext context, String typeId, BigInteger depth,
542         Boolean includePropertyDefinitions )
543     {
544         List<TypeDefinitionContainer> result = new ArrayList<TypeDefinitionContainer>(  );
545 
546         // check depth
547         int d = ( ( depth == null ) ? ( -1 ) : depth.intValue(  ) );
548 
549         if ( d == 0 )
550         {
551             throw new CmisInvalidArgumentException( "Depth must not be 0!" );
552         }
553 
554         // set property definition flag to default value if not set
555         boolean ipd = ( ( includePropertyDefinitions == null ) ? false : includePropertyDefinitions.booleanValue(  ) );
556 
557         if ( typeId == null )
558         {
559             result.add( getTypesDescendants( d, types.get( FOLDER_TYPE_ID ), ipd ) );
560             result.add( getTypesDescendants( d, types.get( DOCUMENT_TYPE_ID ), ipd ) );
561 
562             // result.add(getTypesDescendants(depth,
563             // fTypes.get(RELATIONSHIP_TYPE_ID), includePropertyDefinitions));
564             // result.add(getTypesDescendants(depth, fTypes.get(POLICY_TYPE_ID),
565             // includePropertyDefinitions));
566         }
567         else
568         {
569             TypeDefinitionContainer tc = types.get( typeId );
570 
571             if ( tc != null )
572             {
573                 result.add( getTypesDescendants( d, tc, ipd ) );
574             }
575         }
576 
577         return result;
578     }
579 
580     /**
581      * Gathers the type descendants tree.
582      */
583     private TypeDefinitionContainer getTypesDescendants( int depth, TypeDefinitionContainer tc,
584         boolean includePropertyDefinitions )
585     {
586         TypeDefinitionContainerImpl result = new TypeDefinitionContainerImpl(  );
587 
588         TypeDefinition type = copyTypeDefintion( tc.getTypeDefinition(  ) );
589 
590         if ( !includePropertyDefinitions )
591         {
592             type.getPropertyDefinitions(  ).clear(  );
593         }
594 
595         result.setTypeDefinition( type );
596 
597         if ( depth != 0 )
598         {
599             if ( tc.getChildren(  ) != null )
600             {
601                 result.setChildren( new ArrayList<TypeDefinitionContainer>(  ) );
602 
603                 for ( TypeDefinitionContainer tdc : tc.getChildren(  ) )
604                 {
605                     result.getChildren(  )
606                           .add( getTypesDescendants( ( depth < 0 ) ? ( -1 ) : ( depth - 1 ), tdc,
607                             includePropertyDefinitions ) );
608                 }
609             }
610         }
611 
612         return result;
613     }
614 
615     /**
616      * For internal use.
617      * @param typeId
618      * @return
619      */
620     public TypeDefinition getType( String typeId )
621     {
622         TypeDefinitionContainer tc = types.get( typeId );
623 
624         if ( tc == null )
625         {
626             return null;
627         }
628 
629         return tc.getTypeDefinition(  );
630     }
631 
632     /**
633      * CMIS getTypeDefinition.
634      * @param context
635      * @param typeId
636      * @return
637      */
638     public TypeDefinition getTypeDefinition( CallContext context, String typeId )
639     {
640         TypeDefinitionContainer tc = types.get( typeId );
641 
642         if ( tc == null )
643         {
644             throw new CmisObjectNotFoundException( "Type '" + typeId + "' is unknown!" );
645         }
646 
647         return copyTypeDefintion( tc.getTypeDefinition(  ) );
648     }
649 
650     private static TypeDefinition copyTypeDefintion( TypeDefinition type )
651     {
652         return type;
653 
654         //        return Converter.convert(Converter.convert(type));
655     }
656 }