Alfresco - How to get all Child that are not folders Alfresco (Java) - java

i want to retrieve all the file contained in a folder in Java through the getChildAssocs(NodeRef nodeRef, Set childNodeTypeQNames) method...
I want to use it in this way:
Set<QName> types = new HashSet<QName>(1, 1.0f);
types.add(ContentModel. TYPE_CONTENT);
List<ChildAssociationRef> filesFolderList = nodeService.getChildAssocs(parentNodeRef, types);
for (ChildAssociationRef file : filesFolderList) {
NodeRef childRef = file.getChildRef();
if(!nodeService.hasAspect(childRef, MyModel.MY_ASPECT)
&& !nodeService.hasAspect(childRef, MyModel.MY_SECOND_ASPECT)
&& !childRef.equals(actualDocumentRef)){
String fileName = (String) nodeService.getProperty(childRef, ContentModel.PROP_NAME);
}
}
It returns me 0 results neither files nor folders...what i'm wrong?!
Thanks in advance!

The problem is this bit here:
types.add(ContentModel. TYPE_CONTENT);
List<ChildAssociationRef> filesFolderList =
nodeService.getChildAssocs(parentNodeRef, types);
A call to getChildAssocs can optionally filter by the association type. However, the type you're passing in is a Content Type, not an Association Type. Association types are things like ContentModel.ASSOC_CONTAINS
If you change that first like to be ContentModel.ASSOC_CONTAINS then you would get all children (content, folders and custom types), and within that you could check the type (or better use the Dictionary Service to check types or subtypes)
Otherwise, to easily get all of the children of a node with control of if it has files or folders in, use FileFolderService.list. Simply set the files boolean to true and the folder boolean to false, and you'll get only content items and no folders

Related

XMLUnit - compare xml and ignore few tags based on a condition

I have couple of xmls which needs to be compared with different set of similar xml and while comparing i need to ignore tags based on a condition, for example
personal.xml - ignore fullname
address.xml - igone zipcode
contact.xml - ignore homephone
here is the code
Diff documentDiff=DiffBuilder
.compare(actualxmlfile)
.withTest(expectedxmlfile)
.withNodeFilter(node -> !node.getNodeName().equals("FullName"))
.ignoreWhitespace()
.build();
How can i add conditions at " .withNodeFilter(node -> !node.getNodeName().equals("FullName")) " or is there a smarter way to do this
You can join multiple conditions together using "and" (&&):
private static void doDemo1(File actual, File expected) {
Diff docDiff = DiffBuilder
.compare(actual)
.withTest(expected)
.withNodeFilter(
node -> !node.getNodeName().equals("FullName")
&& !node.getNodeName().equals("ZipCode")
&& !node.getNodeName().equals("HomePhone")
)
.ignoreWhitespace()
.build();
System.out.println(docDiff.toString());
}
If you want to keep your builder tidy, you can move the node filter to a separate method:
private static void doDemo2(File actual, File expected) {
Diff docDiff = DiffBuilder
.compare(actual)
.withTest(expected)
.withNodeFilter(node -> testNode(node))
.ignoreWhitespace()
.build();
System.out.println(docDiff.toString());
}
private static boolean testNode(Node node) {
return !node.getNodeName().equals("FullName")
&& !node.getNodeName().equals("ZipCode")
&& !node.getNodeName().equals("HomePhone");
}
The risk with this is you may have element names which appear in more than one type of file - where that node needs to be filtered from one type of file, but not any others.
In this case, you would also need to take into account the type of file you are handling. For example, you can use the file names (if they follow a suitable naming convention) or use the root elements (assuming they are different) - such as <Personal>, <Address>, <Contact> - or whatever they are, in your case.
However, if you need to distinguish between XML file types, for this reason, you may be better off using that information to have separate DiffBuilder objects, with different filters. That may result in clearer code.
I had provided the separate method in the below link for !node.getNodeName().equals("FullName")(which you are using in your code), I think by using that separate method you can just pass the array of nodes which you want to ignore and see the results. And incase you wish to add any other conditions based on your requirement, you can try and play in this method.
https://stackoverflow.com/a/68099435/13451711

Parse a single POJO from multiple YAML documents representing different classes

