Fetch absolute or relative path using file object in IBM filenet - filenet-p8

String mySQLString = "select * from document where documentTitle like '%test%' ";
SearchSQL sql = new SearchSQL(mySQLString);
IndependentObjectSet s = search.fetchObjects(sql, 10, null, true);
Document doc;
PageIterator iterator = s.pageIterator();
iterator.nextPage();
for (Object object : iterator.getCurrentPage()) {
doc = (Document) object;
Properties properties = doc.getProperties();
//I am trying to get an absolute or relative path here for every document.
// for eg: /objectstorename/foldername/filename like this.
}
I have tried searching propeties and class descriptions in document . but can't able to find the path. ?

To do it all in one single query (as you are trying to do in your code) you can create a join with the ReferentialContainmentRelationship table. The property Head of this table points to the document, the property Tail points to the folder the document is filled in and the property ContainmentName is the name the document has in the folder. Use the following code to construct the document path:
SearchSQL searchSQL = new SearchSQL("SELECT R.ContainmentName, R.Tail, D.This FROM Document AS D WITH INCLUDESUBCLASSES INNER JOIN ReferentialContainmentRelationship AS R WITH INCLUDESUBCLASSES ON D.This = R.Head WHERE DocumentTitle like '%test%'");
SearchScope searchScope = new SearchScope(objectStore);
RepositoryRowSet objects = searchScope.fetchRows(searchSQL, null, null, null);
Iterator<RepositoryRow> iterator = objects.iterator();
while (iterator.hasNext()) {
RepositoryRow repositoryRow = iterator.next();
Properties properties = repositoryRow.getProperties();
Folder folder = (Folder) properties.get("Tail").getEngineObjectValue();
String containmentName = properties.get("ContainmentName").getStringValue();
System.out.println(folder.get_PathName() + "/" + containmentName);
}
Paths constructed this way can also be used to fetch the object from the object store. The query code can be optimized by using a property filter as the third argument of the fetchRows() method. Don't know how this behaves if the document is filed in multiple folders.

I suggest you explore the "Creating DynamicReferentialContainmentRelationship Objects" section of FileNet documentation:
https://www.ibm.com/support/knowledgecenter/SSNW2F_5.5.0/com.ibm.p8.ce.dev.ce.doc/containment_procedures.htm#containment_procedures__fldr_creating_a_drcr
A FileNet Ddocument can be assigned to multiple Folders, so you can have several logical "Paths" for a given document.
At end, you should get something like "Folder.get_PathName() + DynamicReferentialContainmentRelationship.get_Name()" to display the full pathname.
As described by samples in FileNet documentation, a relationship object (e.g. DynamicReferentialContainmentRelationship) controls the relation of document/folder:
myRelationshipObject.set_Head(myDocument);
myRelationshipObject.set_Tail(myFolder);
Also, keep in mind that a FileNet Document can be also a "unfiled" document, so there is no actual "pathname" or folder "relationship" to be retrieved.

tl;dr from FileNet Content Engine - Database Table for Physical path
Documents are stored among the directories at the leaf level using a hashing algorithm to evenly distribute files among these leaf directories.

Related

Exception: while creating work item in TFS

I am using WorkItemTrackingHttpClient class to create work item in TFS,
I am already passing AreaId and ItrationId while creating workItem
patchDocument.Add(new JsonPatchOperation
{
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Path = "/Fields/System.AreaId",
Value = rootAreaNode.Id
});
patchDocument.Add(new JsonPatchOperation
{
Operation = Microsoft.VisualStudio.Services.WebApi.Patch.Operation.Add,
Path = "/Fields/System.IterationId",
Value = rootIterationsNode.Id
});
WorkItem result = workItemTrackingHttpClient.CreateWorkItemAsync(patchDocument, teamProjectReference.Name, "Task").Result;
But I am facing exception as :
New work item updates must specify Area and Iteration node ids. Parameter name: workItemUpdates
There are no /Fields/System.AreaId or /Fields/System.AreaId fields. You can only use System.AreaPath and System.IterationPath. Check the example below:
"System.AreaPath": "TestCase\\windows app",
"System.IterationPath": "TestCase\\Release 1\\Sprint 1",
Try to use "/Fields/System.AreaPath" and "/fields/System.IterationPath" with full path instead of "/Fields/System.AreaId" and "/Fields/System.IterationId". Because AreaId and IterationId based on System.AreaPath and System.IterationPath values.
Values for area and iteration paths you may find on work item form. You may create new work item and get default values:

How to recover deleted data in alfresco share through java?

