You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by dc...@apache.org on 2010/04/22 18:34:54 UTC

svn commit: r936943 [4/4] - in /incubator/chemistry/opencmis/trunk/chemistry-opencmis-test: chemistry-opencmis-test-browser/src/main/java/org/apache/chemistry/opencmis/browser/ chemistry-opencmis-test-fit/src/test/java/org/apache/chemistry/opencmis/fit...

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-util/src/main/java/org/apache/chemistry/opencmis/util/repository/ObjectGenerator.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-util/src/main/java/org/apache/chemistry/opencmis/util/repository/ObjectGenerator.java?rev=936943&r1=936942&r2=936943&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-util/src/main/java/org/apache/chemistry/opencmis/util/repository/ObjectGenerator.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-util/src/main/java/org/apache/chemistry/opencmis/util/repository/ObjectGenerator.java Thu Apr 22 16:34:53 2010
@@ -58,559 +58,559 @@ import org.apache.commons.logging.LogFac
  */
 public class ObjectGenerator {
 
-	private static Log log = LogFactory.getLog(ObjectGenerator.class);
-	private BindingsObjectFactory fFactory;
-	NavigationService fNavSvc;
-	ObjectService fObjSvc;
-	private String fRepositoryId;
-	private TimeLogger fTimeLoggerCreateDoc;
-	private TimeLogger fTimeLoggerCreateFolder;
-	private TimeLogger fTimeLoggerDelete;
-	private boolean fCleanup;
-	List<String> fTopLevelDocsCreated; // list of ids created on first level
-	List<String> fTopLevelFoldersCreated; // list of ids created on first level
-
-	/**
-	 * Indicates if / how many documents are created in each folder
-	 */
-	private int fNoDocumentsToCreate;
-
-	/**
-	 * The type id of the document id that is created.
-	 */
-	private String fDocTypeId = BaseTypeId.CMIS_DOCUMENT.value();
-
-	/**
-	 * The type id of the folder that is created.
-	 */
-	private String fFolderTypeId = BaseTypeId.CMIS_FOLDER.value();
-
-	/**
-	 * A list of property ids. For each element in this list a String property
-	 * value is created for each creation of a document. All ids must be valid
-	 * string property id of the type fDocTypeId
-	 */
-	private List<String> fStringPropertyIdsToSetForDocument;
-
-	/**
-	 * A list of property ids. For each element in this list a String property
-	 * value is created for each creation of a folder. All ids must be valid
-	 * string property id of the type fFolderTypeId
-	 */
-	private List<String> fStringPropertyIdsToSetForFolder;
-
-	/**
-	 * number of documents created in total
-	 */
-	private int fDocumentsInTotalCount = 0;
-
-	/**
-	 * number of folders created in total
-	 */
-	private int fFoldersInTotalCount = 0;
-
-	/**
-	 * size of content in KB, if 0 create documents without content
-	 */
-	private int fContentSizeInK = 0;
-
-	private static final String NAMEPROPVALPREFIXDOC = "My_Document-";
-	private static final String NAMEPROPVALPREFIXFOLDER = "My_Folder-";
-	private static final String STRINGPROPVALPREFIXDOC = "My Doc StringProperty ";
-	private static final String STRINGPROPVALPREFIXFOLDER = "My Folder StringProperty ";
-	private static int PROPVALCOUNTER_DOC_STRING_PROP = 0;
-	private static int PROPVALCOUNTER_FOLDER_STRING_PROP = 0;
-	/**
-	 * use UUIDs to generate folder and document names
-	 */
-	private boolean fUseUuids;
-
-	public ObjectGenerator(BindingsObjectFactory factory, NavigationService navSvc, ObjectService objSvc,
-			String repositoryId) {
-		super();
-		fFactory = factory;
-		fNavSvc = navSvc;
-		fObjSvc = objSvc;
-		fRepositoryId = repositoryId;
-		// create an empty list of properties to generate by default for folder
-		// and document
-		fStringPropertyIdsToSetForDocument = new ArrayList<String>();
-		fStringPropertyIdsToSetForFolder = new ArrayList<String>();
-		fNoDocumentsToCreate = 0;
-		fUseUuids = false;
-		fTimeLoggerCreateDoc = new TimeLogger("createDocument()");
-		fTimeLoggerCreateFolder = new TimeLogger("createFolder()");
-		fTimeLoggerDelete = new TimeLogger("Delete");
-		fCleanup = false;
-		fTopLevelDocsCreated = new ArrayList<String>();
-		fTopLevelFoldersCreated = new ArrayList<String>();
-	}
-
-	public void setNumberOfDocumentsToCreatePerFolder(int noDocumentsToCreate) {
-		fNoDocumentsToCreate = noDocumentsToCreate;
-	}
-
-	public void setFolderTypeId(String folderTypeId) {
-		fFolderTypeId = folderTypeId;
-	}
-
-	public void setDocumentTypeId(String docTypeId) {
-		fDocTypeId = docTypeId;
-	}
-
-	public void setDocumentPropertiesToGenerate(List<String> propertyIds) {
-		fStringPropertyIdsToSetForDocument = propertyIds;
-	}
-
-	public void setFolderPropertiesToGenerate(List<String> propertyIds) {
-		fStringPropertyIdsToSetForFolder = propertyIds;
-	}
-
-	public void setContentSizeInKB(int sizeInK) {
-		fContentSizeInK = sizeInK;
-	}
-
-	public void setCleanUpAfterCreate(boolean doCleanup) {
-		fCleanup = doCleanup;
-	}
-
-	public TimeLogger getCreateDocumentTimeLogger() {
-		return fTimeLoggerCreateDoc;
-	}
-
-	public TimeLogger getCreateFolderTimeLogger() {
-		return fTimeLoggerCreateFolder;
-	}
-
-	public TimeLogger getDeleteTimeLogger() {
-		return fTimeLoggerDelete;
-	}
-
-	public void createFolderHierachy(int levels, int childrenPerLevel, String rootFolderId) {
-		resetCounters();
-		fTimeLoggerCreateDoc.reset();
-		fTimeLoggerCreateFolder.reset();
-		fTopLevelFoldersCreated.clear();
-		fTopLevelDocsCreated.clear();
-		createFolderHierachy(rootFolderId, 0, levels, childrenPerLevel);
-		if (fCleanup)
-			deleteTree();
-	}
-
-	public void setUseUuidsForNames(boolean useUuids) {
-		/**
-		 * use UUIDs to generate folder and document names
-		 */
-		fUseUuids = useUuids;
-	}
-
-	/**
-	 * retrieve the index-th folder from given level of the hierarchy starting
-	 * at rootId
-	 * 
-	 * @param rootId
-	 * @param level
-	 * @param index
-	 * @return
-	 */
-	public String getFolderId(String rootId, int level, int index) {
-		String objectId = rootId;
-		final String requiredProperties = PropertyIds.OBJECT_ID + "," + PropertyIds.OBJECT_TYPE_ID + ","
-				+ PropertyIds.BASE_TYPE_ID;
-		// Note: This works because first folders are created then documents
-		for (int i = 0; i < level; i++) {
-			ObjectInFolderList result = fNavSvc.getChildren(fRepositoryId, objectId, requiredProperties,
-					PropertyIds.OBJECT_TYPE_ID, false, IncludeRelationships.NONE, null, true, BigInteger.valueOf(-1),
-					BigInteger.valueOf(-1), null);
-			List<ObjectInFolderData> children = result.getObjects();
-			ObjectData child = children.get(index).getObject();
-			objectId = (String) child.getProperties().getProperties().get(PropertyIds.OBJECT_ID).getFirstValue();
-		}
-		return objectId;
-	}
-
-	/**
-	 * retrieve the index-th document from given folder
-	 * 
-	 * @param folderId
-	 *            folder to retrieve document from
-	 * @param index
-	 *            index of document to retrieve from this folder
-	 * @return
-	 */
-	public String getDocumentId(String folderId, int index) {
-		String docId = null;
-		final String requiredProperties = PropertyIds.OBJECT_ID + "," + PropertyIds.OBJECT_TYPE_ID + ","
-				+ PropertyIds.BASE_TYPE_ID;
-		ObjectInFolderList result = fNavSvc.getChildren(fRepositoryId, folderId, requiredProperties,
-				PropertyIds.OBJECT_TYPE_ID, false, IncludeRelationships.NONE, null, true, BigInteger.valueOf(-1),
-				BigInteger.valueOf(-1), null);
-		List<ObjectInFolderData> children = result.getObjects();
-		int numDocsFound = 0;
-		for (int i = 0; i < children.size(); i++) {
-			ObjectData child = children.get(i).getObject();
-			docId = (String) child.getProperties().getProperties().get(PropertyIds.OBJECT_ID).getFirstValue();
-			if (child.getBaseTypeId().equals(BaseTypeId.CMIS_DOCUMENT)) {
-				if (numDocsFound == index)
-					return docId;
-				else
-					numDocsFound++;
-			}
-		}
-		return docId;
-	}
-
-	/**
-	 * return the total number of documents created
-	 * 
-	 * @return
-	 */
-	public int getDocumentsInTotal() {
-		return fDocumentsInTotalCount;
-	}
-
-	/**
-	 * return the total number of folders created
-	 * 
-	 * @return
-	 */
-	public int getFoldersInTotal() {
-		return fFoldersInTotalCount;
-	}
-
-	/**
-	 * return the total number of objects created
-	 * 
-	 * @return
-	 */
-	public int getObjectsInTotal() {
-		return fDocumentsInTotalCount + fFoldersInTotalCount;
-	}
-
-	public String createSingleDocument(String folderId) {
-		fTimeLoggerCreateDoc.reset();
-		String objectId = createDocument(folderId, 0, 0);
-		if (fCleanup)
-			deleteObject(objectId);
-		return objectId;
-	}
-
-	public String[] createDocuments(String folderId, int count) {
-
-		String result[];
-
-		fTimeLoggerCreateDoc.reset();
-		for (int i = 0; i < count; i++) {
-			String id = createDocument(folderId, 0, 0);
-			fTopLevelDocsCreated.add(id);
-		}
-		if (fCleanup) {
-			deleteTree();
-			result = null;
-		} else {
-			result = new String[count];
-			for (int i = 0; i < fTopLevelDocsCreated.size(); i++)
-				result[i] = fTopLevelDocsCreated.get(i);
-		}
-		return result;
-	}
-
-	public String[] createFolders(String folderId, int count) {
-
-		String result[];
-
-		fTimeLoggerCreateFolder.reset();
-		for (int i = 0; i < count; i++) {
-			createFolder(folderId);
-		}
-		if (fCleanup) {
-			deleteTree();
-			result = null;
-		} else {
-			result = new String[count];
-			for (int i = 0; i < fTopLevelFoldersCreated.size(); i++)
-				result[i] = fTopLevelFoldersCreated.get(i);
-		}
-		return result;
-	}
-
-	public void resetCounters() {
-		fDocumentsInTotalCount = fFoldersInTotalCount = 0;
-	}
-
-	public void printTimings() {
-		fTimeLoggerCreateDoc.printTimes();
-		fTimeLoggerCreateFolder.printTimes();
-		if (fCleanup)
-			fTimeLoggerDelete.printTimes();
-	}
-
-	public void logTimings() {
-		fTimeLoggerCreateDoc.logTimes();
-		fTimeLoggerCreateFolder.logTimes();
-		if (fCleanup)
-			fTimeLoggerDelete.logTimes();
-	}
-
-	private void createFolderHierachy(String parentId, int level, int levels, int childrenPerLevel) {
-		String id = null;
-
-		if (level >= levels)
-			return;
-
-		log.debug(" create folder for parent id: " + parentId + ", in level " + level + ", max levels " + levels);
-
-		for (int i = 0; i < childrenPerLevel; i++) {
-			Properties props = createFolderProperties(i, level);
-			try {
-				fTimeLoggerCreateFolder.start();
-				id = fObjSvc.createFolder(fRepositoryId, props, parentId, null, null, null, null);
-				if (level == 0)
-					fTopLevelFoldersCreated.add(id);
-			} finally {
-				fTimeLoggerCreateFolder.stop();
-			}
-
-			if (id != null) {
-				++fFoldersInTotalCount;
-				createFolderHierachy(id, level + 1, levels, childrenPerLevel);
-			}
-		}
-		for (int j = 0; j < fNoDocumentsToCreate; j++) {
-			id = createDocument(parentId, j, level);
-			if (level == 0)
-				fTopLevelDocsCreated.add(id);
-		}
-	}
-
-	private String createFolder(String parentId) {
-		Properties props = createFolderProperties(0, 0);
-		String id = null;
-		try {
-			fTimeLoggerCreateFolder.start();
-			id = fObjSvc.createFolder(fRepositoryId, props, parentId, null, null, null, null);
-			fTopLevelFoldersCreated.add(id);
-		} finally {
-			fTimeLoggerCreateFolder.stop();
-		}
-		return id;
-	}
-
-	private String createDocument(String folderId, int no, int level) {
-		ContentStream contentStream = null;
-		VersioningState versioningState = VersioningState.NONE;
-		List<String> policies = null;
-		Acl addACEs = null;
-		Acl removeACEs = null;
-		ExtensionsData extension = null;
-
-		// log.info("create document in folder " + folderId);
-		Properties props = createDocumentProperties(no, level);
-		String id = null;
-		if (fContentSizeInK > 0)
-			contentStream = createContent();
-		try {
-			fTimeLoggerCreateDoc.start();
-			id = fObjSvc.createDocument(fRepositoryId, props, folderId, contentStream, versioningState, policies,
-					addACEs, removeACEs, extension);
-		} finally {
-			fTimeLoggerCreateDoc.stop();
-		}
-
-		if (null == id)
-			throw new RuntimeException("createDocument failed.");
-		++fDocumentsInTotalCount;
-		return id;
-	}
-
-	private void deleteTree() {
-
-		// delete all documents from first level
-		for (String id : fTopLevelDocsCreated) {
-			deleteObject(id);
-		}
-
-		// delete recursively all folders from first level
-		for (String id : fTopLevelFoldersCreated) {
-			try {
-				fTimeLoggerDelete.start();
-				fObjSvc.deleteTree(fRepositoryId, id, true, UnfileObject.DELETE, true, null);
-			} finally {
-				fTimeLoggerDelete.stop();
-			}
-		}
-	}
-
-	private void deleteObject(String objectId) {
-		try {
-			fTimeLoggerDelete.start();
-			fObjSvc.deleteObject(fRepositoryId, objectId, true, null);
-		} finally {
-			fTimeLoggerDelete.stop();
-		}
-	}
-
-	private ContentStream createContent() {
-		ContentStreamImpl content = new ContentStreamImpl();
-		content.setFileName("data.txt");
-		content.setMimeType("text/plain");
-		int len = fContentSizeInK * 1024; // size of document in K
-		byte[] b = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x0c, 0x0a,
-				0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x0c, 0x0a }; // 32
-		// Bytes
-		ByteArrayOutputStream ba = new ByteArrayOutputStream(len);
-		try {
-			for (int j = 0; j < fContentSizeInK; j++) {
-				// write 1K of data
-				for (int i = 0; i < 32; i++)
-					ba.write(b);
-			}
-		} catch (IOException e) {
-			throw new RuntimeException("Failed to fill content stream with data", e);
-		}
-		content.setStream(new ByteArrayInputStream(ba.toByteArray()));
-		return content;
-	}
-
-	private Properties createFolderProperties(int no, int level) {
-		List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
-		properties.add(fFactory.createPropertyStringData(PropertyIds.NAME, generateFolderNameValue(no, level)));
-		properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, fFolderTypeId));
-		// Generate some property values for custom attributes
-		for (String stringPropId : fStringPropertyIdsToSetForFolder) {
-			properties.add(fFactory.createPropertyStringData(stringPropId, generateStringPropValueFolder()));
-		}
-		Properties props = fFactory.createPropertiesData(properties);
-		return props;
-	}
-
-	private Properties createDocumentProperties(int no, int level) {
-		List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
-		properties.add(fFactory.createPropertyStringData(PropertyIds.NAME, generateDocNameValue(no, level)));
-		properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, fDocTypeId));
-		// Generate some property values for custom attributes
-		for (String stringPropId : fStringPropertyIdsToSetForDocument) {
-			properties.add(fFactory.createPropertyStringData(stringPropId, generateStringPropValueDoc()));
-		}
-		Properties props = fFactory.createPropertiesData(properties);
-		return props;
-	}
-
-	private static synchronized int incrementPropCounterDocStringProp() {
-		return PROPVALCOUNTER_DOC_STRING_PROP++;
-	}
-
-	private static synchronized int incrementPropCounterFolderStringProp() {
-		return PROPVALCOUNTER_FOLDER_STRING_PROP++;
-	}
-
-	private String generateDocNameValue(int no, int level) {
-		if (fUseUuids)
-			return UUID.randomUUID().toString();
-		else
-			return NAMEPROPVALPREFIXDOC + level + "-" + no;
-	}
-
-	private String generateFolderNameValue(int no, int level) {
-		if (fUseUuids)
-			return UUID.randomUUID().toString();
-		else
-			return NAMEPROPVALPREFIXFOLDER + level + "-" + no;
-	}
-
-	private static String generateStringPropValueDoc() {
-		return STRINGPROPVALPREFIXDOC + incrementPropCounterDocStringProp();
-	}
-
-	private static String generateStringPropValueFolder() {
-		return STRINGPROPVALPREFIXFOLDER + incrementPropCounterFolderStringProp();
-	}
-
-	public void dumpFolder(String folderId, String propertyFilter) {
-		log.info("starting dumpFolder() id " + folderId + " ...");
-		boolean allRequiredPropertiesArePresent = propertyFilter != null && propertyFilter.equals("*"); // can
-		// be
-		// optimized
-		final String requiredProperties = allRequiredPropertiesArePresent ? propertyFilter : PropertyIds.OBJECT_ID
-				+ "," + PropertyIds.NAME + "," + PropertyIds.OBJECT_TYPE_ID + "," + PropertyIds.BASE_TYPE_ID;
-		// if all required properties are contained in the filter use we use the
-		// filter otherwise
-		// we use our own set and get those from the filter later in an extra
-		// call
-		String propertyFilterIntern = allRequiredPropertiesArePresent ? propertyFilter : requiredProperties;
-		dumpFolder(folderId, propertyFilterIntern, 0);
-	}
-
-	private void dumpFolder(String folderId, String propertyFilter, int depth) {
-		boolean allRequiredPropertiesArePresent = propertyFilter.equals("*"); // can
-		// be
-		// optimized
-		StringBuilder prefix = new StringBuilder();
-		for (int i = 0; i < depth; i++)
-			prefix.append("   ");
-
-		ObjectInFolderList result = fNavSvc.getChildren(fRepositoryId, folderId, propertyFilter, null, false,
-				IncludeRelationships.NONE, null, true, BigInteger.valueOf(-1), BigInteger.valueOf(-1), null);
-		List<ObjectInFolderData> folders = result.getObjects();
-		if (null != folders) {
-			log.info(prefix + "found " + folders.size() + " children in folder " + folderId);
-			int no = 0;
-			for (ObjectInFolderData folder : folders) {
-				log.info(prefix.toString() + ++no + ": found object with id: " + folder.getObject().getId()
-						+ " and path segment: " + folder.getPathSegment());
-				dumpObjectProperties(folder.getObject(), depth, propertyFilter, !allRequiredPropertiesArePresent);
-				String objectTypeBaseId = folder.getObject().getBaseTypeId().value();
-				if (objectTypeBaseId.equals(BaseTypeId.CMIS_FOLDER.value())) {
-					dumpFolder(folder.getObject().getId(), propertyFilter, depth + 1);
-				} else if (objectTypeBaseId.equals(BaseTypeId.CMIS_DOCUMENT.value())) {
-					dumpObjectProperties(folder.getObject(), depth + 1, propertyFilter,
-							!allRequiredPropertiesArePresent);
-				}
-			}
-		}
-		log.info(""); // add empty line
-	}
-
-	private void dumpObjectProperties(ObjectData object, int depth, String propertyFilter, boolean mustFetchProperties) {
-		final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
-		StringBuilder prefix = new StringBuilder();
-		for (int i = 0; i < depth; i++)
-			prefix.append("   ");
-
-		log.info(prefix + "found object id " + object.getId());
-		Map<String, PropertyData<?>> propMap;
-		if (mustFetchProperties) {
-			String objId = (String) object.getProperties().getProperties().get(PropertyIds.OBJECT_ID).getFirstValue();
-			Properties props = fObjSvc.getProperties(fRepositoryId, objId, propertyFilter, null);
-			propMap = props.getProperties();
-		} else {
-			propMap = object.getProperties().getProperties();
-		}
-		StringBuilder valueStr = new StringBuilder("[");
-		for (Map.Entry<String, PropertyData<?>> entry : propMap.entrySet()) {
-			if (entry.getValue().getValues().size() > 1) {
-				if (entry.getValue().getFirstValue() instanceof GregorianCalendar) {
-					for (Object obj : entry.getValue().getValues()) {
-						GregorianCalendar cal = (GregorianCalendar) obj;
-						valueStr.append(df.format(cal.getTime()) + ", ");
-					}
-					valueStr.append("]");
-				} else {
-					valueStr = new StringBuilder(entry.getValue().getValues().toString());
-				}
-			} else {
-				Object value = entry.getValue().getFirstValue();
-				if (null != value) {
-					valueStr = new StringBuilder(value.toString());
-					if (value instanceof GregorianCalendar) {
-						valueStr = new StringBuilder(df.format(((GregorianCalendar) entry.getValue().getFirstValue())
-								.getTime()));
-					}
-				}
-			}
-			log.info(prefix + entry.getKey() + ": " + valueStr);
-		}
-		log.info(""); // add empty line
-	}
+    private static Log log = LogFactory.getLog(ObjectGenerator.class);
+    private BindingsObjectFactory fFactory;
+    NavigationService fNavSvc;
+    ObjectService fObjSvc;
+    private String fRepositoryId;
+    private TimeLogger fTimeLoggerCreateDoc;
+    private TimeLogger fTimeLoggerCreateFolder;
+    private TimeLogger fTimeLoggerDelete;
+    private boolean fCleanup;
+    List<String> fTopLevelDocsCreated; // list of ids created on first level
+    List<String> fTopLevelFoldersCreated; // list of ids created on first level
+
+    /**
+     * Indicates if / how many documents are created in each folder
+     */
+    private int fNoDocumentsToCreate;
+
+    /**
+     * The type id of the document id that is created.
+     */
+    private String fDocTypeId = BaseTypeId.CMIS_DOCUMENT.value();
+
+    /**
+     * The type id of the folder that is created.
+     */
+    private String fFolderTypeId = BaseTypeId.CMIS_FOLDER.value();
+
+    /**
+     * A list of property ids. For each element in this list a String property
+     * value is created for each creation of a document. All ids must be valid
+     * string property id of the type fDocTypeId
+     */
+    private List<String> fStringPropertyIdsToSetForDocument;
+
+    /**
+     * A list of property ids. For each element in this list a String property
+     * value is created for each creation of a folder. All ids must be valid
+     * string property id of the type fFolderTypeId
+     */
+    private List<String> fStringPropertyIdsToSetForFolder;
+
+    /**
+     * number of documents created in total
+     */
+    private int fDocumentsInTotalCount = 0;
+
+    /**
+     * number of folders created in total
+     */
+    private int fFoldersInTotalCount = 0;
+
+    /**
+     * size of content in KB, if 0 create documents without content
+     */
+    private int fContentSizeInK = 0;
+
+    private static final String NAMEPROPVALPREFIXDOC = "My_Document-";
+    private static final String NAMEPROPVALPREFIXFOLDER = "My_Folder-";
+    private static final String STRINGPROPVALPREFIXDOC = "My Doc StringProperty ";
+    private static final String STRINGPROPVALPREFIXFOLDER = "My Folder StringProperty ";
+    private static int PROPVALCOUNTER_DOC_STRING_PROP = 0;
+    private static int PROPVALCOUNTER_FOLDER_STRING_PROP = 0;
+    /**
+     * use UUIDs to generate folder and document names
+     */
+    private boolean fUseUuids;
+
+    public ObjectGenerator(BindingsObjectFactory factory, NavigationService navSvc, ObjectService objSvc,
+            String repositoryId) {
+        super();
+        fFactory = factory;
+        fNavSvc = navSvc;
+        fObjSvc = objSvc;
+        fRepositoryId = repositoryId;
+        // create an empty list of properties to generate by default for folder
+        // and document
+        fStringPropertyIdsToSetForDocument = new ArrayList<String>();
+        fStringPropertyIdsToSetForFolder = new ArrayList<String>();
+        fNoDocumentsToCreate = 0;
+        fUseUuids = false;
+        fTimeLoggerCreateDoc = new TimeLogger("createDocument()");
+        fTimeLoggerCreateFolder = new TimeLogger("createFolder()");
+        fTimeLoggerDelete = new TimeLogger("Delete");
+        fCleanup = false;
+        fTopLevelDocsCreated = new ArrayList<String>();
+        fTopLevelFoldersCreated = new ArrayList<String>();
+    }
+
+    public void setNumberOfDocumentsToCreatePerFolder(int noDocumentsToCreate) {
+        fNoDocumentsToCreate = noDocumentsToCreate;
+    }
+
+    public void setFolderTypeId(String folderTypeId) {
+        fFolderTypeId = folderTypeId;
+    }
+
+    public void setDocumentTypeId(String docTypeId) {
+        fDocTypeId = docTypeId;
+    }
+
+    public void setDocumentPropertiesToGenerate(List<String> propertyIds) {
+        fStringPropertyIdsToSetForDocument = propertyIds;
+    }
+
+    public void setFolderPropertiesToGenerate(List<String> propertyIds) {
+        fStringPropertyIdsToSetForFolder = propertyIds;
+    }
+
+    public void setContentSizeInKB(int sizeInK) {
+        fContentSizeInK = sizeInK;
+    }
+
+    public void setCleanUpAfterCreate(boolean doCleanup) {
+        fCleanup = doCleanup;
+    }
+
+    public TimeLogger getCreateDocumentTimeLogger() {
+        return fTimeLoggerCreateDoc;
+    }
+
+    public TimeLogger getCreateFolderTimeLogger() {
+        return fTimeLoggerCreateFolder;
+    }
+
+    public TimeLogger getDeleteTimeLogger() {
+        return fTimeLoggerDelete;
+    }
+
+    public void createFolderHierachy(int levels, int childrenPerLevel, String rootFolderId) {
+        resetCounters();
+        fTimeLoggerCreateDoc.reset();
+        fTimeLoggerCreateFolder.reset();
+        fTopLevelFoldersCreated.clear();
+        fTopLevelDocsCreated.clear();
+        createFolderHierachy(rootFolderId, 0, levels, childrenPerLevel);
+        if (fCleanup)
+            deleteTree();
+    }
+
+    public void setUseUuidsForNames(boolean useUuids) {
+        /**
+         * use UUIDs to generate folder and document names
+         */
+        fUseUuids = useUuids;
+    }
+
+    /**
+     * retrieve the index-th folder from given level of the hierarchy starting
+     * at rootId
+     * 
+     * @param rootId
+     * @param level
+     * @param index
+     * @return
+     */
+    public String getFolderId(String rootId, int level, int index) {
+        String objectId = rootId;
+        final String requiredProperties = PropertyIds.OBJECT_ID + "," + PropertyIds.OBJECT_TYPE_ID + ","
+                + PropertyIds.BASE_TYPE_ID;
+        // Note: This works because first folders are created then documents
+        for (int i = 0; i < level; i++) {
+            ObjectInFolderList result = fNavSvc.getChildren(fRepositoryId, objectId, requiredProperties,
+                    PropertyIds.OBJECT_TYPE_ID, false, IncludeRelationships.NONE, null, true, BigInteger.valueOf(-1),
+                    BigInteger.valueOf(-1), null);
+            List<ObjectInFolderData> children = result.getObjects();
+            ObjectData child = children.get(index).getObject();
+            objectId = (String) child.getProperties().getProperties().get(PropertyIds.OBJECT_ID).getFirstValue();
+        }
+        return objectId;
+    }
+
+    /**
+     * retrieve the index-th document from given folder
+     * 
+     * @param folderId
+     *            folder to retrieve document from
+     * @param index
+     *            index of document to retrieve from this folder
+     * @return
+     */
+    public String getDocumentId(String folderId, int index) {
+        String docId = null;
+        final String requiredProperties = PropertyIds.OBJECT_ID + "," + PropertyIds.OBJECT_TYPE_ID + ","
+                + PropertyIds.BASE_TYPE_ID;
+        ObjectInFolderList result = fNavSvc.getChildren(fRepositoryId, folderId, requiredProperties,
+                PropertyIds.OBJECT_TYPE_ID, false, IncludeRelationships.NONE, null, true, BigInteger.valueOf(-1),
+                BigInteger.valueOf(-1), null);
+        List<ObjectInFolderData> children = result.getObjects();
+        int numDocsFound = 0;
+        for (int i = 0; i < children.size(); i++) {
+            ObjectData child = children.get(i).getObject();
+            docId = (String) child.getProperties().getProperties().get(PropertyIds.OBJECT_ID).getFirstValue();
+            if (child.getBaseTypeId().equals(BaseTypeId.CMIS_DOCUMENT)) {
+                if (numDocsFound == index)
+                    return docId;
+                else
+                    numDocsFound++;
+            }
+        }
+        return docId;
+    }
+
+    /**
+     * return the total number of documents created
+     * 
+     * @return
+     */
+    public int getDocumentsInTotal() {
+        return fDocumentsInTotalCount;
+    }
+
+    /**
+     * return the total number of folders created
+     * 
+     * @return
+     */
+    public int getFoldersInTotal() {
+        return fFoldersInTotalCount;
+    }
+
+    /**
+     * return the total number of objects created
+     * 
+     * @return
+     */
+    public int getObjectsInTotal() {
+        return fDocumentsInTotalCount + fFoldersInTotalCount;
+    }
+
+    public String createSingleDocument(String folderId) {
+        fTimeLoggerCreateDoc.reset();
+        String objectId = createDocument(folderId, 0, 0);
+        if (fCleanup)
+            deleteObject(objectId);
+        return objectId;
+    }
+
+    public String[] createDocuments(String folderId, int count) {
+
+        String result[];
+
+        fTimeLoggerCreateDoc.reset();
+        for (int i = 0; i < count; i++) {
+            String id = createDocument(folderId, 0, 0);
+            fTopLevelDocsCreated.add(id);
+        }
+        if (fCleanup) {
+            deleteTree();
+            result = null;
+        } else {
+            result = new String[count];
+            for (int i = 0; i < fTopLevelDocsCreated.size(); i++)
+                result[i] = fTopLevelDocsCreated.get(i);
+        }
+        return result;
+    }
+
+    public String[] createFolders(String folderId, int count) {
+
+        String result[];
+
+        fTimeLoggerCreateFolder.reset();
+        for (int i = 0; i < count; i++) {
+            createFolder(folderId);
+        }
+        if (fCleanup) {
+            deleteTree();
+            result = null;
+        } else {
+            result = new String[count];
+            for (int i = 0; i < fTopLevelFoldersCreated.size(); i++)
+                result[i] = fTopLevelFoldersCreated.get(i);
+        }
+        return result;
+    }
+
+    public void resetCounters() {
+        fDocumentsInTotalCount = fFoldersInTotalCount = 0;
+    }
+
+    public void printTimings() {
+        fTimeLoggerCreateDoc.printTimes();
+        fTimeLoggerCreateFolder.printTimes();
+        if (fCleanup)
+            fTimeLoggerDelete.printTimes();
+    }
+
+    public void logTimings() {
+        fTimeLoggerCreateDoc.logTimes();
+        fTimeLoggerCreateFolder.logTimes();
+        if (fCleanup)
+            fTimeLoggerDelete.logTimes();
+    }
+
+    private void createFolderHierachy(String parentId, int level, int levels, int childrenPerLevel) {
+        String id = null;
+
+        if (level >= levels)
+            return;
+
+        log.debug(" create folder for parent id: " + parentId + ", in level " + level + ", max levels " + levels);
+
+        for (int i = 0; i < childrenPerLevel; i++) {
+            Properties props = createFolderProperties(i, level);
+            try {
+                fTimeLoggerCreateFolder.start();
+                id = fObjSvc.createFolder(fRepositoryId, props, parentId, null, null, null, null);
+                if (level == 0)
+                    fTopLevelFoldersCreated.add(id);
+            } finally {
+                fTimeLoggerCreateFolder.stop();
+            }
+
+            if (id != null) {
+                ++fFoldersInTotalCount;
+                createFolderHierachy(id, level + 1, levels, childrenPerLevel);
+            }
+        }
+        for (int j = 0; j < fNoDocumentsToCreate; j++) {
+            id = createDocument(parentId, j, level);
+            if (level == 0)
+                fTopLevelDocsCreated.add(id);
+        }
+    }
+
+    private String createFolder(String parentId) {
+        Properties props = createFolderProperties(0, 0);
+        String id = null;
+        try {
+            fTimeLoggerCreateFolder.start();
+            id = fObjSvc.createFolder(fRepositoryId, props, parentId, null, null, null, null);
+            fTopLevelFoldersCreated.add(id);
+        } finally {
+            fTimeLoggerCreateFolder.stop();
+        }
+        return id;
+    }
+
+    private String createDocument(String folderId, int no, int level) {
+        ContentStream contentStream = null;
+        VersioningState versioningState = VersioningState.NONE;
+        List<String> policies = null;
+        Acl addACEs = null;
+        Acl removeACEs = null;
+        ExtensionsData extension = null;
+
+        // log.info("create document in folder " + folderId);
+        Properties props = createDocumentProperties(no, level);
+        String id = null;
+        if (fContentSizeInK > 0)
+            contentStream = createContent();
+        try {
+            fTimeLoggerCreateDoc.start();
+            id = fObjSvc.createDocument(fRepositoryId, props, folderId, contentStream, versioningState, policies,
+                    addACEs, removeACEs, extension);
+        } finally {
+            fTimeLoggerCreateDoc.stop();
+        }
+
+        if (null == id)
+            throw new RuntimeException("createDocument failed.");
+        ++fDocumentsInTotalCount;
+        return id;
+    }
+
+    private void deleteTree() {
+
+        // delete all documents from first level
+        for (String id : fTopLevelDocsCreated) {
+            deleteObject(id);
+        }
+
+        // delete recursively all folders from first level
+        for (String id : fTopLevelFoldersCreated) {
+            try {
+                fTimeLoggerDelete.start();
+                fObjSvc.deleteTree(fRepositoryId, id, true, UnfileObject.DELETE, true, null);
+            } finally {
+                fTimeLoggerDelete.stop();
+            }
+        }
+    }
+
+    private void deleteObject(String objectId) {
+        try {
+            fTimeLoggerDelete.start();
+            fObjSvc.deleteObject(fRepositoryId, objectId, true, null);
+        } finally {
+            fTimeLoggerDelete.stop();
+        }
+    }
+
+    private ContentStream createContent() {
+        ContentStreamImpl content = new ContentStreamImpl();
+        content.setFileName("data.txt");
+        content.setMimeType("text/plain");
+        int len = fContentSizeInK * 1024; // size of document in K
+        byte[] b = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x0c, 0x0a,
+                0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x0c, 0x0a }; // 32
+        // Bytes
+        ByteArrayOutputStream ba = new ByteArrayOutputStream(len);
+        try {
+            for (int j = 0; j < fContentSizeInK; j++) {
+                // write 1K of data
+                for (int i = 0; i < 32; i++)
+                    ba.write(b);
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to fill content stream with data", e);
+        }
+        content.setStream(new ByteArrayInputStream(ba.toByteArray()));
+        return content;
+    }
+
+    private Properties createFolderProperties(int no, int level) {
+        List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
+        properties.add(fFactory.createPropertyStringData(PropertyIds.NAME, generateFolderNameValue(no, level)));
+        properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, fFolderTypeId));
+        // Generate some property values for custom attributes
+        for (String stringPropId : fStringPropertyIdsToSetForFolder) {
+            properties.add(fFactory.createPropertyStringData(stringPropId, generateStringPropValueFolder()));
+        }
+        Properties props = fFactory.createPropertiesData(properties);
+        return props;
+    }
+
+    private Properties createDocumentProperties(int no, int level) {
+        List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
+        properties.add(fFactory.createPropertyStringData(PropertyIds.NAME, generateDocNameValue(no, level)));
+        properties.add(fFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, fDocTypeId));
+        // Generate some property values for custom attributes
+        for (String stringPropId : fStringPropertyIdsToSetForDocument) {
+            properties.add(fFactory.createPropertyStringData(stringPropId, generateStringPropValueDoc()));
+        }
+        Properties props = fFactory.createPropertiesData(properties);
+        return props;
+    }
+
+    private static synchronized int incrementPropCounterDocStringProp() {
+        return PROPVALCOUNTER_DOC_STRING_PROP++;
+    }
+
+    private static synchronized int incrementPropCounterFolderStringProp() {
+        return PROPVALCOUNTER_FOLDER_STRING_PROP++;
+    }
+
+    private String generateDocNameValue(int no, int level) {
+        if (fUseUuids)
+            return UUID.randomUUID().toString();
+        else
+            return NAMEPROPVALPREFIXDOC + level + "-" + no;
+    }
+
+    private String generateFolderNameValue(int no, int level) {
+        if (fUseUuids)
+            return UUID.randomUUID().toString();
+        else
+            return NAMEPROPVALPREFIXFOLDER + level + "-" + no;
+    }
+
+    private static String generateStringPropValueDoc() {
+        return STRINGPROPVALPREFIXDOC + incrementPropCounterDocStringProp();
+    }
+
+    private static String generateStringPropValueFolder() {
+        return STRINGPROPVALPREFIXFOLDER + incrementPropCounterFolderStringProp();
+    }
+
+    public void dumpFolder(String folderId, String propertyFilter) {
+        log.info("starting dumpFolder() id " + folderId + " ...");
+        boolean allRequiredPropertiesArePresent = propertyFilter != null && propertyFilter.equals("*"); // can
+        // be
+        // optimized
+        final String requiredProperties = allRequiredPropertiesArePresent ? propertyFilter : PropertyIds.OBJECT_ID
+                + "," + PropertyIds.NAME + "," + PropertyIds.OBJECT_TYPE_ID + "," + PropertyIds.BASE_TYPE_ID;
+        // if all required properties are contained in the filter use we use the
+        // filter otherwise
+        // we use our own set and get those from the filter later in an extra
+        // call
+        String propertyFilterIntern = allRequiredPropertiesArePresent ? propertyFilter : requiredProperties;
+        dumpFolder(folderId, propertyFilterIntern, 0);
+    }
+
+    private void dumpFolder(String folderId, String propertyFilter, int depth) {
+        boolean allRequiredPropertiesArePresent = propertyFilter.equals("*"); // can
+        // be
+        // optimized
+        StringBuilder prefix = new StringBuilder();
+        for (int i = 0; i < depth; i++)
+            prefix.append("   ");
+
+        ObjectInFolderList result = fNavSvc.getChildren(fRepositoryId, folderId, propertyFilter, null, false,
+                IncludeRelationships.NONE, null, true, BigInteger.valueOf(-1), BigInteger.valueOf(-1), null);
+        List<ObjectInFolderData> folders = result.getObjects();
+        if (null != folders) {
+            log.info(prefix + "found " + folders.size() + " children in folder " + folderId);
+            int no = 0;
+            for (ObjectInFolderData folder : folders) {
+                log.info(prefix.toString() + ++no + ": found object with id: " + folder.getObject().getId()
+                        + " and path segment: " + folder.getPathSegment());
+                dumpObjectProperties(folder.getObject(), depth, propertyFilter, !allRequiredPropertiesArePresent);
+                String objectTypeBaseId = folder.getObject().getBaseTypeId().value();
+                if (objectTypeBaseId.equals(BaseTypeId.CMIS_FOLDER.value())) {
+                    dumpFolder(folder.getObject().getId(), propertyFilter, depth + 1);
+                } else if (objectTypeBaseId.equals(BaseTypeId.CMIS_DOCUMENT.value())) {
+                    dumpObjectProperties(folder.getObject(), depth + 1, propertyFilter,
+                            !allRequiredPropertiesArePresent);
+                }
+            }
+        }
+        log.info(""); // add empty line
+    }
+
+    private void dumpObjectProperties(ObjectData object, int depth, String propertyFilter, boolean mustFetchProperties) {
+        final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
+        StringBuilder prefix = new StringBuilder();
+        for (int i = 0; i < depth; i++)
+            prefix.append("   ");
+
+        log.info(prefix + "found object id " + object.getId());
+        Map<String, PropertyData<?>> propMap;
+        if (mustFetchProperties) {
+            String objId = (String) object.getProperties().getProperties().get(PropertyIds.OBJECT_ID).getFirstValue();
+            Properties props = fObjSvc.getProperties(fRepositoryId, objId, propertyFilter, null);
+            propMap = props.getProperties();
+        } else {
+            propMap = object.getProperties().getProperties();
+        }
+        StringBuilder valueStr = new StringBuilder("[");
+        for (Map.Entry<String, PropertyData<?>> entry : propMap.entrySet()) {
+            if (entry.getValue().getValues().size() > 1) {
+                if (entry.getValue().getFirstValue() instanceof GregorianCalendar) {
+                    for (Object obj : entry.getValue().getValues()) {
+                        GregorianCalendar cal = (GregorianCalendar) obj;
+                        valueStr.append(df.format(cal.getTime()) + ", ");
+                    }
+                    valueStr.append("]");
+                } else {
+                    valueStr = new StringBuilder(entry.getValue().getValues().toString());
+                }
+            } else {
+                Object value = entry.getValue().getFirstValue();
+                if (null != value) {
+                    valueStr = new StringBuilder(value.toString());
+                    if (value instanceof GregorianCalendar) {
+                        valueStr = new StringBuilder(df.format(((GregorianCalendar) entry.getValue().getFirstValue())
+                                .getTime()));
+                    }
+                }
+            }
+            log.info(prefix + entry.getKey() + ": " + valueStr);
+        }
+        log.info(""); // add empty line
+    }
 
 }

