/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.esri.gpt.control.search.browse; import com.esri.gpt.framework.context.ConfigurationException; import com.esri.gpt.framework.jsf.MessageBroker; import com.esri.gpt.framework.util.Val; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Represents an item within a table of contents. */ public class TocItem { /** instance variables ====================================================== */ private List<TocItem> children = new ArrayList<TocItem>(); private boolean isValid = true; private String id; private String name; private String query; private String resourceKey; private String type; /** constructors ============================================================ */ /** Default constructor */ public TocItem() {} /** properties ============================================================== */ /** * Gets the children. * @return the children */ public List<TocItem> getChildren() { return this.children; } /** * Sets the children. * @param children the children */ public void setChildren(List<TocItem> children) { this.children = children; } /** * Gets the id. * @return the id */ public String getId() { return id; } /** * Sets the id. * @param id the id */ public void setId(String id) { this.id = id; } /** * Gets the name. * @return the name */ public String getName() { return this.name; } /** * Sets the name. * @param name the name */ public void setName(String name) { this.name = name; } /** * Gets the query string (rest). * @return the name */ public String getQuery() { return this.query; } /** * Sets the query string (rest). * @param query query string */ public void setQuery(String query) { this.query = query; } /** * Gets the UI property bundle resource key. * @return the resource key */ public String getResourceKey() { return this.resourceKey; } /** * Sets the UI property bundle resource key. * @param resourceKey the resource key */ public void setResourceKey(String resourceKey) { this.resourceKey = resourceKey; } /** * Gets the type (for TOC image display). * @return the type */ public String getType() { return this.type; } /** * Sets the type (for TOC image display). * @param type the type */ public void setType(String type) { this.type = type; } /** methods ================================================================= */ /** * Determines whether or not this property has children. * @return <code>true</code> if this property has children */ public boolean hasChildren() { return (this.getChildren() != null) && (this.getChildren().size() > 0); } /** * Invalidates the item. */ public void invalidate() { this.isValid = false; } /** * Gets the flag indicating whether or not the item is valid. * @return <code>true</code> if the item is valid */ public boolean isValid() { return this.isValid; } /** * Looks up the item name based upon the UI property bundle resource key. * @param msgBroker the message broker */ public void lookupName(MessageBroker msgBroker) { String rKey = Val.chkStr(this.getResourceKey()); if (rKey.length() > 0) { String rVal = Val.chkStr(msgBroker.retrieveMessage(rKey)); if (rVal.length() > 0) { boolean hadName = (Val.chkStr(this.getName()).length() > 0); if (!hadName || !rVal.startsWith("??")) { this.setName(rVal); } } } } /** * Makes a TocItem instance based upon a class name. * @param context the operation context * @param className the fully qualified class name * @return the instance * @throws ClassNotFoundException if the class was not found * @throws InstantiationException if the class could not be instantiated * @throws IllegalAccessException if the class could not be accessed */ public static TocItem makeItemInstance(TocContext context, String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException { className = Val.chkStr(className); if (className.length() == 0) { return new TocItem(); } else { Class<?> cls = Class.forName(className); Object obj = cls.newInstance(); if (obj instanceof TocItem) { return (TocItem)obj; } else { String msg = "The configured item.className is invalid: "+className; throw new ConfigurationException(msg); } } } /** * Processes a TOC item node. * @param context the operation context * @param node the item node * @throws Exception if an exception occurs */ public void processItemNode(TocContext context, Node node) throws Exception { // process the name and type nodes boolean hadName = false; NodeList nlChildren = node.getChildNodes(); for (int i=0; i<nlChildren.getLength(); i++) { Node ndChild = nlChildren.item(i); if (ndChild.getNodeType() == Node.ELEMENT_NODE) { String nodeName = Val.chkStr(ndChild.getNodeName()); if (nodeName.equalsIgnoreCase("name")) { this.setName(ndChild.getTextContent()); Node ndRes = ndChild.getAttributes().getNamedItem("resourceKey"); if (ndRes != null) { this.setResourceKey(ndRes.getNodeValue()); this.lookupName(context.getMessageBroker()); } hadName = (Val.chkStr(this.getName()).length() > 0); } else if (nodeName.equalsIgnoreCase("type")) { this.setType(ndChild.getTextContent()); } else if (nodeName.equalsIgnoreCase("id")) { this.setId(ndChild.getTextContent()); } } } if (!hadName) this.invalidate(); if (!this.isValid()) return; // process the query node for (int i=0; i<nlChildren.getLength(); i++) { Node ndChild = nlChildren.item(i); if (ndChild.getNodeType() == Node.ELEMENT_NODE) { String nodeName = Val.chkStr(ndChild.getNodeName()); if (nodeName.equalsIgnoreCase("query")) { TocQueryProvider qProvider = null; Node ndClassName = ndChild.getAttributes().getNamedItem("className"); if (ndClassName == null) { qProvider = new TocQueryProvider(); } else { qProvider = TocQueryProvider.makeProviderInstance(context,ndClassName.getNodeValue()); } qProvider.processQueryNode(context,this,ndChild); } } } if (!this.isValid()) return; // process the child items for (int i=0; i<nlChildren.getLength(); i++) { Node ndChild = nlChildren.item(i); if (ndChild.getNodeType() == Node.ELEMENT_NODE) { String nodeName = Val.chkStr(ndChild.getNodeName()); if (nodeName.equalsIgnoreCase("item")) { TocItem subItem = null; Node ndClassName = ndChild.getAttributes().getNamedItem("className"); if (ndClassName == null) { subItem = new TocItem(); } else { subItem = TocItem.makeItemInstance(context,ndClassName.getNodeValue()); } subItem.processItemNode(context,ndChild); if (subItem.isValid()) { this.getChildren().add(subItem); } } } } } /** * Writes a JSON representation of the property. * @param writer the writer * @param depth the depth of the parent * @throws IOException if an exception occurs */ public void toJson(PrintWriter writer, int depth, boolean isLast) throws IOException { String pfx = ""; for (int i=0;i<2*depth;i++) pfx += " "; String pfx2 = pfx+" "; String line; boolean hc = this.hasChildren(); String sId = Val.chkStr(this.getId()); String sName = Val.chkStr(this.getName()); String sType = Val.chkStr(this.getType()); String sQuery = Val.chkStr(this.getQuery()); writer.println(pfx+"{"); if (sId.length() > 0) { line = pfx2+"\"id\": \""+Val.escapeStrForJson(sId)+"\""; if (hc || (sName.length() > 0) || (sType.length() > 0) || (sQuery.length() > 0)) line +=","; writer.println(line); } if (sName.length() > 0) { line = pfx2+"\"name\": \""+Val.escapeStrForJson(sName)+"\""; if (hc || (sType.length() > 0) || (sQuery.length() > 0)) line +=","; writer.println(line); } if (sType.length() > 0) { line = pfx2+"\"type\": \""+Val.escapeStrForJson(sType)+"\""; if (hc || (sQuery.length() > 0)) line +=","; writer.println(line); } if (sQuery.length() > 0) { line = pfx2+"\"query\": \""+Val.escapeStrForJson(sQuery)+"\""; if (hc) line +=","; writer.println(line); } if (hc) { line = pfx2+"\"children\": ["; writer.println(line); for (int i=0; i<this.getChildren().size(); i++) { TocItem child = this.getChildren().get(i); boolean bLast = (i >= (this.getChildren().size() - 1)); child.toJson(writer,(depth+2),bLast); } writer.println(pfx2+"]"); } line = pfx+"}"; if (!isLast) line +=","; writer.println(line); } /** * Writes an XML representation of the property. * @param writer the writer * @param depth the depth of the parent * @throws IOException if an exception occurs */ public void toXml(PrintWriter writer, int depth) throws IOException { String pfx = ""; for (int i=0;i<2*depth;i++) pfx += " "; String pfx2 = pfx+" "; String sId = Val.chkStr(this.getId()); String sName = Val.chkStr(this.getName()); String sType = Val.chkStr(this.getType()); String sQuery = Val.chkStr(this.getQuery()); writer.println(pfx+"<item>"); if (sId.length() > 0) { writer.println(pfx2+"<id>"+Val.escapeXml(sId)+"</id>"); } if (sName.length() > 0) { writer.println(pfx2+"<name>"+Val.escapeXml(sName)+"</name>"); } if (sType.length() > 0) { writer.println(pfx2+"<type>"+Val.escapeXml(sType)+"</type>"); } if (sQuery.length() > 0) { writer.println(pfx2+"<query>"+Val.escapeXml(sQuery)+"</query>"); } if (this.hasChildren()) { for (TocItem child: this.getChildren()) { child.toXml(writer,(depth+1)); } } writer.println(pfx+"</item>"); } }