I am new to alfresco community and i am using alfresco community for Document Management System.
Now my problem is i have deleted one document like as shown below and now i want to recover that data into same in which folder that exist before deletion
Document document = (Document) session.getObjectByPath(filePath);
document.delete();
Please any body help me...
You can use this:
nodeArchiveService.restoreArchivedNode(NodeRef archivedNodeRef)
To get the archivedNodeRef you can either search it in alfresco database (bad) find it using one of it property under the archive://SpacesStore
new NodeRef(archiveRoot.getStoreRef(),(String)node.get("UUID"))
http://dev.alfresco.com/resource/docs/java/org/alfresco/repo/node/archive/NodeArchiveService.html
If you have the trashcanCleaner up and running, your trashcan is protected 14d by default after that, the node is removed.
An sql query to get node from archive store:
String sql = "SELECT n.id, n.UUID "
+ "FROM alf_node n, alf_store s "
+ "WHERE n.store_id = s.id "
+ "AND s.protocol = 'archive' "
+ "AND n.AUDIT_MODIFIED is not null "
+ "ORDER BY n.id asc ";
Add a few criteria in the where clause on the ALF_NODE_PROPERTIES table and you are set.
You can use the java api VersionService(restore), if you know the deleted node.
http://localhost:8080/alfresco/api/-default-/public/alfresco/versions/1/deleted-nodes/{id}/restore
restore
#Auditable(parameters={
"nodeRef",
"parentNodeRef",
"assocTypeQName",
"assocQName"
})
NodeRef restore(NodeRef nodeRef,
NodeRef parentNodeRef,
QName assocTypeQName,
QName assocQName)
By default a deep restore is performed.
Parameters:
nodeRef - the node reference to a node that no longer exists in the store
parentNodeRef - the new parent of the restored node
assocTypeQName - the assoc type qname
assocQName - the assoc qname
Returns:
the newly restored node reference
Also, if your node had "sys:temporary" aspect applied, then you are out of luck, that's the equivalent of "shift + delete" in Windows. You could still get it's content from the deleted store on disk, though.
Take a look at this blog post to understand the complete process:
https://blyx.com/2014/08/18/understanding-alfresco-content-deletion/

How do I add a namespace to an msxml DOMDocument?

How do I add a schema to an IXMLDOMDocument?
For example, I want to generate the XML:
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="Frob" Target="Grob"/>
</Relationships>
I can construct the DOMDocument60 object (pseudo-code):
DOMDocument60 doc = new DOMDocument60();
IXMLDOMElement relationships = doc.appendChild(doc.createElement("Relationships"));
IXMLDOMElement relationship = relationships.appendChild(doc.createElement("Relationship"));
relationship.setAttribute("Id", "rId1");
relationship.setAttribute("Type", "Frob");
relationship.setAttribute("Target", "Grob");
Now comes the question of how to add the namespace.
How to add the namespace?
If I do the obvious solution, setting an attribute on the Relationships node called xmlns:
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
through something like:
relationships.setAttribute("xmlns",
"http://schemas.openxmlformats.org/package/2006/relationships");
When the document is saved, it causes the resulting xml to be wrong:
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="Frob" Target="Grob" xmlns=""/>
</Relationships>
It places empty xmlns attributes on every other element. In this little test document it only misapplies the xmlns to one element. In the real world there are dozens, or a few million other elements with an empty xmlns attribute.
namespaceURI property
I tried setting the namespaceURI property of the Relationships element:
relationshps.namespaceURI := "http://schemas.openxmlformats.org/package/2006/relationships";
but the property is read-only.
schemas Property
The document does have a schemas property, which gets or sets an XMLSchemaCache object. But it requires an actual schema document. E.g. trying to just set a schema doesn't work:
schemas = new XMLSchemaCache60();
schemas.add('', 'http://schemas.openxmlformats.org/spreadsheetml/2006/main');
doc.schemas := schemas;
But that tries to actually load the schema url, rather than not loading the schema because it isn't a URI.
Perhaps I have to randomly try other things:
schemas = new XMLSchemaCache60();
schemas.add('http://schemas.openxmlformats.org/spreadsheetml/2006/main', null);
doc.schemas := schemas;
But that causes no xmlns to be emitted.
Rather than trying to build an XML document the correct way, I could always use a StringBuilder to build the XML manually, and then have parse it into an XML Document object.
But I'd rather do it the right way.
The trick is to realize the W3C DOM Level 2 and 3 have a method createElementNS đź•—:
Creates an element with the specified namespace URI and qualified name.
Syntax
element = document.createElementNS(namespaceURI, qualifiedName);
However MSXML 6 only supports DOM Level 1.
Fortunately, W3C DOM Level 1 did have a method to create an element with a namespace: createNodeđź•—:
Creates a node using the supplied type, name, and namespace.
HRESULT createNode(VARIANT Type, BSTR name, BSTR namespaceURI, out IXMLDOMNode node);
Thus my solution is that i have to change:
relationships: IXMLDOMElement = doc.createElement("Relationships");
into:
const NODE_ELEMENT: Integer = 1;
const ns: string = "http://schemas.openxmlformats.org/package/2006/relationships";
relationships: IXMLDOMElement = doc.createNode(NODE_ELEMENT, "Relationships", namespace);
A sucky part is that every element must be created in that namespace:
function AddElementNS(IXMLDOMNode parentNode, String tagName, String namespaceURI): IXMLDOMElement;
{
doc: IXMLDOMDocument = parentNode as IXMLDOMDocument;
if (doc == null)
doc = parentNode.ownerDocument;
if (namespaceURI <> "")
Result = doc.createNode(NODE_ELEMENT, tagName, namespaceURI)
else
Result = doc.createElement(tagName);
parentNode.appendChild(Result);
}
relationships: IXMLDOMElement = AddElementNS(doc, "Relationships", ns);
relationship: IXMLDOMElement = AddElementNS(relationships, "Relationship", ns);
relationship.setAttribute("Id", "rId1");
relationship.setAttribute("Type", "Frob");
relationship.setAttribute("Target", "Grob");
Bonus Reading
Creating XML with namespaces with Javascript and MSXML đź•—

