ingo@99: package de.intevation.flys.client.server; ingo@99: ingo@99: import java.util.ArrayList; ingo@524: import java.util.HashMap; ingo@99: import java.util.List; ingo@524: import java.util.Map; ingo@99: ingo@99: import javax.xml.xpath.XPathConstants; ingo@99: ingo@99: import org.w3c.dom.Document; ingo@575: import org.w3c.dom.Element; ingo@804: import org.w3c.dom.NamedNodeMap; ingo@804: import org.w3c.dom.Node; ingo@99: import org.w3c.dom.NodeList; ingo@99: ingo@99: import com.google.gwt.user.server.rpc.RemoteServiceServlet; ingo@99: ingo@99: import de.intevation.artifacts.common.ArtifactNamespaceContext; ingo@99: import de.intevation.artifacts.common.utils.ClientProtocolUtils; ingo@99: import de.intevation.artifacts.common.utils.XMLUtils; ingo@99: ingo@99: import de.intevation.artifacts.httpclient.exceptions.ConnectionException; ingo@99: import de.intevation.artifacts.httpclient.http.HttpClient; ingo@99: import de.intevation.artifacts.httpclient.http.HttpClientImpl; ingo@99: import de.intevation.artifacts.httpclient.http.response.DocumentResponseHandler; ingo@99: ingo@215: import de.intevation.flys.client.shared.exceptions.ServerException; ingo@804: import de.intevation.flys.client.shared.model.AttributedTheme; ingo@99: import de.intevation.flys.client.shared.model.Collection; ingo@99: import de.intevation.flys.client.shared.model.CollectionItem; ingo@99: import de.intevation.flys.client.shared.model.DefaultCollection; ingo@99: import de.intevation.flys.client.shared.model.DefaultCollectionItem; ingo@270: import de.intevation.flys.client.shared.model.DefaultFacet; ingo@809: import de.intevation.flys.client.shared.model.DefaultRecommendation; ingo@796: import de.intevation.flys.client.shared.model.ChartMode; ingo@270: import de.intevation.flys.client.shared.model.ExportMode; ingo@796: import de.intevation.flys.client.shared.model.MapMode; sascha@589: import de.intevation.flys.client.shared.model.ReportMode; ingo@270: import de.intevation.flys.client.shared.model.Facet; ingo@99: import de.intevation.flys.client.shared.model.OutputMode; ingo@809: import de.intevation.flys.client.shared.model.Recommendation; ingo@524: import de.intevation.flys.client.shared.model.Theme; ingo@524: import de.intevation.flys.client.shared.model.ThemeList; ingo@99: import de.intevation.flys.client.client.services.DescribeCollectionService; ingo@99: ingo@99: ingo@99: /** ingo@99: * This service implements a method that queries the DESCRIBE document of a ingo@99: * specific collection and returns a Collection object with the information of ingo@99: * the document. ingo@99: * ingo@99: * @author Ingo Weinzierl ingo@99: */ ingo@99: public class DescribeCollectionServiceImpl ingo@99: extends RemoteServiceServlet ingo@99: implements DescribeCollectionService ingo@99: { ingo@215: /** The error message key that is thrown if an error occured while ingo@215: * describe() a Collection.*/ ingo@215: public static final String ERROR_DESCRIBE_COLLECTION = ingo@215: "error_describe_collection"; ingo@215: ingo@270: public static final String XPATH_FACETS = "art:facets/art:facet"; ingo@270: ingo@809: public static final String XPATH_LOADED_RECOMMENDATIONS = ingo@809: "/art:artifact-collection/art:attribute/art:loaded-recommendations/art:recommendation"; ingo@809: ingo@215: ingo@229: public Collection describe(String uuid, String serverUrl, String locale) ingo@215: throws ServerException ingo@215: { ingo@99: System.out.println("DescribeCollectionServiceImpl.describe"); ingo@99: ingo@99: Document describe = ClientProtocolUtils.newDescribeCollectionDocument( ingo@99: uuid); ingo@99: ingo@229: HttpClient client = new HttpClientImpl(serverUrl, locale); ingo@99: ingo@99: try { ingo@99: Document response = (Document) client.doCollectionAction( ingo@99: describe, uuid, new DocumentResponseHandler()); ingo@99: ingo@99: Collection c = parseCollection(response); ingo@99: ingo@99: if (c == null) { ingo@215: throw new ServerException(ERROR_DESCRIBE_COLLECTION); ingo@99: } ingo@99: ingo@524: System.out.println("Collection successfully parsed."); ingo@524: ingo@99: return c; ingo@99: } ingo@99: catch (ConnectionException ce) { ingo@99: System.err.println(ce.getLocalizedMessage()); ingo@99: } ingo@99: ingo@215: throw new ServerException(ERROR_DESCRIBE_COLLECTION); ingo@99: } ingo@99: ingo@99: ingo@99: /** ingo@99: * This method takes the DESCRIBE document of the Collections describe() ingo@99: * operation and extracts the information about the collection itself and ingo@99: * the collection items. ingo@99: * ingo@99: * @param description The DESCRIBE document of the Collections describe() ingo@99: * operation. ingo@99: * ingo@99: * @return a Collection with CollectionItems. ingo@99: */ ingo@99: protected Collection parseCollection(Document description) { ingo@99: System.out.println("AddArtifactServiceImpl.parseCollection"); ingo@99: ingo@99: if (description == null) { ingo@99: System.err.println("The DESCRIBE of the Collection is null!"); ingo@99: return null; ingo@99: } ingo@99: ingo@99: String uuid = XMLUtils.xpathString( ingo@99: description, ingo@99: "art:artifact-collection/@art:uuid", ingo@99: ArtifactNamespaceContext.INSTANCE); ingo@99: ingo@587: String ttlStr = XMLUtils.xpathString( ingo@587: description, ingo@587: "art:artifact-collection/@art:ttl", ingo@587: ArtifactNamespaceContext.INSTANCE); ingo@587: ingo@587: if (uuid.length() == 0 || ttlStr.length() == 0) { ingo@99: System.err.println("Found an invalid Collection!"); ingo@99: return null; ingo@99: } ingo@99: ingo@587: ingo@587: long ttl = -1; ingo@587: try { ingo@587: ttl = Long.valueOf(ttlStr); ingo@587: } ingo@587: catch (NumberFormatException nfe) { ingo@587: // do nothing ingo@587: } ingo@587: ingo@524: Map themeList = parseThemeLists(description); ingo@809: List recommended = parseRecommendations(description); ingo@524: sascha@581: Collection c = !themeList.isEmpty() ingo@809: ? new DefaultCollection(uuid, ttl, recommended, themeList) ingo@809: : new DefaultCollection(uuid, ttl, recommended); ingo@99: ingo@99: NodeList items = (NodeList) XMLUtils.xpath( ingo@99: description, ingo@99: "art:artifact-collection/art:artifacts/art:artifact", ingo@99: XPathConstants.NODESET, ingo@99: ArtifactNamespaceContext.INSTANCE); ingo@99: ingo@99: if (items == null || items.getLength() == 0) { ingo@99: System.out.println("No collection item found for this collection."); ingo@99: ingo@99: return c; ingo@99: } ingo@99: ingo@99: int size = items.getLength(); ingo@99: ingo@99: for (int i = 0; i < size; i++) { ingo@829: CollectionItem item = parseCollectionItem( ingo@829: (Element)items.item(i), ingo@829: i == 0); ingo@99: ingo@99: if (item != null) { ingo@99: c.addItem(item); ingo@99: } ingo@99: } ingo@99: ingo@99: System.out.println( ingo@99: "Found " + c.getItemLength() + " collection items " + ingo@99: "for the Collection '" + c.identifier() + "'."); ingo@99: ingo@99: return c; ingo@99: } ingo@99: ingo@99: ingo@524: protected Map parseThemeLists(Document description) { ingo@524: System.out.println("DescribeCollectionServiceImpl.parseThemeLists"); ingo@524: ingo@524: NodeList lists = (NodeList) XMLUtils.xpath( ingo@524: description, ingo@524: "/art:artifact-collection/art:attribute/art:outputs/art:output", ingo@524: XPathConstants.NODESET, ingo@524: ArtifactNamespaceContext.INSTANCE); ingo@524: ingo@524: int num = lists != null ? lists.getLength() : 0; ingo@524: ingo@524: Map themeList = new HashMap(num); ingo@524: sascha@581: String uri = ArtifactNamespaceContext.NAMESPACE_URI; ingo@524: sascha@581: for (int i = 0; i < num; i++) { sascha@581: Element node = (Element)lists.item(i); ingo@524: sascha@581: String outName = node.getAttribute("name"); ingo@524: sascha@581: if (outName.length() > 0) { sascha@581: ThemeList list = parseThemeList(node); sascha@581: if (list.getThemeCount() > 0) { sascha@581: themeList.put(outName, list); sascha@581: } ingo@524: } ingo@524: } ingo@524: ingo@524: return themeList; ingo@524: } ingo@524: ingo@524: sascha@581: protected ThemeList parseThemeList(Element node) { ingo@524: System.out.println("DescribeCollectionServiceImpl.parseThemeList"); ingo@524: sascha@581: NodeList themes = node.getElementsByTagNameNS( sascha@581: ArtifactNamespaceContext.NAMESPACE_URI, ingo@804: "facet"); ingo@524: ingo@524: int num = themes != null ? themes.getLength() : 0; ingo@524: ingo@524: List themeList = new ArrayList(num); ingo@524: ingo@524: for (int i = 0; i < num; i++) { sascha@581: Theme theme = parseTheme((Element)themes.item(i)); ingo@524: ingo@524: if (theme != null) { ingo@524: themeList.add(theme); ingo@524: } ingo@524: } ingo@524: ingo@524: return new ThemeList(themeList); ingo@524: } ingo@524: ingo@524: ingo@575: protected Theme parseTheme(Element ele) { ingo@524: System.out.println("DescribeCollectionServiceImpl.parseTheme"); ingo@524: ingo@575: String uri = ArtifactNamespaceContext.NAMESPACE_URI; ingo@524: ingo@804: NamedNodeMap attrMap = ele.getAttributes(); ingo@804: int attrNum = attrMap != null ? attrMap.getLength() : 0; ingo@524: ingo@804: AttributedTheme t = new AttributedTheme(); ingo@524: ingo@804: for (int i = 0; i < attrNum; i++) { ingo@804: Node attr = attrMap.item(i); ingo@804: ingo@804: String prefix = attr.getPrefix(); ingo@804: String name = attr.getNodeName().replace(prefix + ":", ""); ingo@804: String value = attr.getNodeValue(); ingo@804: ingo@804: t.addAttr(name, value); ingo@524: } ingo@524: ingo@804: return t; ingo@524: } ingo@524: ingo@524: ingo@99: /** ingo@99: * This method extracts the CollectionItem from node with its output ingo@99: * modes. The output modes are parsed using the parseOutputModes() method. ingo@99: * ingo@99: * @param node A node that contains information about a CollectionItem. ingo@99: * ingo@99: * @return a CollectionItem. ingo@99: */ ingo@829: protected CollectionItem parseCollectionItem(Element node, boolean outs) { ingo@99: System.out.println("AddArtifactServiceImpl.parseCollectionItem"); ingo@99: ingo@99: if (node == null) { ingo@99: System.err.println("The node for parsing CollectionItem is null!"); ingo@99: return null; ingo@99: } ingo@99: sascha@581: String uri = ArtifactNamespaceContext.NAMESPACE_URI; ingo@99: sascha@581: String uuid = node.getAttributeNS(uri, "uuid"); sascha@581: String hash = node.getAttributeNS(uri, "hash"); ingo@99: ingo@587: if (uuid == null || uuid.length() == 0) { ingo@99: System.err.println("Found an invalid CollectionItem!"); sascha@581: return null; ingo@99: } ingo@99: ingo@829: List modes = new ArrayList(); ingo@99: ingo@829: if (outs) { ingo@829: NodeList outputmodes = node.getElementsByTagNameNS( ingo@829: uri, "outputmodes"); ingo@829: ingo@829: if (outputmodes.getLength() < 1) { ingo@829: return null; ingo@829: } ingo@829: ingo@829: Element om = (Element)outputmodes.item(0); ingo@829: ingo@829: modes = parseOutputModes(om); sascha@581: } sascha@581: ingo@99: return new DefaultCollectionItem(uuid, hash, modes); ingo@99: } ingo@99: ingo@99: ingo@99: /** ingo@99: * This method extracts the OutputModes available for a specific ingo@99: * CollectionItem and returns them as list. ingo@99: * ingo@99: * @param node The root node of the outputmodes list. ingo@99: * ingo@99: * @return a list of OutputModes. ingo@99: */ sascha@581: protected List parseOutputModes(Element node) { ingo@99: System.out.println("AddArtifactServiceImpl.parseOutputModes"); ingo@99: ingo@99: if (node == null) { ingo@99: System.err.println("The node for parsing OutputModes is null!"); ingo@99: return null; ingo@99: } ingo@99: sascha@581: String uri = ArtifactNamespaceContext.NAMESPACE_URI; ingo@99: sascha@581: NodeList list = node.getElementsByTagNameNS(uri, "output"); sascha@581: sascha@581: int size = list.getLength(); sascha@581: sascha@581: if (size == 0) { ingo@99: System.err.println("No outputmode nodes found!"); ingo@99: return null; ingo@99: } ingo@99: ingo@99: List modes = new ArrayList(size); ingo@99: ingo@99: for (int i = 0; i < size; i++) { sascha@581: Element tmp = (Element)list.item(i); ingo@99: sascha@581: String name = tmp.getAttributeNS(uri, "name"); sascha@581: String desc = tmp.getAttributeNS(uri, "description"); sascha@581: String mime = tmp.getAttributeNS(uri, "mime-type"); ingo@796: String type = tmp.getAttributeNS(uri, "type"); sascha@581: sascha@581: if (name.length() == 0) { ingo@99: System.err.println("Found an invalid output mode."); ingo@99: continue; ingo@99: } ingo@99: ingo@270: OutputMode outmode = null; ingo@270: List fs = extractFacets(tmp); ingo@99: ingo@796: if (type.equals("export")) { ingo@270: outmode = new ExportMode(name, desc, mime, fs); ingo@270: } ingo@796: else if (type.equals("report")) { sascha@589: outmode = new ReportMode(name, desc, mime, fs); sascha@589: } ingo@796: else if (type.equals("chart")){ ingo@796: outmode = new ChartMode(name, desc, mime, fs); ingo@796: } ingo@796: else if (type.equals("map")){ ingo@796: outmode = new MapMode(name, desc, mime, fs); ingo@796: } ingo@270: else { ingo@796: System.err.println("Broken Output mode without type found."); ingo@796: continue; ingo@270: } ingo@270: ingo@270: modes.add(outmode); ingo@99: } ingo@99: ingo@99: return modes; ingo@99: } ingo@270: ingo@270: sascha@581: protected static List extractFacets(Element outmode) { ingo@809: System.out.println("DescribeCollectionServiceImpl - extractFacets()"); ingo@270: ingo@270: NodeList facetList = (NodeList) XMLUtils.xpath( ingo@270: outmode, ingo@270: XPATH_FACETS, ingo@270: XPathConstants.NODESET, ingo@270: ArtifactNamespaceContext.INSTANCE); ingo@270: ingo@270: int num = facetList != null ? facetList.getLength() : 0; ingo@270: ingo@270: List facets = new ArrayList(num); ingo@270: ingo@575: String uri = ArtifactNamespaceContext.NAMESPACE_URI; ingo@270: ingo@575: for (int i = 0; i < num; i++) { ingo@575: Element facetEl = (Element) facetList.item(i); ingo@270: ingo@575: String name = facetEl.getAttributeNS(uri, "name"); ingo@575: String desc = facetEl.getAttributeNS(uri, "description"); ingo@575: String index = facetEl.getAttributeNS(uri, "index"); ingo@575: ingo@575: if (name != null && name.length() > 0 && index != null) { ingo@575: facets.add(new DefaultFacet(name, Integer.valueOf(index),desc)); ingo@270: } ingo@270: } ingo@270: ingo@270: return facets; ingo@270: } ingo@809: ingo@809: ingo@809: public static List parseRecommendations(Document doc) { ingo@809: System.out.println("DescribeCollectionServiceImpl.parseRecommendations"); ingo@809: ingo@809: NodeList list = (NodeList) XMLUtils.xpath( ingo@809: doc, ingo@809: XPATH_LOADED_RECOMMENDATIONS, ingo@809: XPathConstants.NODESET, ingo@809: ArtifactNamespaceContext.INSTANCE); ingo@809: ingo@809: int num = list != null ? list.getLength() : 0; ingo@809: ingo@809: List recs = new ArrayList(num); ingo@809: ingo@809: String uri = ArtifactNamespaceContext.NAMESPACE_URI; ingo@809: ingo@809: for (int i = 0; i < num; i++) { ingo@809: Element rec = (Element) list.item(i); ingo@809: ingo@809: String factory = rec.getAttributeNS(uri, "factory"); sascha@836: String dbids = rec.getAttributeNS(uri, "ids"); ingo@809: ingo@809: if (factory != null && factory.length() > 0) { ingo@809: recs.add(new DefaultRecommendation(factory, dbids)); ingo@809: } ingo@809: } ingo@809: ingo@809: return recs; ingo@809: } ingo@99: } ingo@99: // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :