cancel
Showing results for 
Search instead for 
Did you mean: 

How to create directory structure using Java API?

upforsin
Star Collaborator
Star Collaborator

Hello

I'm trying to create a folder structure (something similar to "mkdir -p" command) using Java API, but when I create a folder, I cannot create a subfolder in it, because a parent folder does not exist yet.

How can I create a folder, commit transition, and then create a subfolder?

howkymike
Alfresco Developer
1 ACCEPTED ANSWER

Considering you have root folder known, i would follow steps as (no external transaction handling needed):

1- Using the root folder name, get the path of the root folder.

2- Using the TMDQ as suggested, get the root folder node ref. 

3- If subfolder  (considering an input  are separated by multiple paths (like your mkdir -p case), you can split the path and iterate each subfolder and create subfolder within rootfolder and their sub folders.

3- If subfolder is not separated by path, you can directly create the subfoler within root folder.

Here is an example:

String folderPathQuery  = getFolderPathQuery(rootFolderName, siteShortName); //Change the query accordingly if not using sites
List<NodeRef> selectedNodes = searchService.selectNodes(nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE),
		folderPathQuery, null, namespaceService, false);
if (selectedNodes != null && !selectedNodes.isEmpty()) {
	NodeRef rootFolderRef = selectedNodes.get(0); 
	if(rootFolderRef != null && fileFolderService.exists(rootFolderRef)) {
		if(subFolderName.contains("/")) {
			String[] pathTokens = subFolderName.split("/");
			NodeRef subRootNodeRef = rootFolderRef;
			for (String subFolder : pathTokens) {
				subRootNodeRef = fileFolderService.create(subRootNodeRef, subFolder, ContentModel.TYPE_FOLDER).getNodeRef();
			}
		} else {
			fileFolderService.create(rootFolderRef, subFolderName, ContentModel.TYPE_FOLDER);
		}
	} else {
		// handle and notify message as needed. ROOT FOLDR NOT FOUND
	}
} else {
	// handle and notify message as needed.
}


private String getFolderPathQuery(String folderPath, String siteShortName) {
	StringBuilder queryBuilder = new StringBuilder("/app:company_home/st:sites/");
	queryBuilder.append("cm:").append(ISO9075.encode(siteShortName))
			.append("/cm:documentLibrary");
	if (null != folderPath && !folderPath.isEmpty()) {
		String[] pathTokens = folderPath.split("/");
		if (!"Document Library".equals(folderPath)) {
			for (String pathToken : pathTokens) {
				queryBuilder.append("/cm:").append(ISO9075.encode(pathToken));
			}
		}
	}
	return queryBuilder.toString();
}
~Abhinav
(ACSCE, AWS SAA, Azure Admin)

View answer in original post

6 REPLIES 6

sanjaybandhaniya
Elite Collaborator
Elite Collaborator

Can you provide detail how you are creating?Some code snippet.

If you are using lucene to search created node then it will take some time because indexing will take time for making content searchable.

You can use Transactional metadata query  

Hi @sanjaybandhniya 

Sure, I do.  The method should create a directory structure given a path (similar to mkdir -p command). I used Lucene (is there another way if I don't have noderef, only the human-readable-path?).

    private static void createDirectoryStructure(String parentPath, String childName) {
		StoreRef storeRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "SpacesStore");
		ResultSet rs = searchService.query(storeRef, SearchService.LANGUAGE_LUCENE,
				"PATH:\"" + parentPath + "\"");
		if (rs.length() == 0) {
			logger.warn("Didn't find the parent path, trying to create it...");
			createParentPath(parentPath);  // very similar code
			rs = searchService.query(storeRef, SearchService.LANGUAGE_LUCENE,
					"PATH:\"" + parentPath + "\"");
			if(rs.length() == 0) {
				throw new AlfrescoRuntimeException("Parent still does not exist!");
			}
		}
		NodeRef parentRef = rs.getNodeRef(0);
.... }

(I modified the code a bit to make it more readable)

@kaynezhang I mean Java (foundation?) API, not remote. Getting nodeService is not a problem at all, I'm just trying to create a node, and then create another node inside the previously created one.

howkymike
Alfresco Developer

Considering you have root folder known, i would follow steps as (no external transaction handling needed):

1- Using the root folder name, get the path of the root folder.

2- Using the TMDQ as suggested, get the root folder node ref. 

3- If subfolder  (considering an input  are separated by multiple paths (like your mkdir -p case), you can split the path and iterate each subfolder and create subfolder within rootfolder and their sub folders.

3- If subfolder is not separated by path, you can directly create the subfoler within root folder.

Here is an example:

String folderPathQuery  = getFolderPathQuery(rootFolderName, siteShortName); //Change the query accordingly if not using sites
List<NodeRef> selectedNodes = searchService.selectNodes(nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE),
		folderPathQuery, null, namespaceService, false);
if (selectedNodes != null && !selectedNodes.isEmpty()) {
	NodeRef rootFolderRef = selectedNodes.get(0); 
	if(rootFolderRef != null && fileFolderService.exists(rootFolderRef)) {
		if(subFolderName.contains("/")) {
			String[] pathTokens = subFolderName.split("/");
			NodeRef subRootNodeRef = rootFolderRef;
			for (String subFolder : pathTokens) {
				subRootNodeRef = fileFolderService.create(subRootNodeRef, subFolder, ContentModel.TYPE_FOLDER).getNodeRef();
			}
		} else {
			fileFolderService.create(rootFolderRef, subFolderName, ContentModel.TYPE_FOLDER);
		}
	} else {
		// handle and notify message as needed. ROOT FOLDR NOT FOUND
	}
} else {
	// handle and notify message as needed.
}


private String getFolderPathQuery(String folderPath, String siteShortName) {
	StringBuilder queryBuilder = new StringBuilder("/app:company_home/st:sites/");
	queryBuilder.append("cm:").append(ISO9075.encode(siteShortName))
			.append("/cm:documentLibrary");
	if (null != folderPath && !folderPath.isEmpty()) {
		String[] pathTokens = folderPath.split("/");
		if (!"Document Library".equals(folderPath)) {
			for (String pathToken : pathTokens) {
				queryBuilder.append("/cm:").append(ISO9075.encode(pathToken));
			}
		}
	}
	return queryBuilder.toString();
}
~Abhinav
(ACSCE, AWS SAA, Azure Admin)

Well, that is even more than I wanted. Thank you very much.

howkymike
Alfresco Developer

@upforsin Glad to hear that.

~Abhinav
(ACSCE, AWS SAA, Azure Admin)

kaynezhang
World-Class Innovator
World-Class Innovator

By java api do you mean the embeded java foundation api or remote java api ?
If you mean java fondation api ,you shoud inject the capitalized bean name NodeService into your bean,like following

<property name="nodeService" ref="NodeService"/>


If you mean  remote java pai ,you can try createPath method of org.apache.chemistry.opencmis.client.api.Session interface