Modified: incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-util/src/main/java/org/apache/chemistry/opencmis/util/repository/TimeLogger.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-util/src/main/java/org/apache/chemistry/opencmis/util/repository/TimeLogger.java?rev=936943&r1=936942&r2=936943&view=diff
==============================================================================
--- incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-util/src/main/java/org/apache/chemistry/opencmis/util/repository/TimeLogger.java (original)
+++ incubator/chemistry/opencmis/trunk/chemistry-opencmis-test/chemistry-opencmis-test-util/src/main/java/org/apache/chemistry/opencmis/util/repository/TimeLogger.java Thu Apr 22 16:34:53 2010
@@ -30,228 +30,228 @@ import org.apache.commons.logging.LogFac
  * 
  */
 public class TimeLogger {
-	private static Log LOG = LogFactory.getLog(TimeLogger.class);
+    private static Log LOG = LogFactory.getLog(TimeLogger.class);
 
-	private static class TimeRecord {
-		public long fStart;
-		public long fStop;
-	};
-
-	private String fAction;
-	private LinkedList<TimeRecord> fTimeRecs = new LinkedList<TimeRecord>();
-	private final int maxSize = 2500;
-	TimeRecord fCurrentRec;
-
-	public TimeLogger() {
-		fAction = "";
-		fTimeRecs = new LinkedList<TimeRecord>();
-	}
-
-	public TimeLogger(String action) {
-		fAction = action;
-	}
-
-	public void start() {
-		createAndAddNewRecord();
-		fCurrentRec.fStart = System.currentTimeMillis();
-	}
-
-	public void stop() {
-		fCurrentRec.fStop = System.currentTimeMillis();
-	}
-
-	public void reset() {
-		fTimeRecs.clear();
-	}
-
-	public void logTimes() {
-		long size = fTimeRecs.size();
-		if (size == 0)
-			LOG.info("No samples for " + fAction + " available. ");
-		else if (size == 1)
-			LOG.info("Time elapsed for " + fAction + ": " + getLastTime());
-		else {
-			LOG.info("Timings for " + size + " samples for action " + fAction + ": ");
-			LOG.info("  Average: " + getAverageTime() + "ms");
-			LOG.info("  Min    : " + getMinTime() + "ms");
-			LOG.info("  Max    : " + getMaxTime() + "ms");
-			LOG.info("  Total  : " + getTotalTime() + "ms");
-		}
-	}
-
-	public void printTimes() {
-		long size = fTimeRecs.size();
-		if (size == 0)
-			System.out.println("No samples for " + fAction + " available. ");
-		else if (size == 1)
-			System.out.println("Time elapsed for " + fAction + ": " + getLastTime());
-		else {
-			System.out.println("Timings for " + size + " samples for action " + fAction + ": ");
-			System.out.println("  Average: " + getAverageTime() + "ms");
-			System.out.println("  Min    : " + getMinTime() + "ms");
-			System.out.println("  Max    : " + getMaxTime() + "ms");
-			System.out.println("  Total  : " + getTotalTime() + "ms");
-		}
-	}
-
-	public long getLastTime() {
-		TimeRecord lastRec = fTimeRecs.getLast();
-		if (null != lastRec)
-			return lastRec.fStop - lastRec.fStart;
-		else
-			return 0;
-	}
-
-	private void createAndAddNewRecord() {
-		if (fTimeRecs.size() < maxSize) {
-			fCurrentRec = new TimeRecord();
-			fTimeRecs.add(fCurrentRec);
-		}
-	}
-
-	private long getAverageTime() {
-		long sum = 0;
-		long size = fTimeRecs.size();
-
-		if (0 == fTimeRecs.size())
-			return 0;
-
-		for (TimeRecord tm : fTimeRecs) {
-			sum += tm.fStop - tm.fStart;
-		}
-		return (sum + size / 2) / size;
-	}
-
-	private long getMinTime() {
-		long min = Long.MAX_VALUE;
-
-		if (0 == fTimeRecs.size())
-			return 0;
-
-		for (TimeRecord tm : fTimeRecs) {
-			long val = tm.fStop - tm.fStart;
-			if (val < min)
-				min = val;
-		}
-		return min;
-
-	}
-
-	private long getMaxTime() {
-		long max = Long.MIN_VALUE;
-
-		if (0 == fTimeRecs.size())
-			return 0;
-
-		for (TimeRecord tm : fTimeRecs) {
-			long val = tm.fStop - tm.fStart;
-			if (val > max)
-				max = val;
-		}
-		return max;
-	}
-
-	private long getTotalTime() {
-		long sum = 0;
-
-		for (TimeRecord tm : fTimeRecs) {
-			sum += tm.fStop - tm.fStart;
-		}
-		return sum;
-	}
-
-	////////////////////////////////////////////////////////////////////////////
-	// ////////
-	//
-	// Same methods used for multithreaded logging
-
-	public static void logTimes(TimeLogger[] loggers) {
-		long size = 0;
-		if (null == loggers)
-			return;
-
-		for (int i = 0; i < loggers.length; i++)
-			size += loggers[i].fTimeRecs.size();
-
-		LOG.info("Timings for " + size + " samples for action " + loggers[0].fAction + ": ");
-		LOG.info("  Average: " + getAverageTime(loggers) + "ms");
-		LOG.info("  Min    : " + getMinTime(loggers) + "ms");
-		LOG.info("  Max    : " + getMaxTime(loggers) + "ms");
-		LOG.info("  Total  : " + getTotalTime(loggers) + "ms");
-	}
-
-	public static void printTimes(TimeLogger[] loggers) {
-		long size = 0;
-		if (null == loggers)
-			return;
-
-		for (int i = 0; i < loggers.length; i++)
-			size += loggers[i].fTimeRecs.size();
-
-		System.out.println("Timings for " + size + " samples for action " + loggers[0].fAction + ": ");
-		System.out.println("  Average: " + getAverageTime(loggers) + "ms");
-		System.out.println("  Min    : " + getMinTime(loggers) + "ms");
-		System.out.println("  Max    : " + getMaxTime(loggers) + "ms");
-		System.out.println("  Total  : " + getTotalTime(loggers) + "ms");
-
-	}
-
-	static private long getAverageTime(TimeLogger[] loggers) {
-		long sum = 0;
-		long size = 0;
-
-		for (int i = 0; i < loggers.length; i++)
-			size += loggers[i].fTimeRecs.size();
-
-		if (size == 0)
-			return 0;
-
-		for (int i = 0; i < loggers.length; i++) {
-			if (0 == loggers[i].fTimeRecs.size())
-				continue;
-
-			for (TimeRecord tm : loggers[i].fTimeRecs) {
-				sum += tm.fStop - tm.fStart;
-			}
-		}
-
-		return (sum + size / 2) / size;
-	}
-
-	static private long getMaxTime(TimeLogger[] loggers) {
-		long max = Long.MIN_VALUE;
-
-		for (int i = 0; i < loggers.length; i++) {
-			long val = loggers[i].getMaxTime();
-			if (val > max)
-				max = val;
-		}
-
-		return max;
-	}
-
-	static private long getMinTime(TimeLogger[] loggers) {
-		long min = Long.MAX_VALUE;
-
-		for (int i = 0; i < loggers.length; i++) {
-			long val = loggers[i].getMinTime();
-			if (val < min)
-				min = val;
-		}
-
-		return min;
-	}
-
-	static private long getTotalTime(TimeLogger[] loggers) {
-		long totalTime = Long.MIN_VALUE;
-
-		for (int i = 0; i < loggers.length; i++) {
-			long val = loggers[i].getTotalTime();
-			if (val > totalTime)
-				totalTime = val;
-		}
+    private static class TimeRecord {
+        public long fStart;
+        public long fStop;
+    };
+
+    private String fAction;
+    private LinkedList<TimeRecord> fTimeRecs = new LinkedList<TimeRecord>();
+    private final int maxSize = 2500;
+    TimeRecord fCurrentRec;
+
+    public TimeLogger() {
+        fAction = "";
+        fTimeRecs = new LinkedList<TimeRecord>();
+    }
+
+    public TimeLogger(String action) {
+        fAction = action;
+    }
+
+    public void start() {
+        createAndAddNewRecord();
+        fCurrentRec.fStart = System.currentTimeMillis();
+    }
+
+    public void stop() {
+        fCurrentRec.fStop = System.currentTimeMillis();
+    }
+
+    public void reset() {
+        fTimeRecs.clear();
+    }
+
+    public void logTimes() {
+        long size = fTimeRecs.size();
+        if (size == 0)
+            LOG.info("No samples for " + fAction + " available. ");
+        else if (size == 1)
+            LOG.info("Time elapsed for " + fAction + ": " + getLastTime());
+        else {
+            LOG.info("Timings for " + size + " samples for action " + fAction + ": ");
+            LOG.info("  Average: " + getAverageTime() + "ms");
+            LOG.info("  Min    : " + getMinTime() + "ms");
+            LOG.info("  Max    : " + getMaxTime() + "ms");
+            LOG.info("  Total  : " + getTotalTime() + "ms");
+        }
+    }
+
+    public void printTimes() {
+        long size = fTimeRecs.size();
+        if (size == 0)
+            System.out.println("No samples for " + fAction + " available. ");
+        else if (size == 1)
+            System.out.println("Time elapsed for " + fAction + ": " + getLastTime());
+        else {
+            System.out.println("Timings for " + size + " samples for action " + fAction + ": ");
+            System.out.println("  Average: " + getAverageTime() + "ms");
+            System.out.println("  Min    : " + getMinTime() + "ms");
+            System.out.println("  Max    : " + getMaxTime() + "ms");
+            System.out.println("  Total  : " + getTotalTime() + "ms");
+        }
+    }
+
+    public long getLastTime() {
+        TimeRecord lastRec = fTimeRecs.getLast();
+        if (null != lastRec)
+            return lastRec.fStop - lastRec.fStart;
+        else
+            return 0;
+    }
+
+    private void createAndAddNewRecord() {
+        if (fTimeRecs.size() < maxSize) {
+            fCurrentRec = new TimeRecord();
+            fTimeRecs.add(fCurrentRec);
+        }
+    }
+
+    private long getAverageTime() {
+        long sum = 0;
+        long size = fTimeRecs.size();
+
+        if (0 == fTimeRecs.size())
+            return 0;
+
+        for (TimeRecord tm : fTimeRecs) {
+            sum += tm.fStop - tm.fStart;
+        }
+        return (sum + size / 2) / size;
+    }
+
+    private long getMinTime() {
+        long min = Long.MAX_VALUE;
+
+        if (0 == fTimeRecs.size())
+            return 0;
+
+        for (TimeRecord tm : fTimeRecs) {
+            long val = tm.fStop - tm.fStart;
+            if (val < min)
+                min = val;
+        }
+        return min;
+
+    }
+
+    private long getMaxTime() {
+        long max = Long.MIN_VALUE;
+
+        if (0 == fTimeRecs.size())
+            return 0;
+
+        for (TimeRecord tm : fTimeRecs) {
+            long val = tm.fStop - tm.fStart;
+            if (val > max)
+                max = val;
+        }
+        return max;
+    }
+
+    private long getTotalTime() {
+        long sum = 0;
+
+        for (TimeRecord tm : fTimeRecs) {
+            sum += tm.fStop - tm.fStart;
+        }
+        return sum;
+    }
+
+    // //////////////////////////////////////////////////////////////////////////
+    // ////////
+    //
+    // Same methods used for multithreaded logging
+
+    public static void logTimes(TimeLogger[] loggers) {
+        long size = 0;
+        if (null == loggers)
+            return;
+
+        for (int i = 0; i < loggers.length; i++)
+            size += loggers[i].fTimeRecs.size();
+
+        LOG.info("Timings for " + size + " samples for action " + loggers[0].fAction + ": ");
+        LOG.info("  Average: " + getAverageTime(loggers) + "ms");
+        LOG.info("  Min    : " + getMinTime(loggers) + "ms");
+        LOG.info("  Max    : " + getMaxTime(loggers) + "ms");
+        LOG.info("  Total  : " + getTotalTime(loggers) + "ms");
+    }
+
+    public static void printTimes(TimeLogger[] loggers) {
+        long size = 0;
+        if (null == loggers)
+            return;
+
+        for (int i = 0; i < loggers.length; i++)
+            size += loggers[i].fTimeRecs.size();
+
+        System.out.println("Timings for " + size + " samples for action " + loggers[0].fAction + ": ");
+        System.out.println("  Average: " + getAverageTime(loggers) + "ms");
+        System.out.println("  Min    : " + getMinTime(loggers) + "ms");
+        System.out.println("  Max    : " + getMaxTime(loggers) + "ms");
+        System.out.println("  Total  : " + getTotalTime(loggers) + "ms");
+
+    }
+
+    static private long getAverageTime(TimeLogger[] loggers) {
+        long sum = 0;
+        long size = 0;
+
+        for (int i = 0; i < loggers.length; i++)
+            size += loggers[i].fTimeRecs.size();
+
+        if (size == 0)
+            return 0;
+
+        for (int i = 0; i < loggers.length; i++) {
+            if (0 == loggers[i].fTimeRecs.size())
+                continue;
+
+            for (TimeRecord tm : loggers[i].fTimeRecs) {
+                sum += tm.fStop - tm.fStart;
+            }
+        }
+
+        return (sum + size / 2) / size;
+    }
+
+    static private long getMaxTime(TimeLogger[] loggers) {
+        long max = Long.MIN_VALUE;
+
+        for (int i = 0; i < loggers.length; i++) {
+            long val = loggers[i].getMaxTime();
+            if (val > max)
+                max = val;
+        }
+
+        return max;
+    }
+
+    static private long getMinTime(TimeLogger[] loggers) {
+        long min = Long.MAX_VALUE;
+
+        for (int i = 0; i < loggers.length; i++) {
+            long val = loggers[i].getMinTime();
+            if (val < min)
+                min = val;
+        }
+
+        return min;
+    }
+
+    static private long getTotalTime(TimeLogger[] loggers) {
+        long totalTime = Long.MIN_VALUE;
+
+        for (int i = 0; i < loggers.length; i++) {
+            long val = loggers[i].getTotalTime();
+            if (val > totalTime)
+                totalTime = val;
+        }
 
-		return totalTime;
-	}
+        return totalTime;
+    }
 
 }