This project has retired. For details please refer to its Attic page.
ObjectGenerator 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.util.repository;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.IOException;
24  import java.math.BigInteger;
25  import java.text.SimpleDateFormat;
26  import java.util.ArrayList;
27  import java.util.GregorianCalendar;
28  import java.util.List;
29  import java.util.Map;
30  import java.util.UUID;
31  
32  import org.apache.chemistry.opencmis.commons.PropertyIds;
33  import org.apache.chemistry.opencmis.commons.data.Acl;
34  import org.apache.chemistry.opencmis.commons.data.ContentStream;
35  import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
36  import org.apache.chemistry.opencmis.commons.data.ObjectData;
37  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
38  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
39  import org.apache.chemistry.opencmis.commons.data.Properties;
40  import org.apache.chemistry.opencmis.commons.data.PropertyData;
41  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinition;
42  import org.apache.chemistry.opencmis.commons.definitions.TypeDefinitionList;
43  import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
44  import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
45  import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
46  import org.apache.chemistry.opencmis.commons.enums.VersioningState;
47  import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
48  import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory;
49  import org.apache.chemistry.opencmis.commons.spi.NavigationService;
50  import org.apache.chemistry.opencmis.commons.spi.ObjectService;
51  import org.apache.chemistry.opencmis.commons.spi.RepositoryService;
52  import org.apache.chemistry.opencmis.util.content.fractal.FractalGenerator;
53  import org.apache.chemistry.opencmis.util.content.loremipsum.LoremIpsum;
54  import org.apache.commons.logging.Log;
55  import org.apache.commons.logging.LogFactory;
56  
57  /**
58   * A simple helper class for the tests that generates a sample folder hierarchy
59   * and optionally documents in it.
60   *
61   * @author Jens
62   *
63   */
64  public class ObjectGenerator {
65  
66      private static final Log log = LogFactory.getLog(ObjectGenerator.class);
67      private final BindingsObjectFactory fFactory;
68      NavigationService fNavSvc;
69      ObjectService fObjSvc;
70      RepositoryService fRepSvc;
71      private final String fRepositoryId;
72      private final TimeLogger fTimeLoggerCreateDoc;
73      private final TimeLogger fTimeLoggerCreateFolder;
74      private final TimeLogger fTimeLoggerDelete;
75      private final TimeLogger fTimeLoggerCreateType;
76      private boolean fCleanup;
77      List<String> fTopLevelDocsCreated; // list of ids created on first level
78      List<String> fTopLevelFoldersCreated; // list of ids created on first level
79  
80      /**
81       * supported kinds of content
82       *
83       */
84      public enum CONTENT_KIND {StaticText, LoremIpsumText, LoremIpsumHtml, ImageFractalJpeg};
85  
86      /**
87       * Indicates if / how many documents are created in each folder
88       */
89      private int fNoDocumentsToCreate;
90  
91      /**
92       * The type id of the document id that is created.
93       */
94      private String fDocTypeId = BaseTypeId.CMIS_DOCUMENT.value();
95  
96      /**
97       * The type id of the folder that is created.
98       */
99      private String fFolderTypeId = BaseTypeId.CMIS_FOLDER.value();
100 
101     /**
102      * A list of property ids. For each element in this list a String property
103      * value is created for each creation of a document. All ids must be valid
104      * string property id of the type fDocTypeId
105      */
106     private List<String> fStringPropertyIdsToSetForDocument;
107 
108     /**
109      * A list of property ids. For each element in this list a String property
110      * value is created for each creation of a folder. All ids must be valid
111      * string property id of the type fFolderTypeId
112      */
113     private List<String> fStringPropertyIdsToSetForFolder;
114 
115     /**
116      * number of documents created in total
117      */
118     private int fDocumentsInTotalCount = 0;
119 
120     /**
121      * number of folders created in total
122      */
123     private int fFoldersInTotalCount = 0;
124 
125     /**
126      * size of content in KB, if 0 create documents without content
127      */
128     private int fContentSizeInK = 0;
129     
130     /**
131      * Kind of content to create
132      */
133     private CONTENT_KIND fContentKind;
134     
135 
136     private static final String NAMEPROPVALPREFIXDOC = "My_Document-";
137     private static final String NAMEPROPVALPREFIXFOLDER = "My_Folder-";
138     private static final String STRINGPROPVALPREFIXDOC = "My Doc StringProperty ";
139     private static final String STRINGPROPVALPREFIXFOLDER = "My Folder StringProperty ";
140     private int propValCounterDocString = 0;
141     private int propValCounterFolderString = 0;
142     /**
143      * use UUIDs to generate folder and document names
144      */
145     private boolean fUseUuids;
146     
147     /**
148      * generator for images
149      */
150     private FractalGenerator fractalGenerator = null;
151 
152     public ObjectGenerator(BindingsObjectFactory factory, NavigationService navSvc, ObjectService objSvc,
153             RepositoryService repSvc, String repositoryId, CONTENT_KIND contentKind) {
154         super();
155         fFactory = factory;
156         fNavSvc = navSvc;
157         fObjSvc = objSvc;
158         fRepSvc = repSvc;
159         fRepositoryId = repositoryId;
160         // create an empty list of properties to generate by default for folder
161         // and document
162         fStringPropertyIdsToSetForDocument = new ArrayList<String>();
163         fStringPropertyIdsToSetForFolder = new ArrayList<String>();
164         fNoDocumentsToCreate = 0;
165         fUseUuids = false;
166         fTimeLoggerCreateDoc = new TimeLogger("createDocument()");
167         fTimeLoggerCreateFolder = new TimeLogger("createFolder()");
168         fTimeLoggerDelete = new TimeLogger("Delete");
169         fTimeLoggerCreateType = new TimeLogger("createType()");
170         fCleanup = false;
171         fTopLevelDocsCreated = new ArrayList<String>();
172         fTopLevelFoldersCreated = new ArrayList<String>();
173         fContentKind = contentKind;
174     }
175 
176     public void setNumberOfDocumentsToCreatePerFolder(int noDocumentsToCreate) {
177         fNoDocumentsToCreate = noDocumentsToCreate;
178     }
179 
180     public void setFolderTypeId(String folderTypeId) {
181         fFolderTypeId = folderTypeId;
182     }
183 
184     public void setDocumentTypeId(String docTypeId) {
185         fDocTypeId = docTypeId;
186     }
187 
188     public void setDocumentPropertiesToGenerate(List<String> propertyIds) {
189         fStringPropertyIdsToSetForDocument = propertyIds;
190     }
191 
192     public void setFolderPropertiesToGenerate(List<String> propertyIds) {
193         fStringPropertyIdsToSetForFolder = propertyIds;
194     }
195 
196     public void setContentSizeInKB(int sizeInK) {
197         fContentSizeInK = sizeInK;
198     }
199     
200     public CONTENT_KIND getContentKind() {
201         return fContentKind;
202     }
203     
204     public void setLoreIpsumGenerator(CONTENT_KIND contentKind) {
205         fContentKind = contentKind;
206     }
207 
208     public void setCleanUpAfterCreate(boolean doCleanup) {
209         fCleanup = doCleanup;
210     }
211 
212     public TimeLogger getCreateDocumentTimeLogger() {
213         return fTimeLoggerCreateDoc;
214     }
215 
216     public TimeLogger getCreateFolderTimeLogger() {
217         return fTimeLoggerCreateFolder;
218     }
219 
220     public TimeLogger getDeleteTimeLogger() {
221         return fTimeLoggerDelete;
222     }
223 
224     public void createFolderHierachy(int levels, int childrenPerLevel, String rootFolderId) {
225         resetCounters();
226         fTimeLoggerCreateDoc.reset();
227         fTimeLoggerCreateFolder.reset();
228         fTopLevelFoldersCreated.clear();
229         fTopLevelDocsCreated.clear();
230         createFolderHierachy(rootFolderId, 0, levels, childrenPerLevel);
231         if (fCleanup) {
232             deleteTree();
233         }
234     }
235 
236     public void setUseUuidsForNames(boolean useUuids) {
237         /**
238          * use UUIDs to generate folder and document names
239          */
240         fUseUuids = useUuids;
241     }
242 
243     /**
244      * retrieve the index-th folder from given level of the hierarchy starting
245      * at rootId
246      *
247      * @param rootId
248      * @param level
249      * @param index
250      * @return
251      */
252     public String getFolderId(String rootId, int level, int index) {
253         String objectId = rootId;
254         final String requiredProperties = PropertyIds.OBJECT_ID + "," + PropertyIds.OBJECT_TYPE_ID + ","
255                 + PropertyIds.BASE_TYPE_ID;
256         // Note: This works because first folders are created then documents
257         for (int i = 0; i < level; i++) {
258             ObjectInFolderList result = fNavSvc.getChildren(fRepositoryId, objectId, requiredProperties,
259                     PropertyIds.OBJECT_TYPE_ID, false, IncludeRelationships.NONE, null, true, BigInteger.valueOf(-1),
260                     BigInteger.valueOf(-1), null);
261             List<ObjectInFolderData> children = result.getObjects();
262             ObjectData child = children.get(index).getObject();
263             objectId = (String) child.getProperties().getProperties().get(PropertyIds.OBJECT_ID).getFirstValue();
264         }
265         return objectId;
266     }
267 
268     /**
269      * retrieve the index-th document from given folder
270      *
271      * @param folderId
272      *            folder to retrieve document from
273      * @param index
274      *            index of document to retrieve from this folder
275      * @return
276      */
277     public String getDocumentId(String folderId, int index) {
278         String docId = null;
279         final String requiredProperties = PropertyIds.OBJECT_ID + "," + PropertyIds.OBJECT_TYPE_ID + ","
280                 + PropertyIds.BASE_TYPE_ID;
281         ObjectInFolderList result = fNavSvc.getChildren(fRepositoryId, folderId, requiredProperties,
282                 PropertyIds.OBJECT_TYPE_ID, false, IncludeRelationships.NONE, null, true, BigInteger.valueOf(-1),
283                 BigInteger.valueOf(-1), null);
284         List<ObjectInFolderData> children = result.getObjects();
285         int numDocsFound = 0;
286         for (int i = 0; i < children.size(); i++) {
287             ObjectData child = children.get(i).getObject();
288             docId = (String) child.getProperties().getProperties().get(PropertyIds.OBJECT_ID).getFirstValue();
289             if (child.getBaseTypeId().equals(BaseTypeId.CMIS_DOCUMENT)) {
290                 if (numDocsFound == index) {
291                     return docId;
292                 } else {
293                     numDocsFound++;
294                 }
295             }
296         }
297         return docId;
298     }
299 
300     /**
301      * return the total number of documents created
302      *
303      * @return
304      */
305     public int getDocumentsInTotal() {
306         return fDocumentsInTotalCount;
307     }
308 
309     /**
310      * return the total number of folders created
311      *
312      * @return
313      */
314     public int getFoldersInTotal() {
315         return fFoldersInTotalCount;
316     }
317 
318     /**
319      * return the total number of objects created
320      */
321     public int getObjectsInTotal() {
322         return fDocumentsInTotalCount + fFoldersInTotalCount;
323     }
324 
325     public String createSingleDocument(String folderId) {
326         fTimeLoggerCreateDoc.reset();
327         String objectId = createDocument(folderId, 0, 0);
328         if (fCleanup) {
329             deleteObject(objectId);
330         }
331         return objectId;
332     }
333 
334     public String[] createDocuments(String folderId, int count) {
335 
336         String[] result;
337 
338         fTimeLoggerCreateDoc.reset();
339         for (int i = 0; i < count; i++) {
340             String id = createDocument(folderId, 0, 0);
341             fTopLevelDocsCreated.add(id);
342         }
343         if (fCleanup) {
344             deleteTree();
345             result = null;
346         } else {
347             result = new String[count];
348             for (int i = 0; i < fTopLevelDocsCreated.size(); i++) {
349                 result[i] = fTopLevelDocsCreated.get(i);
350             }
351         }
352         return result;
353     }
354 
355     public String[] createFolders(String folderId, int count) {
356 
357         String[] result;
358 
359         fTimeLoggerCreateFolder.reset();
360         for (int i = 0; i < count; i++) {
361             createFolder(folderId);
362         }
363         if (fCleanup) {
364             deleteTree();
365             result = null;
366         } else {
367             result = new String[count];
368             for (int i = 0; i < fTopLevelFoldersCreated.size(); i++) {
369                 result[i] = fTopLevelFoldersCreated.get(i);
370             }
371         }
372         return result;
373     }
374 
375     public void resetCounters() {
376         fDocumentsInTotalCount = fFoldersInTotalCount = 0;
377     }
378 
379     public void printTimings() {
380         fTimeLoggerCreateDoc.printTimes();
381         fTimeLoggerCreateFolder.printTimes();
382         if (fCleanup) {
383             fTimeLoggerDelete.printTimes();
384         }
385     }
386 
387     public void logTimings() {
388         fTimeLoggerCreateDoc.logTimes();
389         fTimeLoggerCreateFolder.logTimes();
390         if (fCleanup) {
391             fTimeLoggerDelete.logTimes();
392         }
393     }
394 
395     private void createFolderHierachy(String parentId, int level, int levels, int childrenPerLevel) {
396         String id = null;
397 
398         if (level >= levels) {
399             return;
400         }
401 
402         log.debug(" create folder for parent id: " + parentId + ", in level " + level + ", max levels " + levels);
403 
404         for (int i = 0; i < childrenPerLevel; i++) {
405             Properties props = createFolderProperties(i, level);
406             try {
407                 fTimeLoggerCreateFolder.start();
408                 id = fObjSvc.createFolder(fRepositoryId, props, parentId, null, null, null, null);
409                 if (level == 0) {
410                     fTopLevelFoldersCreated.add(id);
411                 }
412             } finally {
413                 fTimeLoggerCreateFolder.stop();
414             }
415 
416             if (id != null) {
417                 ++fFoldersInTotalCount;
418                 createFolderHierachy(id, level + 1, levels, childrenPerLevel);
419             }
420         }
421         for (int j = 0; j < fNoDocumentsToCreate; j++) {
422             id = createDocument(parentId, j, level);
423             if (level == 0) {
424                 fTopLevelDocsCreated.add(id);
425             }
426         }
427     }
428 
429     private String createFolder(String parentId) {
430         Properties props = createFolderProperties(0, 0);
431         String id = null;
432         try {
433             fTimeLoggerCreateFolder.start();
434             id = fObjSvc.createFolder(fRepositoryId, props, parentId, null, null, null, null);
435             fTopLevelFoldersCreated.add(id);
436         } finally {
437             fTimeLoggerCreateFolder.stop();
438         }
439         return id;
440     }
441 
442     private String createDocument(String folderId, int no, int level) {
443         ContentStream contentStream = null;
444         VersioningState versioningState = VersioningState.NONE;
445         List<String> policies = null;
446         Acl addACEs = null;
447         Acl removeACEs = null;
448         ExtensionsData extension = null;
449 
450         log.debug("create document in folder " + folderId);
451         Properties props = createDocumentProperties(no, level);
452         String id = null;
453         
454         if (fContentSizeInK > 0) {
455             switch (fContentKind) {
456             case StaticText:
457                 contentStream = createContentStaticText();
458                 break;
459             case LoremIpsumText:
460                 contentStream = createContentLoremIpsumText();
461                 break;
462             case LoremIpsumHtml:
463                 contentStream = createContentLoremIpsumHtml();
464                 break;
465             case ImageFractalJpeg:
466                 contentStream = createContentFractalimageJpeg();
467                 break;
468             }
469         }
470 
471         try {
472             fTimeLoggerCreateDoc.start();
473             id = fObjSvc.createDocument(fRepositoryId, props, folderId, contentStream, versioningState, policies,
474                     addACEs, removeACEs, extension);
475         } finally {
476             fTimeLoggerCreateDoc.stop();
477         }
478 
479         if (null == id) {
480             throw new RuntimeException("createDocument failed.");
481         }
482         ++fDocumentsInTotalCount;
483         return id;
484     }
485 
486     private void deleteTree() {
487 
488         // delete all documents from first level
489         for (String id : fTopLevelDocsCreated) {
490             deleteObject(id);
491         }
492 
493         // delete recursively all folders from first level
494         for (String id : fTopLevelFoldersCreated) {
495             try {
496                 fTimeLoggerDelete.start();
497                 fObjSvc.deleteTree(fRepositoryId, id, true, UnfileObject.DELETE, true, null);
498             } finally {
499                 fTimeLoggerDelete.stop();
500             }
501         }
502     }
503 
504     private void deleteObject(String objectId) {
505         try {
506             fTimeLoggerDelete.start();
507             fObjSvc.deleteObject(fRepositoryId, objectId, true, null);
508         } finally {
509             fTimeLoggerDelete.stop();
510         }
511     }
512 
513     public ContentStream createContentLoremIpsumHtml() {
514         ContentStreamImpl content = new ContentStreamImpl();
515         content.setFileName("data.html");
516         content.setMimeType("text/html");
517         int len = fContentSizeInK * 1024; // size of document in K
518         
519         LoremIpsum ipsum = new LoremIpsum();
520         String text = ipsum.generateParagraphsFullHtml(len, true);
521         content.setStream(new ByteArrayInputStream(text.getBytes()));
522         return content;
523     }
524 
525     public ContentStream createContentLoremIpsumText() {
526         ContentStreamImpl content = new ContentStreamImpl();
527         content.setFileName("data.txt");
528         content.setMimeType("text/plain");
529         int len = fContentSizeInK * 1024; // size of document in K
530         
531         LoremIpsum ipsum = new LoremIpsum();
532         String text = ipsum.generateParagraphsPlainText(len, 80, true);
533         content.setStream(new ByteArrayInputStream(text.getBytes()));
534         return content;
535     }
536 
537     public ContentStream createContentStaticText() {
538         ContentStreamImpl content = new ContentStreamImpl();
539         content.setFileName("data.txt");
540         content.setMimeType("text/plain");
541         int len = fContentSizeInK * 1024; // size of document in K
542         byte[] b = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x0c, 0x0a,
543                 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x0c, 0x0a }; // 32
544         // Bytes
545         ByteArrayOutputStream ba = new ByteArrayOutputStream(len);
546         try {
547             for (int j = 0; j < fContentSizeInK; j++) {
548                 // write 1K of data
549                 for (int i = 0; i < 32; i++) {
550                     ba.write(b);
551                 }
552             }
553         } catch (IOException e) {
554             throw new RuntimeException("Failed to fill content stream with data", e);
555         }
556         content.setStream(new ByteArrayInputStream(ba.toByteArray()));
557         return content;
558     }
559 
560     public ContentStream createContentFractalimageJpeg() {
561         if (null == fractalGenerator)
562             fractalGenerator = new FractalGenerator();
563 
564         ContentStreamImpl content = null;
565 
566         try {
567             ByteArrayOutputStream bos = fractalGenerator.generateFractal();
568             content = new ContentStreamImpl();
569             content.setFileName("image.jpg");
570             content.setMimeType("image/jpeg");
571             content.setStream(new ByteArrayInputStream(bos.toByteArray()));
572             bos.close();            
573         } catch (IOException e) {
574             System.err.println("Error when generating fractal image: " + e);
575             e.printStackTrace();
576         }
577 
578         return content;
579     }
580 
581     private Properties createFolderProperties(int no, int level) {
582         List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
583         properties.add(fFactory.createPropertyStringData(PropertyIds.NAME, generateFolderNameValue(no, level)));
584         properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, fFolderTypeId));
585         // Generate some property values for custom attributes
586         for (String stringPropId : fStringPropertyIdsToSetForFolder) {
587             properties.add(fFactory.createPropertyStringData(stringPropId, generateStringPropValueFolder()));
588         }
589         Properties props = fFactory.createPropertiesData(properties);
590         return props;
591     }
592 
593     private Properties createDocumentProperties(int no, int level) {
594         List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
595         properties.add(fFactory.createPropertyStringData(PropertyIds.NAME, generateDocNameValue(no, level)));
596         properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, fDocTypeId));
597         // Generate some property values for custom attributes
598         for (String stringPropId : fStringPropertyIdsToSetForDocument) {
599             properties.add(fFactory.createPropertyStringData(stringPropId, generateStringPropValueDoc()));
600         }
601         Properties props = fFactory.createPropertiesData(properties);
602         return props;
603     }
604 
605     private synchronized int incrementPropCounterDocStringProp() {
606         return propValCounterDocString++;
607     }
608 
609     private synchronized int incrementPropCounterFolderStringProp() {
610         return propValCounterFolderString++;
611     }
612 
613     private String generateDocNameValue(int no, int level) {
614         if (fUseUuids) {
615             return UUID.randomUUID().toString();
616         } else {
617             return NAMEPROPVALPREFIXDOC + level + "-" + no;
618         }
619     }
620 
621     private String generateFolderNameValue(int no, int level) {
622         if (fUseUuids) {
623             return UUID.randomUUID().toString();
624         } else {
625             return NAMEPROPVALPREFIXFOLDER + level + "-" + no;
626         }
627     }
628 
629     private String generateStringPropValueDoc() {
630         return STRINGPROPVALPREFIXDOC + incrementPropCounterDocStringProp();
631     }
632 
633     private String generateStringPropValueFolder() {
634         return STRINGPROPVALPREFIXFOLDER + incrementPropCounterFolderStringProp();
635     }
636 
637     public void dumpFolder(String folderId, String propertyFilter) {
638         log.debug("starting dumpFolder() id " + folderId + " ...");
639         boolean allRequiredPropertiesArePresent = propertyFilter != null && propertyFilter.equals("*"); // can
640         // be
641         // optimized
642         final String requiredProperties = allRequiredPropertiesArePresent ? propertyFilter : PropertyIds.OBJECT_ID
643                 + "," + PropertyIds.NAME + "," + PropertyIds.OBJECT_TYPE_ID + "," + PropertyIds.BASE_TYPE_ID;
644         // if all required properties are contained in the filter use we use the
645         // filter otherwise
646         // we use our own set and get those from the filter later in an extra
647         // call
648         String propertyFilterIntern = allRequiredPropertiesArePresent ? propertyFilter : requiredProperties;
649         dumpFolder(folderId, propertyFilterIntern, 0);
650     }
651 
652     private void dumpFolder(String folderId, String propertyFilter, int depth) {
653         boolean allRequiredPropertiesArePresent = propertyFilter.equals("*"); // can
654         // be
655         // optimized
656         StringBuilder prefix = new StringBuilder();
657         for (int i = 0; i < depth; i++) {
658             prefix.append("   ");
659         }
660 
661         ObjectInFolderList result = fNavSvc.getChildren(fRepositoryId, folderId, propertyFilter, null, false,
662                 IncludeRelationships.NONE, null, true, BigInteger.valueOf(-1), BigInteger.valueOf(-1), null);
663         List<ObjectInFolderData> folders = result.getObjects();
664         if (null != folders) {
665             log.debug(prefix + "found " + folders.size() + " children in folder " + folderId);
666             int no = 0;
667             for (ObjectInFolderData folder : folders) {
668                 log.debug(prefix.toString() + ++no + ": found object with id: " + folder.getObject().getId()
669                         + " and path segment: " + folder.getPathSegment());
670                 dumpObjectProperties(folder.getObject(), depth, propertyFilter, !allRequiredPropertiesArePresent);
671                 String objectTypeBaseId = folder.getObject().getBaseTypeId().value();
672                 if (objectTypeBaseId.equals(BaseTypeId.CMIS_FOLDER.value())) {
673                     dumpFolder(folder.getObject().getId(), propertyFilter, depth + 1);
674                 } else if (objectTypeBaseId.equals(BaseTypeId.CMIS_DOCUMENT.value())) {
675                     dumpObjectProperties(folder.getObject(), depth + 1, propertyFilter,
676                             !allRequiredPropertiesArePresent);
677                 }
678             }
679         }
680         log.debug(""); // add empty line
681     }
682 
683     private void dumpObjectProperties(ObjectData object, int depth, String propertyFilter, boolean mustFetchProperties) {
684         final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
685         StringBuilder prefix = new StringBuilder();
686         for (int i = 0; i < depth; i++) {
687             prefix.append("   ");
688         }
689 
690         log.debug(prefix + "found object id " + object.getId());
691         Map<String, PropertyData<?>> propMap;
692         if (mustFetchProperties) {
693             String objId = (String) object.getProperties().getProperties().get(PropertyIds.OBJECT_ID).getFirstValue();
694             Properties props = fObjSvc.getProperties(fRepositoryId, objId, propertyFilter, null);
695             propMap = props.getProperties();
696         } else {
697             propMap = object.getProperties().getProperties();
698         }
699         StringBuilder valueStr = new StringBuilder("[");
700         for (Map.Entry<String, PropertyData<?>> entry : propMap.entrySet()) {
701             if (entry.getValue().getValues().size() > 1) {
702                 if (entry.getValue().getFirstValue() instanceof GregorianCalendar) {
703                     for (Object obj : entry.getValue().getValues()) {
704                         GregorianCalendar cal = (GregorianCalendar) obj;
705                         valueStr.append(df.format(cal.getTime())).append(", ");
706                     }
707                     valueStr.append("]");
708                 } else {
709                     valueStr = new StringBuilder(entry.getValue().getValues().toString());
710                 }
711             } else {
712                 Object value = entry.getValue().getFirstValue();
713                 if (null != value) {
714                     valueStr = new StringBuilder(value.toString());
715                     if (value instanceof GregorianCalendar) {
716                         valueStr = new StringBuilder(df.format(((GregorianCalendar) entry.getValue().getFirstValue())
717                                 .getTime()));
718                     }
719                 }
720             }
721             log.debug(prefix + entry.getKey() + ": " + valueStr);
722         }
723         log.debug(""); // add empty line
724     }
725 
726     public void createTypes(TypeDefinitionList typeDefList) {
727         
728         fTimeLoggerCreateType.reset();         
729         for (TypeDefinition td : typeDefList.getList()) {
730             // TODO: enable this if available!
731 //            fRepSvc.createTypeDefinition(fRepositoryId, td);
732         }
733     }
734 }