I have seen to similar questions here on this topic but none really helped me grasp the steps to solve this.
Given a queue, and a rootNode , how can I iterate through it? I understand first I have to enqueue the node I start with, but I am confused on how to implement the next() method. Also it has to be breadth-first traversal.
for the next() method I have this:
public File next(){
while(the peek() is a directory ("parent"){
use lists() to return the array of files
iterate thru those and add to queue
remove the first node
}
return peek();
It seems to work if I have a single file directory.
Also, I am looking for a pseucode not the code. I am just confused on whether I am on the right path or not.
If, for some reason, you insist on non recursive solution, although FileVisitor is definitely way to go with this in Java, breadth first search can be implemented non recursively.
This is general definition, marking is used to avoid circular referencing although you wont have that in this case:
Enqueue root of directories and mark root as discovered
while queue is not empty
dequeue and process element
discover adjacent edges - children
for every child, if not marked already and is a directory, mark and queue
To get children you need: String[] directories = file.list().
To make sure you are queuing directories and not files
call file.isDirectory() and enqueue only directories.
You do not need to do marking before queuing as you won't have circular reference between directories.
Edit:
Here is recursive breadth first search, you can modify it into iterative with the pseudo code above.
import java.io.File;
import java.util.LinkedList;
import java.util.Queue;
public class BFSRecursive {
public static void main(String[] args) {
File file = new File("D:/Tomcat");
Queue<File> files = new LinkedList<>();
files.add(file);
bfs(files);
}
private static void bfs(Queue<File> files) {
if (files.isEmpty())
return;
File file = files.poll();
System.out.println(file.getName());
String[] directories = file.list();
for(String child: directories) {
File childFile = new File(file.getAbsolutePath() +"/"+ child);
if (childFile.isDirectory())
files.add(childFile);
}
bfs(files);
}
}
Related
everyone. I'm new in working with aem. I'm using aem 6.4. My task is to programmatically sort the order of the contents of a cq:project in aem depending on the content of a JSON file.
The content of the JSON file should be set as the initial child instead of the children sorted by their creation date.
This is the current structure of my cq:page. If the child2 is the one indicated in the JSON file, it should be the first one to be displayed. The content of the JSON file is just the name of one child so even though there are 10 children, the content of the JSON file should always be the first one in the list.
I've spent hours researching on how I can implement this although I still can't find any solution. Any insights on how should I create this? Thanks!
As I understand it, you want a way to order a named child of a cq:Page to be first in the list.
This is possible because cq:Page is an orderable node. This would not be possible otherwise. you chan check any nodetype in CRX Explorer.
I think adding the bit about JSON complicates the question. You just need a simple method such as the following:
private void orderAsFirstChild(String childName, Node parentNode) throws RepositoryException {
if (parentNode.hasNode(childName)) {
// find current first child name
String firstChildName = Optional.ofNullable(parentNode.getNodes())
.map(NodeIterator::nextNode)
.map(node -> {
try {
node.getName();
} catch (RepositoryException e) {
e.printStackTrace();
}
return (String) null;
}) //
.orElse(null);
parentNode.orderBefore(childName, firstChildName);
}
}
You should probably clean this up a little, but this is the general idea using Node#orderBefore
This may helps -
Get the children from the parent node.(you will get 'iterator' convert it to list here-Convert Iterator to ArrayList)
Delete all child nodes now. And keep the back up of above list.
iterate through the list , identify the node which you want place first(by title or some other property) add that to a separate set(LinkedHashSet- to maintain order).
Now add the remaining items/nodes in the same order after your specific node in the above set.(you may need to iterate through again)
Now this Set has nodes/Resources in the order which you want, iterate , create nodes and save your changes.
I have implemented https://blogs.oracle.com/geertjan/file-browser to show only folders (changed == in accept() to !=). However, no matter what I have done it only calls the FileFilterNodeChildren for the first level, the children of the root node. So what I get is the folders of the root node (the directory I want) but it show ALL files and folders below this level. I have put in statements that verify that the filter function is only called for the first level.
What do I need to do to filter the children of the first level and below?
Inside of createNodes() you need to wrap the child nodes with instances of FileFilterNode. Here is a revised version of createNodes():
#Override
protected Node[] createNodes(Node object) {
List<Node> result = new ArrayList<Node>();
for (Node node : super.createNodes(object)) {
if (accept(node)) {
// This is the only changed line
result.add(new FileFilterNode(node));
}
}
return result.toArray(new Node[0]);
}
This was tested in NetBeans 8.2 on Windows and works as expected. The "File Browser" displays a tree containing only folders at all levels.
I am working with code which makes use of java.nio.file.Path. I have a path like
/tmp/something/first/second/third/last
which I see only as
{parent.dir}/first/second/third/{path.end}
In this example /tmp/something or {parent.dir} is a path which can be different during runtime and which is irrelevant for me. The same applies for the last element in the path {path.end}
What I would need is to iterate over elements between {parent.dir} and {path.end}. Basically to test each element in the path if it exists and if it is a file or
a directory or something else (it doesn't matter).
I am therefore looking for some elegant/simple and proper way to iterate over instance of Pathwhere I can access paths like these:
/tmp
/tmp/something/
/tmp/something/first
...
/tmp/something/first/second/third/last
ideally in this case without the first 2 and the last iteration.
I am looking for a good solution using Path and java.nio and not the old way. I know I can achieve this using old io API but I am interested in the proper way of using nio.
Here I print all directories child of your parent dir:
Files.walk(Paths.get(${parent.dir})).filter(path -> Files.isDirectory(path, LinkOption.NOFOLLOW_LINKS)).forEach(System.out::println);
You can pass another lambda to the forEach method for your own purpose.
Also replace ${parent.dir} with your correct value as a String.
(The code above may throw IOException).
Assuming that the base and end parts are parameters, while the in-between part is fixed, a solution can look like this:
static void iterate(Path base, Path end) {
if(!base.isAbsolute() || end.isAbsolute()) throw new
IllegalArgumentException("base must be absolute, end must be relative");
// test the fixed in-between paths
Path fixed=Paths.get("first", "second", "third");
for(Path part: fixed) {
base=base.resolve(part);
System.out.print(base);
if(Files.isDirectory(base)) {
System.out.println(" is a directory");
}
else {
System.out.println(Files.exists(part)?" is not a directory":" does not exist");
return;
}
}
// test the end path
end=base.resolve(end);
System.out.print(end+(
Files.isDirectory(end)? " is a directory":
Files.exists(end)? " is not a directory": " does not exist"));
}
It stops the iteration once it encounters a non-directory path component. You will have to adapt this behavior if you want to enforce a specific policy regarding following symbolic links…
I am creating an editor application, and I am having a problem with my menus. In the object menu, I want to display several objects types using a JTree. These object types are dynamically registered by plugins and follow this style:
trigger.button
trigger.lever
out.door.fallgate
trigger.plate
out.door.door
...
This list of names is unsorted and I want to build a TreeNode structure for a JTree like this:
trigger
button
lever
plate
out
door
fallgate
door
Additionally, if the user selects a leaf node, I need to recreate the object name (e.g. trigger.button) from the TreePath. Could someone please advise how this can be done.
In psuedocode, this is what you need to do...
public TreeNode buildTree(){
String[] names = new String[]; // fill this with the names of your plugins
TreeNode tree;
// for each plugin name...
for (int i=0;i<names.length;i++){
String currentName = names[i];
String[] splitName = currentName.split(".");
// loop over the split name and see if the nodes exist in the tree. If not, create them
TreeNode parent = tree;
for (int n=0;n<splitName.length;n++){
if (parent.hasChild(splitName[n])){
// the parent node exists, so it doesn't need to be created. Store the node as 'parent' to use in the next loop run
parent = parent.getChild(splitName[n]);
}
else {
// the node doesn't exist, so create it. Then set it as 'parent' for use by the next loop run
TreeNode child = new TreeNode(splitName[n]);
parent.addChild(child);
parent = child;
}
}
return tree;
}
This is only psuedocode - you'll need to do the work of implementing the TreeNode methods properly, etc. Give it a try yourself - if you have any more problems, create a question and show us that you've attempted to do it yourself, then we will be more willing to help you solve the minor problems.
see Oracle JTree tutorial
part Dynamically Changing a Tree, check the code example
similair idea
I want to write a Java application that validate files and directories according to certain naming standards. The program would let you pick a directory and would recursively analyze -- giving a list of files/directories that do not match the given rules.
Eventually I want the user to be able to input rules, but for now they would be hard coded. Oh, and this would need to be cross-platform.
I'm have a working knowledge of basic Java constructs but have no experience with libraries and have not had much luck finding demos/code samples for this type of thing.
I would love suggestions for what trees to start barking up, pseudo-code -- whatever you feel would be helpful.
EDIT: I'm not trying to remove anything here, just get a recursive listing of any names that break certain rules (e.g. no spaces or special characters, no directories that start with uppercase) in the chosen directory.
I would like to use Commons IO, I think DirectoryWalker will help you.
Here is the sample for checking and removing ".svn" dir
public class FileCleaner extends DirectoryWalker {
public FileCleaner() {
super();
}
public List clean(File startDirectory) {
List results = new ArrayList();
walk(startDirectory, results);
return results;
}
protected boolean handleDirectory(File directory, int depth, Collection results) {
// delete svn directories and then skip
if (".svn".equals(directory.getName())) {
directory.delete();
return false;
} else {
return true;
}
}
protected void handleFile(File file, int depth, Collection results) {
// delete file and add to list of deleted
file.delete();
results.add(file);
}
}