I want to use a single YAML file which contains several different objects - for different applications. I need to fetch one object to get an instance of MyClass1, ignoring the rest of docs for MyClass2, MyClass3, etc. Some sort of selective de-serializing: now this class, then that one... The structure of MyClass2, MyClass3 is totally unknown to the application working with MyClass1. The file is always a valid YAML, of course.
The YAML may be of any structure we need to implement such a multi-class container. The preferred parsing tool is snakeyaml.
Is it sensible? How can I ignore all but one object?
UPD: replaced all "document" with "object". I think we have to speak about the single YAML document containing several objects of different structure. More of it, the parser knows exactly only 1 structure and wants to ignore the rest.
UDP2: I think it is impossible with snakeyaml. We have to read all objects anyway - and select the needed one later. But maybe I'm wrong.
UPD2: sample config file
---
-
exportConfiguration781:
attachmentFieldName: "name"
baseSftpInboxPath: /home/user/somedir/
somebool: false
days: 9999
expected:
- ABC w/o quotes
- "Cat ABC"
- "Some string"
dateFormat: yyyy-MMdd-HHmm
user: someuser
-
anotherConfiguration:
k1: v1
k2:
- v21
- v22
This is definitely possible with SnakeYAML, albeit not trivial. Here's a general rundown what you need to do:
First, let's have a look what loading with SnakeYAML does. Here's the important part of the YAML class:
private Object loadFromReader(StreamReader sreader, Class<?> type) {
Composer composer = new Composer(new ParserImpl(sreader), resolver, loadingConfig);
constructor.setComposer(composer);
return constructor.getSingleData(type);
}
The composer parses YAML input into Nodes. To do that, it doesn't need any knowledge about the structure of your classes, since every node is either a ScalarNode, a SequenceNode or a MappingNode and they just represent the YAML structure.
The constructor takes a root node generated by the composer and generates native POJOs from it. So what you want to do is to throw away parts of the node graph before they reach the constructor.
The easiest way to do that is probably to derive from Composer and override two methods like this:
public class MyComposer extends Composer {
private final int objIndex;
public MyComposer(Parser parser, Resolver resolver, int objIndex) {
super(parser, resolver);
this.objIndex = objIndex;
}
public MyComposer(Parser parser, Resolver resolver, LoaderOptions loadingConfig, int objIndex) {
super(parser, resolver, loadingConfig);
this.objIndex = objIndex;
}
#Override
public Node getNode() {
return strip(super.getNode());
}
private Node strip(Node input) {
return ((SequenceNode)input).getValue().get(objIndex);
}
}
The strip implementation is just an example. In this case, I assumed your YAML looks like this (object content is arbitrary):
- {first: obj}
- {second: obj}
- {third: obj}
And you simply select the object you actually want to deserialize by its index in the sequence. But you can also have something more complex like a searching algorithm.
Now that you have your own composer, you can do
Constructor constructor = new Constructor();
// assuming we want to get the object at index 1 (i.e. second object)
Composer composer = new MyComposer(new ParserImpl(sreader), new Resolver(), 1);
constructor.setComposer(composer);
MyObject result = (MyObject)constructor.getSingleData(MyObject.class);
The answer of #flyx was very helpful for me, opening the way to workaround the library (in our case - snakeyaml) limitations by overriding some methods. Thanks a lot! It's quite possible there is a final solution in it - but not now. Besides, the simple solution below is robust and should be considered even if we'd found the complete library-intruding solution.
I've decided to solve the task by double distilling, sorry, processing the configuration file. Imagine the latter consisting of several parts and every part is marked by the unique token-delimiter. For the sake of keeping the YAML-likenes, it may be
---
#this is a unique key for the configuration A
<some YAML document>
---
#this is another key for the configuration B
<some YAML document
The first pass is pre-processing. For the given String fileString and String key (and DELIMITER = "\n---\n". for example) we select a substring with the key-defined configuration:
int begIndex;
do {
begIndex= fileString.indexOf(DELIMITER);
if (begIndex == -1) {
break;
}
if (fileString.startsWith(DELIMITER + key, begIndex)) {
fileString = fileString.substring(begIndex + DELIMITER.length() + key.length());
break;
}
// spoil alien delimiter and repeat search
fileString = fileString.replaceFirst(DELIMITER, " ");
} while (true);
int endIndex = fileString.indexOf(DELIMITER);
if (endIndex != -1) {
fileString = fileString.substring(0, endIndex);
}
Now we feed the fileString to the simple YAML parsing
ExportConfiguration configuration = new Yaml(new Constructor(ExportConfiguration.class))
.loadAs(fileString, ExportConfiguration.class);
This time we have a single document that must co-respond to the ExportConfiguration class.
Note 1: The structure and even the very content of the rest of configuration file plays absolutely no role. This was the main idea, to get independent configurations in a single file
Note 2: the rest of configurations may be JSON or XML or whatever. We have a method-preprocessor that returns a String configuration - and the next processor parses it properly.

How to get private vendor attribute tag in C_FIND from pixelmed?