How to find a template in Alfresco with OpenCMIS from Spring application?

I am working in a Spring 3.1 application and I need to find a String template document located in Alfresco's repository. I can already create a file in alfresco with OpenCMIS, but I couldn't figure out how to find a template, so if anyone knows how to do it or point me an example, please let me know, thanks in advance!
There are a number of options you can use. First of all, you need to have a criteria that uniquely identifies your document. Here below I'll show some, hopefully your case falls in one of them or they will inspire you towards a proper solution. The following uses pseudo code, please have a look to the OpenCMIS dev guide for working with the Java client API.
BY ID
Once you create a Document via CMIS, you get the unique ID of it that you can store in your application for later retrieval.
Map<String, Object> templateProperties = createDocumentProperties();
Folder folder = getTemplatesFolder();
ObjectId templateId = createTemplateIn(folder);
storeTemplateId(templateId.getId(), templateProperties); // persist the ID
...
// later on
...
String id = getTemplateId(); // retrieve the ID
Session session = openCMISSession();
Document template = (Document)session.getObject(id);
BY PATH
Similar to the previous example, you will have to take note of where you stored the document instead of its ID, or having a way to construct the path by hand.
String path = getTemplatePath(); // either recover it from DB or construct a path
Document template = (Document)session.getObjectByPath(path);
BY PROPERTY VALUE
Let's say you can use a specific metadata field on a template Document that allows you to easily retrieve it afterwards (e.g. you created some specific Alfresco metadata model for your use case).
String meta = TemplateProperties.TEMPLATE_ID; // e.g. my:templateId
String type = TemplateProperties.TEMPLATE_TYPE; // e.g. my:template
String templateMeta = "TEMPLATE1";
Map<String, Object> templateProperties = createDocumentProperties();
templateProperties.put(meta, templateMeta);
templateProperties.put(PropertyIds.OBJECT_TYPE_ID, type);
createTemplate(templateProperties);
...
// later on
...
String type = TemplateProperties.TEMPLATE_TYPE; // e.g. my:template
String meta = TemplateProperties.TEMPLATE_ID;
String tplId = "TEMPLATE1";
String query = String.format("SELECT * FROM % WHERE % = '%'", type, meta, tplId);
ItemIterable<QueryResult> i = session.query(query, false);
QueryResult qr = i.iterator().next(); // let's assume we have one single match
String templateId = qr.getPropertyByQueryName("cmis:objectId").getFirstValue()
Document template = (Document)session.getObject(templateId);
BY QUERY
The previous approach is not really tied to search by property name, and can be easily extended to use any kind of query that identifies your templates. Have a look at the Alfresco page on its CMIS query language implementation details to learn more ways of querying the repository.

EntityRef<T> Issues, not returning value from Lookup List

Ok, I'll explain this as much as I can...
I've got a Site Lookup Column called EEE Content Type which refers to the Site Content Item Type Types List.
Now in my custom list (which inherits from Item), I am referencing that column, and it comes up in sharepoint fine and displays the lookup values.
The issue is when I'm using SPMetal.exe to generate the types it whinges about "Key isn't present in the dictionary" and fails. So I remove the definition of the column in the parameters.xml file for SPMetal, and re-generate the classes.
Now I've manually added the property and association.
private EntityRef<SiteContentItemTypeItem> _eeeContentType;
[Association(Name = "EEE_x0020_Content_x0020_Type", Storage = "_eeeContentType", MultivalueType = AssociationType.Single, List = "Site Content Item Types")]
public SiteContentItemTypeItem EEEContentType
{
get
{
return this._eeeContentType.GetEntity();
}
set
{
this._eeeContentType.SetEntity(value);
}
}
SiteContentItemTypeItem inherits from Item so its class is empty.
But when I load the custom list I have created, i get the first entry and the EEEContentType field is null...
using (IntranetDataContext context = new IntranetDataContext("http://siteurl")) {
context.ObjectTrackingEnabled = false;
EntityList<SiteContentItem> alerts = context.GetList<SiteContentItem>("User Alerts");
SiteContentItem alert = (from tmpalert in alerts where tmpalert.Id == 1 select tmpalert).First();
SiteContentItemTypeItem contentType = alert.EEEContentType;
}
I'm all out of ideas...
Should the List value in the Association attribute be that of a collection in the class or is it refering to the actual lookup list name?
Figured it out...
Stupid of me to "assume" when creating site lookup columns via code that SharePoint would use the proper naming conventions for FieldNames with spaces.
So the fieldName was correct, its InternalName wasn't the one I was expecting. And as sharepoint linq requires the internal names, it was throwing internal exceptions in the Linq.SharePoint DLL.

Resources