i have list of departments and each department might have a parent or not,department domain object is as follows:
- departmentId
- parentDepartmentId (null if current department has no parent i,e should be under root directly, and have value if current department have parent).
.
.
.
looking at icefaces tutorial code for creating basic tree:
// create root node with its children expanded
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
IceUserObject rootObject = new IceUserObject(rootTreeNode);
rootObject.setText("Root Node");
rootObject.setExpanded(true);
rootTreeNode.setUserObject(rootObject);
// model is accessed by by the ice:tree component via a getter method, this object is what's needed in the view to display the tree
model = new DefaultTreeModel(rootTreeNode);
// add some child nodes
for (int i = 0; i <3; i++) {
DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
IceUserObject branchObject = new IceUserObject(branchNode);
branchObject.setText("node-" + i);
branchNode.setUserObject(branchObject);
rootTreeNode.add(branchNode);
}
it's all about constructing basic node, and adding childs.
my case is complex that child A which is under root may have child nodes B,C,D and D have for example child nodes and so on so on.
so i am thinking of a best practice about how to accomplish something like that, i need a sample code or hints if anyone can help.
You would need a recursive method to construct the tree from your model.
public void buildRecursiveTreeNode(DefaultMutableTreeNode parentTreeNode,
String treeId, String treeName, GenericTreeVo modelVo)
{
// if the database model contains more children.
// add the current nodes first and pass in this nodes tree id and name to construct the children for this parent nodes.
}
Updated answer to include recursion example.
http://www.danzig.us/java_class/recursion.html
just added a recursion link, all I am saying is when you iterate the data from the database, you would see if you have any child records, if you have child records you would call the same method by passing the DefaultMutableTreeNode and that would become the parent.
finally i was able to do it as follows:
List<Department> departmentList = getAllDepartments();
// create root node with its children expanded
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
IceUserObject rootObject = new IceUserObject(rootTreeNode);
rootObject.setText("Root");
rootObject.setExpanded(true);
rootTreeNode.setUserObject(rootObject);
HashMap<Department, DefaultMutableTreeNode> createdNodesMap = new HashMap<Department, DefaultMutableTreeNode>(
0);
for (Department department : departmentList) {
DefaultMutableTreeNode currentNode = null;
if (createdNodesMap.get(department) == null) {
log.debug("############ CREATING NODE "
+ department.getName());
currentNode = new DefaultMutableTreeNode();
IceUserObject currentObject = new IceUserObject(currentNode);
currentObject.setText(department.getName());
currentObject.setExpanded(true);
currentNode.setUserObject(currentObject);
if (department.getParentDepartment() == null) {
rootTreeNode.add(currentNode);
log.debug("######### NODE " + department.getName()
+ " ADDED UNDER ROOT");
}
createdNodesMap.put(department, currentNode);
} else {
log.debug("############ GETTING CREATED NODE "
+ department.getName());
currentNode = createdNodesMap.get(department);
}
if (department.getChildren().size() > 0)
log.debug("############ NODE " + department.getName()
+ " HAVE " + department.getChildren().size()
+ " CHILDREN");
else
log.debug("############ NODE " + department.getName()
+ " DOES NOT HAVE CHILDREN");
for (Department department2 : department.getChildren()) {
log.debug("############ CREATING CHILD "
+ department2.getName() + " FOR PARENT "
+ department.getName());
DefaultMutableTreeNode branchNode;
if (createdNodesMap.get(department2) == null) {
branchNode = new DefaultMutableTreeNode();
IceUserObject branchObject = new IceUserObject(
branchNode);
branchObject.setText(department2.getName());
branchObject.setExpanded(true);
branchNode.setUserObject(branchObject);
} else
branchNode = createdNodesMap.get(department2);
createdNodesMap.put(department2, branchNode);
currentNode.add(branchNode);
}
}
model = new DefaultTreeModel(rootTreeNode);
Check http://click.avoka.com/click-examples/tree/checkbox-tree-page.htm
The latter is done via the Apache Click framework. Right now I'm developing a project where this data structure (hierarchy tree) is heavily used. You can set the root node or if you need to have several starting points, you can create a wildcard root node that won't affect the functionality, the subclasses, like others have commented, need to be created recursively.
Related
I'm writing an XPath selector to select all the node name o:OLEObject providing that its ancestor is not w:del. but the nodes in w:del are included in the result. Can you help me to clear it?
Here is my script:
publicList<String> getAllOleObjectId(XmlObject wobj) {
List<String> lstOfOleObjIds = new ArrayList<String>();
XmlCursor cursorForOle = wobj.newCursor();
if(cursorForOle != null) {
cursorForOle.selectPath(
"declare namespace w='http://schemas.openxmlformats.org/wordprocessingml/2006/main' " +
"declare namespace o='urn:schemas-microsoft-com:office:office' " +
".//*/o:OLEObject[ancestor::*[not(self::w:del)]]"
);
while (cursorForOle.hasNextSelection()) {
cursorForOle.toNextSelection();
XmlObject oleObj = cursorForOle.getObject();
Node oleDomNode = oleObj.getDomNode();
NamedNodeMap domAttrObj = oleDomNode.getAttributes();
lstOfOleObjIds.add(domAttrObj.getNamedItem("r:id").getNodeValue());
}
}
cursorForOle.dispose();
return lstOfOleObjIds;
}
You should replace your XPath with :
//*/o:OLEObject[not(ancestor::w:del)]
Select OLEObject element, child of any (*) element, and which has no ancestor element named del.
How do I use SOOT to build at Call graph? Or are there any better programs for this? I have been sent around the same five pages looking for answers and I can't find what I am looking for. There are also a problem with the plugin version to Eclipse. It is installed correct but I cant choose it when I want to run the code.
Small modification to previous answer
private static void visit(CallGraph cg, SootMethod method) {
String identifier = method.getSignature();
visited.put(method.getSignature(), true);
dot.drawNode(identifier);
// iterate over unvisited parents
Iterator<MethodOrMethodContext> ptargets = new Sources(cg.edgesInto(method));
if (ptargets != null) {
while (ptargets.hasNext()) {
SootMethod parent = (SootMethod) ptargets.next();
if (!visited.containsKey(parent.getSignature())) visit(cg, parent);
}
}
Here are some examples include call graph for Java. http://www.brics.dk/SootGuide/
And call graph for apk.
https://github.com/secure-software-engineering/soot-infoflow/issues/38
If you want to get the dot file, you can iterate over the callgraph and write the contents out in dot format like this.
private static void visit(CallGraph cg, SootMethod method) {
String identifier = method.getSignature();
visited.put(method.getSignature(), true);
dot.drawNode(identifier);
// iterate over unvisited parents
Iterator<MethodOrMethodContext> ptargets = new Targets(cg.edgesInto(method));
if (ptargets != null) {
while (ptargets.hasNext()) {
SootMethod parent = (SootMethod) ptargets.next();
if (!visited.containsKey(parent.getSignature())) visit(cg, parent);
}
}
// iterate over unvisited children
Iterator<MethodOrMethodContext> ctargets = new Targets(cg.edgesOutOf(method));
if (ctargets != null) {
while (ctargets.hasNext()) {
SootMethod child = (SootMethod) ctargets.next();
dot.drawEdge(identifier, child.getSignature());
System.out.println(method + " may call " + child);
if (!visited.containsKey(child.getSignature())) visit(cg, child);
}
}
}
I am stuck on an issue trying to parse some XML documents to obtain the output i require.
Take this sample XML:
<root>
<ZoneRule Name="After" RequiresApproval="false">
<Zone>
<WSAZone ConsecutiveDayNumber="1">
<DaysOfWeek>
<WSADaysOfWeek Saturday="false"/>
</DaysOfWeek>
<SelectedLimits>
</SelectedLimits>
<SelectedHolidays>
</SelectedHolidays>
</WSAZone>
</Zone>
</ZoneRule>
<ZoneRule Name="Before" RequiresApproval="false">
<Zone>
<WSAZone ConsecutiveDayNumber="3">
<DaysOfWeek>
<WSADaysOfWeek Saturday="true"/>
</DaysOfWeek>
<SelectedLimits>
</SelectedLimits>
<SelectedHolidays>
</SelectedHolidays>
</WSAZone>
</Zone>
</ZoneRule>
</root>
What i am attempting to do is to be able to ignore the root tag (this is working so no problems here), and treat each of the "ZoneRule's" as its own individual block.
Once i have each ZoneRule isolated i need to extract all of the nodes and attributes to allow me to to create a string to query a database to check if it exists (this part is also working).
The issue i am having is that in my code i cannot separate out each individual ZoneRule block, for some reason it is being processed all as one.
My sample code is as follows:
public String testXML = "";
int andCount = 0;
public void printNote(NodeList nodeList) {
for (int count = 0; count < nodeList.getLength(); count++) {
Node tempNode = nodeList.item(count);
// make sure it's element node.
if (tempNode.getNodeType() == Node.ELEMENT_NODE) {
if (tempNode.hasAttributes()))) {
// get attributes names and values
NamedNodeMap nodeMap = tempNode.getAttributes();
for (int i = 0; i < nodeMap.getLength(); i++) {
Node node = nodeMap.item(i);
if (andCount == 0) {
testXML = testXML + "XMLDataAsXML.exist('//" + tempNode.getNodeName() + "[./#" + node.getNodeName() + "=\"" + node.getNodeValue() + "\"]')=1 \n";
} else {
testXML = testXML + " and XMLDataAsXML.exist('//" + tempNode.getNodeName() + "[./#" + node.getNodeName() + "=\"" + node.getNodeValue() + "\"]')=1 \n";
}
andCount = andCount + 1;
}
}
if (tempNode.hasChildNodes()) {
// loop again if has child nodes
printNote(tempNode.getChildNodes());
}
}
}
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
try {
File file = new File("C:\\Test.xml");
DocumentBuilder dBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = dBuilder.parse(file);
//System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
if (doc.hasChildNodes()) {
printNote(doc.getChildNodes());
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
System.out.println(testXML);
}
Which produces this output (both nodes combined).
XMLDataAsXML.exist('//ZoneRule[./#Name="After"]')=1
and XMLDataAsXML.exist('//ZoneRule[./#RequiresApproval="false"]')=1
and XMLDataAsXML.exist('//WSAZone[./#ConsecutiveDayNumber="1"]')=1
and XMLDataAsXML.exist('//WSADaysOfWeek[./#Saturday="false"]')=1
and XMLDataAsXML.exist('//ZoneRule[./#Name="Before"]')=1
and XMLDataAsXML.exist('//ZoneRule[./#RequiresApproval="false"]')=1
and XMLDataAsXML.exist('//WSAZone[./#ConsecutiveDayNumber="3"]')=1
and XMLDataAsXML.exist('//WSADaysOfWeek[./#Saturday="true"]')=1
What i am actually after is this (excuse the incomplete SQL statements):
XMLDataAsXML.exist('//ZoneRule[./#Name="After"]')=1
and XMLDataAsXML.exist('//ZoneRule[./#RequiresApproval="false"]')=1
and XMLDataAsXML.exist('//WSAZone[./#ConsecutiveDayNumber="1"]')=1
and XMLDataAsXML.exist('//WSADaysOfWeek[./#Saturday="false"]')=1
XMLDataAsXML.exist XMLDataAsXML.exist('//ZoneRule[./#Name="Before"]')=1
and XMLDataAsXML.exist('//ZoneRule[./#RequiresApproval="false"]')=1
and XMLDataAsXML.exist('//WSAZone[./#ConsecutiveDayNumber="3"]')=1
and XMLDataAsXML.exist('//WSADaysOfWeek[./#Saturday="true"]')=1
The XML that will be parsed will not always be exactly like above so i cannot use hardcoded xPaths etc - i need to dynamically loop through the document, looking for the ZoneRule node as my base (i will dynamically generate this value based on the file received) and then extract all the required info.
I am completely open to better methods than what i have tried above.
Thanks very much.
In your code, the testXML and andCount are declared outside the printNote method and are not being reset during iterations.
You start with the first ZoneRule, generate the correct text during the first for iterations (lets forget about the recursion) and now you move to the next ZoneRule, but testXML contains the whole generated text and the andCount is lager then 0 so you keep attaching the text generated for the next ZoneRule.
You should reset the andCount and testXML at the beggining of each iteriation of the for loop. But then you 'recursive' children would not be rendered correctly.
So either you need two methods one to deal with top level ZoneRule elements and another for its children, or much better, instead of appending to text to shared variable, you should redisng your method so they would return String value which then can be appended correctly (with and or without, withou new line or without) at the place when it is recursively callled.
I have a Neo4j graph database which maps a file system structure consisting of nodes representing folders and files.
Each node has a FATHER_OF and a CHILD_OF relationship.
Now I need to create a TreeNode structure in Java starting from the Neo4j graph: currently I implemented a breadth first print of the NEO4J structure as follows:
public Traverser getTraverser()
{
Transaction tx = graphDb.beginTx();
Traverser traverser = traverseStorage(rootNode);
return traverser;
}
private static Traverser traverseStorage(final Node startNode) {
TraversalDescription td = Traversal.description()
.breadthFirst()
.relationships(GraphStorage.RelTypes.FATHER_OF, Direction.OUTGOING);
return td.traverse(startNode);
}
Now I'm trying to create a Tree using the above breadth-first traverser but can't figure out how to properly assign the correct parent to each node.
TreeNode root = new DefaultTreeNode("root", null);
Traverser traverser = graphStorage.getTraverser();
TreeNode parent = root;
for (Path directoryPath : traverser) {
DefaultTreeNode tmp1 = new DefaultTreeNode((String)directoryPath.endNode().getProperty("name"), parent);
}
I hoped there was something like directoryPath.endNode().getParent() but apparently there isn't.
I'm searching for a solution which doesn't require me to use Cypher query language, any help?
Ok found out, just need a HashMap to map Neo4j node id's to TreeNode objects:
HashMap<Long, TreeNode> treeNodeMap = new HashMap();
then the rest becomes:
TreeNode root = new DefaultTreeNode("root", null);
Traverser traverser = graphStorage.getTraverser();
TreeNode parent = root;
Relationship parentRelationship = directoryPath.endNode().getSingleRelationship(
GraphStorage.RelTypes.CHILD_OF, Direction.OUTGOING);
if (parentRelationship != null) {
Node parentFileNode = parentRelationship.getEndNode();
if (parentFileNode != null) {
long parentId = parentFileNode.getId();
parent = treeNodeMap.get(new Long(parentId));
}
DefaultTreeNode tmp1 = new DefaultTreeNode((String)directoryPath.endNode().getProperty("name"), parent);
treeNodeMap.put(new Long(directoryPath.endNode().getId()), tmp1);
}
The above correctly works.
Can i get the full xpath from the org.w3c.dom.Node ?
Say currently node is pointing to some where the middle of the xml document. I would like extract the xpath for that element.
The output xpath I'm looking for is //parent/child1/chiild2/child3/node. A parent to node xpath. Just ignore the xpath's which are having expressions and points to the same node.
There's no generic method for getting the XPath, mainly because there's no one generic XPath that identifies a particular node in the document. In some schemas, nodes will be uniquely identified by an attribute (id and name are probably the most common attributes.) In others, the name of each element (that is, the tag) is enough to uniquely identify a node. In a few (unlikely, but possible) cases, there's no one unique name or attribute that takes you to a specific node, and so you'd need to use cardinality (get the n'th child of the m'th child of...).
EDIT:
In most cases, it's not hard to create a schema-dependent function to assemble an XPath for a given node. For example, suppose you have a document where every node is uniquely identified by an id attribute, and you're not using namespaces. Then (I think) the following pseudo-Java would work to return an XPath based on those attributes. (Warning: I have not tested this.)
String getXPath(Node node)
{
Node parent = node.getParent();
if (parent == null) {
return "/" + node.getTagName();
}
return getXPath(parent) + "/" + "[#id='" + node.getAttribute("id") + "']";
}
I am working for the company behind jOOX, a library that provides many useful extensions to the Java standard DOM API, mimicking the jquery API. With jOOX, you can obtain the XPath of any element like this:
String path = $(element).xpath();
The above path will then be something like this
/document[1]/library[2]/books[3]/book[1]
I've taken this code from
Mikkel Flindt post & modified it so it can work for Attribute Node.
public static String getFullXPath(Node n) {
// abort early
if (null == n)
return null;
// declarations
Node parent = null;
Stack<Node> hierarchy = new Stack<Node>();
StringBuffer buffer = new StringBuffer();
// push element on stack
hierarchy.push(n);
switch (n.getNodeType()) {
case Node.ATTRIBUTE_NODE:
parent = ((Attr) n).getOwnerElement();
break;
case Node.ELEMENT_NODE:
parent = n.getParentNode();
break;
case Node.DOCUMENT_NODE:
parent = n.getParentNode();
break;
default:
throw new IllegalStateException("Unexpected Node type" + n.getNodeType());
}
while (null != parent && parent.getNodeType() != Node.DOCUMENT_NODE) {
// push on stack
hierarchy.push(parent);
// get parent of parent
parent = parent.getParentNode();
}
// construct xpath
Object obj = null;
while (!hierarchy.isEmpty() && null != (obj = hierarchy.pop())) {
Node node = (Node) obj;
boolean handled = false;
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) node;
// is this the root element?
if (buffer.length() == 0) {
// root element - simply append element name
buffer.append(node.getNodeName());
} else {
// child element - append slash and element name
buffer.append("/");
buffer.append(node.getNodeName());
if (node.hasAttributes()) {
// see if the element has a name or id attribute
if (e.hasAttribute("id")) {
// id attribute found - use that
buffer.append("[#id='" + e.getAttribute("id") + "']");
handled = true;
} else if (e.hasAttribute("name")) {
// name attribute found - use that
buffer.append("[#name='" + e.getAttribute("name") + "']");
handled = true;
}
}
if (!handled) {
// no known attribute we could use - get sibling index
int prev_siblings = 1;
Node prev_sibling = node.getPreviousSibling();
while (null != prev_sibling) {
if (prev_sibling.getNodeType() == node.getNodeType()) {
if (prev_sibling.getNodeName().equalsIgnoreCase(
node.getNodeName())) {
prev_siblings++;
}
}
prev_sibling = prev_sibling.getPreviousSibling();
}
buffer.append("[" + prev_siblings + "]");
}
}
} else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
buffer.append("/#");
buffer.append(node.getNodeName());
}
}
// return buffer
return buffer.toString();
}
For me this one worked best ( using org.w3c.dom elements):
String getXPath(Node node)
{
Node parent = node.getParentNode();
if (parent == null)
{
return "";
}
return getXPath(parent) + "/" + node.getNodeName();
}
Some IDEs specialised in XML will do that for you.
Here are the most well known
oXygen
Stylus Studio
xmlSpy
For instance in oXygen, you can right-click on an element part of an XML document and the contextual menu will have an option 'Copy Xpath'.
There are also a number of Firefox add-ons (such as XPather that will happily do the job for you. For Xpather, you just click on a part of the web page and select in the contextual menu 'show in XPather' and you're done.
But, as Dan has pointed out in his answer, the XPath expression will be of limited use. It will not include predicates for instance. Rather it will look like this.
/root/nodeB[2]/subnodeX[2]
For a document like
<root>
<nodeA>stuff</nodeA>
<nodeB>more stuff</nodeB>
<nodeB cond="thisOne">
<subnodeX>useless stuff</subnodeX>
<subnodeX id="MyCondition">THE STUFF YOU WANT</subnodeX>
<subnodeX>more useless stuff</subnodeX>
</nodeB>
</root>
The tools I listed will not generate
/root/nodeB[#cond='thisOne']/subnodeX[#id='MyCondition']
For instance for an html page, you'll end-up with the pretty useless expression :
/html/body/div[6]/p[3]
And that's to be expected. If they had to generate predicates, how would they know which condition is relevant ? There are zillions of possibilities.
Something like this will give you a simple xpath:
public String getXPath(Node node) {
return getXPath(node, "");
}
public String getXPath(Node node, String xpath) {
if (node == null) {
return "";
}
String elementName = "";
if (node instanceof Element) {
elementName = ((Element) node).getLocalName();
}
Node parent = node.getParentNode();
if (parent == null) {
return xpath;
}
return getXPath(parent, "/" + elementName + xpath);
}