i'm trying to read a private vendor tag from a dicom server.
The only tags I'm able to read successfully are the standard DICOM tagFromNames
the tag is 2001,100b, and in my example set of files they definitely have that entry in their header
here is the code for calling the CFIND request
SpecificCharacterSet specificCharacterSet = new SpecificCharacterSet((String[])null);
AttributeList identifier = new AttributeList();
//specify attributes to retrieve and pass in any search criteria
//query root of "study" to retrieve studies
studies.removeAllElements();
identifier.putNewAttribute(TagFromName.QueryRetrieveLevel).addValue("STUDY");
identifier.putNewAttribute(TagFromName.PatientName,specificCharacterSet).addValue("*");
identifier.putNewAttribute(TagFromName.PatientID,specificCharacterSet);
identifier.putNewAttribute(TagFromName.StudyID);
identifier.putNewAttribute(TagFromName.PatientAge);
identifier.putNewAttribute(TagFromName.PatientSex);
identifier.putNewAttribute(TagFromName.ModalitiesInStudy);
identifier.putNewAttribute(TagFromName.AccessionNumber);
identifier.putNewAttribute(TagFromName.StudyInstanceUID);
identifier.putNewAttribute(TagFromName.StudyDescription);
identifier.putNewAttribute(TagFromName.StudyDate).addValue(date);
identifier.putNewAttribute(TagFromName.StudyTime);
AttributeTag at = new com.pixelmed.dicom.AttributeTag("0x2001,0x100b");
identifier.putNewAttribute(at);
IdentifierHandler ih = new IdentifierHandler(){
#Override
public void doSomethingWithIdentifier(AttributeList id) throws DicomException {
studies.add(new Study(id, reportfolder));
//Attempt to read private dicom tag from received identifier
System.out.println(id.get(at));
}
};
new FindSOPClassSCU(serv.getAddress(),serv.getPort(), serv.getAetitle(), "ISPReporter",SOPClass.StudyRootQueryRetrieveInformationModelFind,identifier,ih);
However, my output from the query, receives 7 identifiers that match for the date however when I try to read the 2001,100b tag, the error I get reads:
DicomException: No such data element as (0x2001,0x100b) in dictionary
if I use this line instead
identifier.put(new com.pixelmed.dicom.TextAttribute(at) {
public int getMaximumLengthOfEntireValue() { return 20; }
});
Then I get:
null
null
null
null
null
null
null
(null for each identifier returned)
Two things (second one moot because this won't work anyway because of the first):
C-FIND SCPs query against a database of a subset of data elements previously extracted from the DICOM image header and indexed - only a (small) subset of data elements present in images are actually indexed, as described; the standard requires very few in the Query Information Models, and the IHE Scheduled Workflow (SWF) profile a few more (Query Images Transaction Table 4.14-1; implementers could index every data element (or at least every standard data elements), but this is rarely done (PixelMed doesn't, though I have consider doing it adaptively as data elements are encountered now that hsqldb supports adding columns; NoSQL based implementations might find this easier)
When you encode a private data element, whether it be in a query identifier/response, or in an image header, you need to include its creator; i.e., for (2001,100b), you need to include (2001,0010); otherwise the creator of the private data element is not specified.
David

Removing redundant folder paths from a list

I have the following list which contains a series of folder paths. Some of these are redundant so I need to remove them and the final list should only contain the bottom level folders:
Initial list:
var paths = new List<string>
{
"Pavements/",
"Pavements/2019_05/",
"Pavements/2019_06/",
"Pavements/2019_06/A/",
"Roads/",
"Roads/2019_06/"
};
The final List should look like:
paths =
{
"Pavements/2019_05/",
"Pavements/2019_06/A/",
"Roads/2019_06/"
};
i.e. all the upper level folder paths have been removed.
Does anyone know how I can achieve this? I have a feeling I need a recursive method but am unsure how to go about it. I am using C# but answer in java or something similar is ok.
Thanks.
One way to do this is with a linq query that compares each item to all the other items and returns the item only if none of the others begin with it:
paths = paths.Where(path => !paths.Any(p => p != path && p.StartsWith(path))).ToList();

How to create a blankNode Resource in Jena [duplicate]

I'm trying to populate a Jena ontology model with an existing set of triples, some of which contain blank nodes. I want to maintain these blank nodes inside this new model faithfully but I can't work out a way of adding them into a Jena model.
I have been using:
Statement s = ResourceFactory.createStatement(subject, predicate, object);
To add new statements to the model:
private OntModel model = ModelFactory.createOntologyModel();
model.add(s);
but this only allows for certain types as subject, predicate, and object; Resource subject, Property predicate, RDFNode object. None of these types allow for the adding of a blanknode as subject or object such as through:
Node subject = NodeFactory.createBlankNode(subjectValue);
Any suggestions? I've tried just using the blanknodes as resources and creating a Resource object but that breaks everything as they become classes then and not blank nodes.
Any help would be much appreciated, been pulling my hair out with this.
well, if you already have an existing set of triples you can easily read them from file by using:
OntModel model = ModelFactory.createOntologyModel();
model.read(new FileInputStream("data.ttl"), null, "TTL");
this will take care of blank nodes, see the jena documentation
you can create a blank node by hand like this:
Resource subject = model.createResource("s");
Property predicate = model.createProperty("p");
Resource object = model.createResource();
model.add(subject, predicate, object);
which will result in something like:
[s, p, aad22737-ce84-4564-a9c5-9bdfd49b55de]

Categories

Resources