0001: /*
0002: * GeoTools - OpenSource mapping toolkit
0003: * http://geotools.org
0004: * (C) 2005-2006, GeoTools Project Managment Committee (PMC)
0005: *
0006: * This library is free software; you can redistribute it and/or
0007: * modify it under the terms of the GNU Lesser General Public
0008: * License as published by the Free Software Foundation;
0009: * version 2.1 of the License.
0010: *
0011: * This library is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * Lesser General Public License for more details.
0015: */
0016: package org.geotools.styling;
0017:
0018: import java.io.File;
0019: import java.net.MalformedURLException;
0020: import java.net.URL;
0021: import java.util.ArrayList;
0022: import java.util.HashMap;
0023: import java.util.LinkedList;
0024: import java.util.List;
0025: import java.util.Map;
0026: import java.util.StringTokenizer;
0027: import java.util.logging.Level;
0028:
0029: import org.geotools.factory.CommonFactoryFinder;
0030: import org.geotools.factory.GeoTools;
0031: import org.geotools.filter.ExpressionBuilder;
0032: import org.opengis.filter.Filter;
0033: import org.opengis.filter.FilterFactory;
0034: import org.opengis.filter.expression.Expression;
0035: import org.opengis.filter.expression.Function;
0036: import org.w3c.dom.Element;
0037: import org.w3c.dom.NamedNodeMap;
0038: import org.w3c.dom.Node;
0039: import org.w3c.dom.NodeList;
0040: import org.xml.sax.InputSource;
0041:
0042: /**
0043: * TODO: This really needs to be container ready
0044: * @author jgarnett
0045: *
0046: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/main/src/main/java/org/geotools/styling/SLDParser.java $
0047: */
0048: public class SLDParser {
0049:
0050: private static final java.util.logging.Logger LOGGER = org.geotools.util.logging.Logging
0051: .getLogger("org.geotools.styling");
0052:
0053: private FilterFactory ff;
0054:
0055: // protected java.io.InputStream instream;
0056: protected InputSource source;
0057:
0058: private org.w3c.dom.Document dom;
0059:
0060: protected StyleFactory factory;
0061:
0062: private String graphicSt = "Graphic"; // to make pmd to shut up
0063:
0064: private String geomSt = "Geometry"; // to make pmd to shut up
0065:
0066: private String fillSt = "Fill";
0067:
0068: /** useful for detecting relative onlineresources */
0069: private URL sourceUrl;
0070:
0071: /**
0072: * Create a Stylereader - use if you already have a dom to parse.
0073: *
0074: * @param factory
0075: * The StyleFactory to use to build the style
0076: */
0077: public SLDParser(StyleFactory factory) {
0078: this (factory, CommonFactoryFinder.getFilterFactory(GeoTools
0079: .getDefaultHints()));
0080: }
0081:
0082: public SLDParser(StyleFactory factory, FilterFactory filterFactory) {
0083: this .factory = factory;
0084: this .ff = filterFactory;
0085: }
0086:
0087: /**
0088: * Creates a new instance of SLDStyler
0089: *
0090: * @param factory
0091: * The StyleFactory to use to read the file
0092: * @param filename
0093: * The file to be read.
0094: *
0095: * @throws java.io.FileNotFoundException -
0096: * if the file is missing
0097: */
0098: public SLDParser(StyleFactory factory, String filename)
0099: throws java.io.FileNotFoundException {
0100: this (factory);
0101:
0102: File f = new File(filename);
0103: setInput(f);
0104: }
0105:
0106: /**
0107: * Creates a new SLDStyle object.
0108: *
0109: * @param factory
0110: * The StyleFactory to use to read the file
0111: * @param f
0112: * the File to be read
0113: *
0114: * @throws java.io.FileNotFoundException -
0115: * if the file is missing
0116: */
0117: public SLDParser(StyleFactory factory, File f)
0118: throws java.io.FileNotFoundException {
0119: this (factory);
0120: setInput(f);
0121: }
0122:
0123: /**
0124: * Creates a new SLDStyle object.
0125: *
0126: * @param factory
0127: * The StyleFactory to use to read the file
0128: * @param url
0129: * the URL to be read.
0130: *
0131: * @throws java.io.IOException -
0132: * if something goes wrong reading the file
0133: */
0134: public SLDParser(StyleFactory factory, java.net.URL url)
0135: throws java.io.IOException {
0136: this (factory);
0137: setInput(url);
0138: }
0139:
0140: /**
0141: * Creates a new SLDStyle object.
0142: *
0143: * @param factory
0144: * The StyleFactory to use to read the file
0145: * @param s
0146: * The inputstream to be read
0147: */
0148: public SLDParser(StyleFactory factory, java.io.InputStream s) {
0149: this (factory);
0150: setInput(s);
0151: }
0152:
0153: /**
0154: * Creates a new SLDStyle object.
0155: *
0156: * @param factory
0157: * The StyleFactory to use to read the file
0158: * @param r
0159: * The inputstream to be read
0160: */
0161: public SLDParser(StyleFactory factory, java.io.Reader r) {
0162: this (factory);
0163: setInput(r);
0164: }
0165:
0166: /**
0167: * set the file to read the SLD from
0168: *
0169: * @param filename
0170: * the file to read the SLD from
0171: *
0172: * @throws java.io.FileNotFoundException
0173: * if the file is missing
0174: */
0175: public void setInput(String filename)
0176: throws java.io.FileNotFoundException {
0177: File f = new File(filename);
0178: source = new InputSource(new java.io.FileInputStream(f));
0179: try {
0180: sourceUrl = f.toURL();
0181: } catch (MalformedURLException e) {
0182: LOGGER.warning("Can't build URL for file "
0183: + f.getAbsolutePath());
0184: }
0185: }
0186:
0187: /**
0188: * Sets the file to use to read the SLD from
0189: *
0190: * @param f
0191: * the file to use
0192: *
0193: * @throws java.io.FileNotFoundException
0194: * if the file is missing
0195: */
0196: public void setInput(File f) throws java.io.FileNotFoundException {
0197: source = new InputSource(new java.io.FileInputStream(f));
0198: try {
0199: sourceUrl = f.toURL();
0200: } catch (MalformedURLException e) {
0201: LOGGER.warning("Can't build URL for file "
0202: + f.getAbsolutePath());
0203: }
0204: }
0205:
0206: /**
0207: * sets an URL to read the SLD from
0208: *
0209: * @param url
0210: * the url to read the SLD from
0211: *
0212: * @throws java.io.IOException
0213: * If anything goes wrong opening the url
0214: */
0215: public void setInput(java.net.URL url) throws java.io.IOException {
0216: source = new InputSource(url.openStream());
0217: sourceUrl = url;
0218: }
0219:
0220: /**
0221: * Sets the input stream to read the SLD from
0222: *
0223: * @param in
0224: * the inputstream used to read the SLD from
0225: */
0226: public void setInput(java.io.InputStream in) {
0227: source = new InputSource(in);
0228: }
0229:
0230: /**
0231: * Sets the input stream to read the SLD from
0232: *
0233: * @param in
0234: * the inputstream used to read the SLD from
0235: */
0236: public void setInput(java.io.Reader in) {
0237: source = new InputSource(in);
0238: }
0239:
0240: /**
0241: * Read the xml inputsource provided and create a Style object for each user
0242: * style found
0243: *
0244: * @return Style[] the styles constructed.
0245: *
0246: * @throws RuntimeException
0247: * if a parsing error occurs
0248: */
0249: public Style[] readXML() {
0250: javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory
0251: .newInstance();
0252: dbf.setNamespaceAware(true);
0253: try {
0254: javax.xml.parsers.DocumentBuilder db = dbf
0255: .newDocumentBuilder();
0256: dom = db.parse(source);
0257: } catch (javax.xml.parsers.ParserConfigurationException pce) {
0258: throw new RuntimeException(pce);
0259: } catch (org.xml.sax.SAXException se) {
0260: throw new RuntimeException(se);
0261: } catch (java.io.IOException ie) {
0262: throw new RuntimeException(ie);
0263: }
0264:
0265: return readDOM(dom);
0266: }
0267:
0268: /**
0269: * Read the DOM provided and create a Style object for each user style found
0270: *
0271: * @param document
0272: * a dom containing the SLD
0273: *
0274: * @return Style[] the styles constructed.
0275: */
0276: public Style[] readDOM(org.w3c.dom.Document document) {
0277: this .dom = document;
0278:
0279: // for our next trick do something with the dom.
0280: NodeList nodes = findElements(document, "UserStyle");
0281:
0282: if (nodes == null)
0283: return new Style[0];
0284:
0285: Style[] styles = new Style[nodes.getLength()];
0286:
0287: for (int i = 0; i < nodes.getLength(); i++) {
0288: styles[i] = parseStyle(nodes.item(i));
0289: }
0290:
0291: return styles;
0292: }
0293:
0294: /**
0295: * @param document
0296: * @param name
0297: */
0298: private NodeList findElements(final org.w3c.dom.Document document,
0299: final String name) {
0300: NodeList nodes = document.getElementsByTagNameNS("*", name);
0301:
0302: if (nodes.getLength() == 0) {
0303: nodes = document.getElementsByTagName(name);
0304: }
0305:
0306: return nodes;
0307: }
0308:
0309: private NodeList findElements(final org.w3c.dom.Element element,
0310: final String name) {
0311: NodeList nodes = element.getElementsByTagNameNS("*", name);
0312:
0313: if (nodes.getLength() == 0) {
0314: nodes = element.getElementsByTagName(name);
0315: }
0316:
0317: return nodes;
0318: }
0319:
0320: public StyledLayerDescriptor parseSLD() {
0321: javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory
0322: .newInstance();
0323: dbf.setNamespaceAware(true);
0324:
0325: try {
0326: javax.xml.parsers.DocumentBuilder db = dbf
0327: .newDocumentBuilder();
0328: dom = db.parse(source);
0329: // for our next trick do something with the dom.
0330:
0331: //NodeList nodes = findElements(dom, "StyledLayerDescriptor");
0332:
0333: StyledLayerDescriptor sld = parseDescriptor(dom
0334: .getDocumentElement());// should only be one per file
0335: return sld;
0336:
0337: } catch (javax.xml.parsers.ParserConfigurationException pce) {
0338: throw new RuntimeException(pce);
0339: } catch (org.xml.sax.SAXException se) {
0340: throw new RuntimeException(se);
0341: } catch (java.io.IOException ie) {
0342: throw new RuntimeException(ie);
0343: }
0344: }
0345:
0346: public StyledLayerDescriptor parseDescriptor(Node root) {
0347: StyledLayerDescriptor sld = factory
0348: .createStyledLayerDescriptor();
0349: // StyledLayer layer = null;
0350: // LineSymbolizer symbol = factory.createLineSymbolizer();
0351:
0352: NodeList children = root.getChildNodes();
0353:
0354: for (int i = 0; i < children.getLength(); i++) {
0355: Node child = children.item(i);
0356: if ((child == null)
0357: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0358: continue;
0359: }
0360: String childName = child.getLocalName();
0361: if (childName == null) {
0362: childName = child.getNodeName();
0363: }
0364: if (childName.equalsIgnoreCase("Name")) {
0365: sld.setName(child.getFirstChild().getNodeValue());
0366: }
0367:
0368: if (childName.equalsIgnoreCase("Title")) {
0369: sld.setTitle(child.getFirstChild().getNodeValue());
0370: }
0371:
0372: if (childName.equalsIgnoreCase("Abstract")) {
0373: sld.setAbstract(child.getFirstChild().getNodeValue());
0374: }
0375:
0376: if (childName.equalsIgnoreCase("NamedLayer")) {
0377: NamedLayer layer = parseNamedLayer(child);
0378: sld.addStyledLayer(layer);
0379: }
0380:
0381: if (childName.equalsIgnoreCase("UserLayer")) {
0382: StyledLayer layer = parseUserLayer(child);
0383: sld.addStyledLayer(layer);
0384: }
0385: }
0386:
0387: return sld;
0388: }
0389:
0390: private StyledLayer parseUserLayer(Node root) {
0391: UserLayer layer = new UserLayerImpl();
0392: // LineSymbolizer symbol = factory.createLineSymbolizer();
0393:
0394: NodeList children = root.getChildNodes();
0395: List layerFeatureConstraints = new ArrayList();
0396: for (int i = 0; i < children.getLength(); i++) {
0397: Node child = children.item(i);
0398: if ((child == null)
0399: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0400: continue;
0401: }
0402: String childName = child.getLocalName();
0403: if (childName == null) {
0404: childName = child.getNodeName();
0405: }
0406: if (childName.equalsIgnoreCase("InlineFeature")) {
0407: parseInlineFeature(child, layer);
0408: }
0409: if (childName.equalsIgnoreCase("UserStyle")) {
0410: Style user = parseStyle(child);
0411: layer.addUserStyle(user);
0412: }
0413:
0414: if (childName.equalsIgnoreCase("Name")) {
0415: String layerName = child.getFirstChild().getNodeValue();
0416: layer.setName(layerName);
0417: LOGGER.info("layer name: " + layer.getName());
0418: }
0419:
0420: if (childName.equalsIgnoreCase("RemoteOWS")) {
0421: RemoteOWS remoteOws = parseRemoteOWS(child);
0422: layer.setRemoteOWS(remoteOws);
0423: }
0424:
0425: if (childName.equalsIgnoreCase("LayerFeatureConstraints")) {
0426: layer
0427: .setLayerFeatureConstraints(parseLayerFeatureConstraints(child));
0428: }
0429:
0430: }
0431:
0432: return layer;
0433: }
0434:
0435: private FeatureTypeConstraint[] parseLayerFeatureConstraints(
0436: Node root) {
0437: List featureTypeConstraints = new ArrayList();
0438:
0439: NodeList children = root.getChildNodes();
0440: for (int i = 0; i < children.getLength(); i++) {
0441: Node child = children.item(i);
0442: if ((child == null)
0443: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0444: continue;
0445: }
0446: String childName = child.getLocalName();
0447: if (childName.equalsIgnoreCase("FeatureTypeConstraint")) {
0448: final FeatureTypeConstraint ftc = parseFeatureTypeConstraint(child);
0449: if (ftc != null)
0450: featureTypeConstraints.add(ftc);
0451: }
0452: }
0453: return (FeatureTypeConstraint[]) featureTypeConstraints
0454: .toArray(new FeatureTypeConstraint[featureTypeConstraints
0455: .size()]);
0456: }
0457:
0458: private FeatureTypeConstraint parseFeatureTypeConstraint(Node root) {
0459: FeatureTypeConstraint ftc = new FeatureTypeConstraintImpl();
0460:
0461: NodeList children = root.getChildNodes();
0462: for (int i = 0; i < children.getLength(); i++) {
0463: Node child = children.item(i);
0464: if ((child == null)
0465: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0466: continue;
0467: }
0468: String childName = child.getLocalName();
0469: if (childName.equalsIgnoreCase("FeatureTypeName")) {
0470: ftc.setFeatureTypeName(child.getFirstChild()
0471: .getNodeValue());
0472: } else if (childName.equalsIgnoreCase("Filter")) {
0473: ftc.setFilter(parseFilter(child));
0474: }
0475: }
0476: ftc.setExtents(new Extent[0]);
0477: if (ftc.getFeatureTypeName() == null)
0478: return null;
0479: else
0480: return ftc;
0481: }
0482:
0483: private RemoteOWS parseRemoteOWS(Node root) {
0484: RemoteOWS ows = new RemoteOWSImpl();
0485:
0486: NodeList children = root.getChildNodes();
0487: for (int i = 0; i < children.getLength(); i++) {
0488: Node child = children.item(i);
0489: if ((child == null)
0490: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0491: continue;
0492: }
0493: String childName = child.getLocalName();
0494:
0495: if (childName.equalsIgnoreCase("Service")) {
0496: ows.setService(child.getFirstChild().getNodeValue());
0497: } else if (childName.equalsIgnoreCase("OnlineResource")) {
0498: ows.setOnlineResource(parseOnlineResource(child));
0499: }
0500: }
0501: return ows;
0502: }
0503:
0504: /**
0505: *
0506: * @param child
0507: * @param layer
0508: */
0509: private void parseInlineFeature(Node root, UserLayer layer) {
0510: try {
0511: SLDInlineFeatureParser inparser = new SLDInlineFeatureParser(
0512: root);
0513: layer.setInlineFeatureDatastore(inparser.dataStore);
0514: layer.setInlineFeatureType(inparser.featureType);
0515: } catch (Exception e) {
0516: throw (IllegalArgumentException) new IllegalArgumentException()
0517: .initCause(e);
0518: }
0519:
0520: }
0521:
0522: /**
0523: * Parses a NamedLayer.
0524: * <p>
0525: * The NamedLayer schema is:
0526: * <pre><code>
0527: * <xsd:element name="NamedLayer">
0528: * <xsd:annotation>
0529: * <xsd:documentation> A NamedLayer is a layer of data that has a name advertised by a WMS. </xsd:documentation>
0530: * </xsd:annotation>
0531: * <xsd:complexType>
0532: * <xsd:sequence>
0533: * <xsd:element ref="sld:Name"/>
0534: * <xsd:element ref="sld:LayerFeatureConstraints" minOccurs="0"/>
0535: * <xsd:choice minOccurs="0" maxOccurs="unbounded">
0536: * <xsd:element ref="sld:NamedStyle"/>
0537: * <xsd:element ref="sld:UserStyle"/>
0538: * </xsd:choice>
0539: * </xsd:sequence>
0540: * </xsd:complexType>
0541: * </xsd:element>
0542: * </code></pre>
0543: * </p>
0544: * @param root
0545: */
0546: private NamedLayer parseNamedLayer(Node root) {
0547: NamedLayer layer = new NamedLayerImpl();
0548:
0549: NodeList children = root.getChildNodes();
0550:
0551: for (int i = 0; i < children.getLength(); i++) {
0552: Node child = children.item(i);
0553: if ((child == null)
0554: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0555: continue;
0556: }
0557: String childName = child.getLocalName();
0558: if (childName == null) {
0559: childName = child.getNodeName();
0560: }
0561:
0562: if (childName.equalsIgnoreCase("Name")) {
0563: layer.setName(child.getFirstChild().getNodeValue());
0564: }
0565:
0566: if (childName.equalsIgnoreCase("NamedStyle")) {
0567: NamedStyle style = parseNamedStyle(child);
0568: layer.addStyle(style);
0569: }
0570:
0571: if (childName.equalsIgnoreCase("UserStyle")) {
0572: Style user = parseStyle(child);
0573: layer.addStyle(user);
0574: }
0575:
0576: if (childName.equalsIgnoreCase("LayerFeatureConstraints")) {
0577: throw new UnsupportedOperationException(
0578: "LayerFeatureConstraints pending of implementation");
0579: }
0580: }
0581:
0582: return layer;
0583: }
0584:
0585: /**
0586: * Parses a NamedStyle from node.
0587: * <p>
0588: * A NamedStyle is used to refer to a style that has a name in a WMS,
0589: * and is defined as:
0590: * <pre><code>
0591: * <xsd:element name="NamedStyle">
0592: * <xsd:annotation>
0593: * <xsd:documentation> A NamedStyle is used to refer to a style that has a name in a WMS. </xsd:documentation>
0594: * </xsd:annotation>
0595: * <xsd:complexType>
0596: * <xsd:sequence>
0597: * <xsd:element ref="sld:Name"/>
0598: * </xsd:sequence>
0599: * </xsd:complexType>
0600: * </xsd:element>
0601: * </code></pre>
0602: * </p>
0603: * @param n
0604: */
0605: public NamedStyle parseNamedStyle(Node n) {
0606: if (dom == null) {
0607: try {
0608: javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory
0609: .newInstance();
0610: javax.xml.parsers.DocumentBuilder db = dbf
0611: .newDocumentBuilder();
0612: dom = db.newDocument();
0613: } catch (javax.xml.parsers.ParserConfigurationException pce) {
0614: throw new RuntimeException(pce);
0615: }
0616: }
0617:
0618: NamedStyle style = factory.createNamedStyle();
0619:
0620: NodeList children = n.getChildNodes();
0621:
0622: if (LOGGER.isLoggable(Level.FINEST)) {
0623: LOGGER.finest("" + children.getLength()
0624: + " children to process");
0625: }
0626:
0627: for (int j = 0; j < children.getLength(); j++) {
0628: Node child = children.item(j);
0629:
0630: if ((child == null)
0631: || (child.getNodeType() != Node.ELEMENT_NODE)
0632: || (child.getFirstChild() == null)) {
0633: continue;
0634: }
0635: if (LOGGER.isLoggable(Level.FINEST)) {
0636: LOGGER.finest("processing " + child.getLocalName());
0637: }
0638: String childName = child.getLocalName();
0639: if (childName == null) {
0640: childName = child.getNodeName();
0641: }
0642: if (childName.equalsIgnoreCase("Name")) {
0643: style.setName(child.getFirstChild().getNodeValue());
0644: }
0645: }
0646: return style;
0647: }
0648:
0649: /**
0650: *
0651: * @param root
0652: * @deprecated this method is not being used
0653: */
0654: private StyledLayerImpl parseLayer(Node root) {
0655: StyledLayerImpl layer = null;
0656: // LineSymbolizer symbol = factory.createLineSymbolizer();
0657:
0658: NodeList children = root.getChildNodes();
0659:
0660: for (int i = 0; i < children.getLength(); i++) {
0661: Node child = children.item(i);
0662:
0663: if ((child == null)
0664: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0665: continue;
0666: }
0667: String childName = child.getLocalName();
0668: if (childName == null) {
0669: childName = child.getNodeName();
0670: }
0671: if (childName.equalsIgnoreCase("NamedLayer")) {
0672: layer = new NamedLayerImpl();
0673: }
0674:
0675: if (childName.equalsIgnoreCase("UserLayer")) {
0676:
0677: layer = new UserLayerImpl();
0678:
0679: // symbol.setStroke(parseStroke(child));
0680: }
0681: }
0682:
0683: return layer;
0684: }
0685:
0686: /**
0687: * build a style for the Node provided
0688: *
0689: * @param n
0690: * the node which contains the style to be parsed.
0691: *
0692: * @return the Style constructed.
0693: *
0694: * @throws RuntimeException
0695: * if an error occurs setting up the parser
0696: */
0697: public Style parseStyle(Node n) {
0698: if (dom == null) {
0699: try {
0700: javax.xml.parsers.DocumentBuilderFactory dbf = javax.xml.parsers.DocumentBuilderFactory
0701: .newInstance();
0702: javax.xml.parsers.DocumentBuilder db = dbf
0703: .newDocumentBuilder();
0704: dom = db.newDocument();
0705: } catch (javax.xml.parsers.ParserConfigurationException pce) {
0706: throw new RuntimeException(pce);
0707: }
0708: }
0709:
0710: Style style = factory.createStyle();
0711:
0712: NodeList children = n.getChildNodes();
0713:
0714: if (LOGGER.isLoggable(Level.FINEST)) {
0715: LOGGER.finest("" + children.getLength()
0716: + " children to process");
0717: }
0718:
0719: for (int j = 0; j < children.getLength(); j++) {
0720: Node child = children.item(j);
0721:
0722: if ((child == null)
0723: || (child.getNodeType() != Node.ELEMENT_NODE)
0724: || (child.getFirstChild() == null)) {
0725: continue;
0726: }
0727: // System.out.println("The child is: " + child.getNodeName() + " or
0728: // " + child.getLocalName() + " prefix is " +child.getPrefix());
0729: if (LOGGER.isLoggable(Level.FINEST)) {
0730: LOGGER.finest("processing " + child.getLocalName());
0731: }
0732: String childName = child.getLocalName();
0733: if (childName == null) {
0734: childName = child.getNodeName();
0735: }
0736: if (childName.equalsIgnoreCase("Name")) {
0737: style.setName(child.getFirstChild().getNodeValue());
0738: }
0739:
0740: if (childName.equalsIgnoreCase("Title")) {
0741: style.setTitle(child.getFirstChild().getNodeValue());
0742: }
0743:
0744: if (childName.equalsIgnoreCase("Abstract")) {
0745: style.setAbstract(child.getFirstChild().getNodeValue());
0746: }
0747:
0748: if (childName.equalsIgnoreCase("IsDefault")) {
0749: style.setDefault(Boolean.valueOf(
0750: child.getFirstChild().getNodeValue())
0751: .booleanValue());
0752: }
0753:
0754: if (childName.equalsIgnoreCase("FeatureTypeStyle")) {
0755: style.addFeatureTypeStyle(parseFeatureTypeStyle(child));
0756: }
0757: }
0758:
0759: return style;
0760: }
0761:
0762: private FeatureTypeStyle parseFeatureTypeStyle(Node style) {
0763: if (LOGGER.isLoggable(Level.FINEST)) {
0764: LOGGER.finest("Parsing featuretype style "
0765: + style.getLocalName());
0766: }
0767:
0768: FeatureTypeStyle ft = factory.createFeatureTypeStyle();
0769:
0770: ArrayList rules = new ArrayList();
0771: ArrayList sti = new ArrayList();
0772: NodeList children = style.getChildNodes();
0773:
0774: for (int i = 0; i < children.getLength(); i++) {
0775: Node child = children.item(i);
0776:
0777: if ((child == null)
0778: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0779: continue;
0780: }
0781:
0782: if (LOGGER.isLoggable(Level.FINEST)) {
0783: LOGGER.finest("processing " + child.getLocalName());
0784: }
0785: String childName = child.getLocalName();
0786: if (childName == null) {
0787: childName = child.getNodeName();
0788: }
0789: if (childName.equalsIgnoreCase("Name")) {
0790: ft.setName(child.getFirstChild().getNodeValue());
0791: }
0792:
0793: if (childName.equalsIgnoreCase("Title")) {
0794: ft.setTitle(child.getFirstChild().getNodeValue());
0795: }
0796:
0797: if (childName.equalsIgnoreCase("Abstract")) {
0798: ft.setAbstract(child.getFirstChild().getNodeValue());
0799: }
0800:
0801: if (childName.equalsIgnoreCase("FeatureTypeName")) {
0802: ft.setFeatureTypeName(child.getFirstChild()
0803: .getNodeValue());
0804: }
0805:
0806: if (childName.equalsIgnoreCase("SemanticTypeIdentifier")) {
0807: sti.add(child.getFirstChild().getNodeValue());
0808: }
0809:
0810: if (childName.equalsIgnoreCase("Rule")) {
0811: rules.add(parseRule(child));
0812: }
0813: }
0814:
0815: if (sti.size() > 0) {
0816: ft.setSemanticTypeIdentifiers((String[]) sti
0817: .toArray(new String[0]));
0818: }
0819: ft.setRules((Rule[]) rules.toArray(new Rule[0]));
0820:
0821: return ft;
0822: }
0823:
0824: private Rule parseRule(Node ruleNode) {
0825: if (LOGGER.isLoggable(Level.FINEST)) {
0826: LOGGER.finest("Parsing rule " + ruleNode.getLocalName());
0827: }
0828:
0829: Rule rule = factory.createRule();
0830: ArrayList symbolizers = new ArrayList();
0831: NodeList children = ruleNode.getChildNodes();
0832:
0833: for (int i = 0; i < children.getLength(); i++) {
0834: Node child = children.item(i);
0835:
0836: if ((child == null)
0837: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0838: continue;
0839: }
0840: String childName = child.getLocalName();
0841: if (childName == null) {
0842: childName = child.getNodeName();
0843: }
0844:
0845: if (childName.indexOf(':') != -1) {
0846: //the DOM parser wasnt properly set to handle namespaces...
0847: childName = childName
0848: .substring(childName.indexOf(':') + 1);
0849: }
0850:
0851: if (LOGGER.isLoggable(Level.FINEST)) {
0852: LOGGER.finest("processing " + child.getLocalName());
0853: }
0854:
0855: if (childName.equalsIgnoreCase("Name")) {
0856: rule.setName(child.getFirstChild().getNodeValue());
0857: }
0858:
0859: if (childName.equalsIgnoreCase("Title")) {
0860: rule.setTitle(child.getFirstChild().getNodeValue());
0861: }
0862:
0863: if (childName.equalsIgnoreCase("Abstract")) {
0864: rule.setAbstract(child.getFirstChild().getNodeValue());
0865: }
0866:
0867: if (childName.equalsIgnoreCase("MinScaleDenominator")) {
0868: rule.setMinScaleDenominator(Double.parseDouble(child
0869: .getFirstChild().getNodeValue()));
0870: }
0871:
0872: if (childName.equalsIgnoreCase("MaxScaleDenominator")) {
0873: rule.setMaxScaleDenominator(Double.parseDouble(child
0874: .getFirstChild().getNodeValue()));
0875: }
0876:
0877: if (childName.equalsIgnoreCase("Filter")) {
0878: Filter filter = parseFilter(child);
0879: rule.setFilter(filter);
0880: }
0881:
0882: if (childName.equalsIgnoreCase("ElseFilter")) {
0883: rule.setIsElseFilter(true);
0884: }
0885:
0886: if (childName.equalsIgnoreCase("LegendGraphic")) {
0887: findElements(((Element) child), graphicSt);
0888: NodeList g = findElements(((Element) child), graphicSt);
0889: ArrayList legends = new ArrayList();
0890:
0891: for (int k = 0; k < g.getLength(); k++) {
0892: legends.add(parseGraphic(g.item(k)));
0893: }
0894:
0895: rule.setLegendGraphic((Graphic[]) legends
0896: .toArray(new Graphic[0]));
0897: }
0898:
0899: if (childName.equalsIgnoreCase("LineSymbolizer")) {
0900: symbolizers.add(parseLineSymbolizer(child));
0901: }
0902:
0903: if (childName.equalsIgnoreCase("PolygonSymbolizer")) {
0904: symbolizers.add(parsePolygonSymbolizer(child));
0905: }
0906:
0907: if (childName.equalsIgnoreCase("PointSymbolizer")) {
0908: symbolizers.add(parsePointSymbolizer(child));
0909: }
0910:
0911: if (childName.equalsIgnoreCase("TextSymbolizer")) {
0912: symbolizers.add(parseTextSymbolizer(child));
0913: }
0914:
0915: if (childName.equalsIgnoreCase("RasterSymbolizer")) {
0916: symbolizers.add(parseRasterSymbolizer(child));
0917: }
0918: }
0919:
0920: rule.setSymbolizers((Symbolizer[]) symbolizers
0921: .toArray(new Symbolizer[0]));
0922:
0923: return rule;
0924: }
0925:
0926: private Filter parseFilter(Node child) {
0927: // this sounds stark raving mad, but this is actually how the dom parser works...
0928: // instead of passing in the parent element, pass in the first child and its
0929: // siblings will also be parsed
0930: Node firstChild = child.getFirstChild();
0931: while (firstChild != null
0932: && firstChild.getNodeType() != Node.ELEMENT_NODE) {
0933: //advance to the first actual element (rather than whitespace)
0934: firstChild = firstChild.getNextSibling();
0935: }
0936: Filter filter = org.geotools.filter.FilterDOMParser
0937: .parseFilter(firstChild);
0938: return filter;
0939: }
0940:
0941: /**
0942: * parses the SLD for a linesymbolizer
0943: *
0944: * @param root
0945: * a w2c Dom Node
0946: *
0947: * @return the linesymbolizer
0948: */
0949: private LineSymbolizer parseLineSymbolizer(Node root) {
0950: LineSymbolizer symbol = factory.createLineSymbolizer();
0951: NodeList children = root.getChildNodes();
0952:
0953: for (int i = 0; i < children.getLength(); i++) {
0954: Node child = children.item(i);
0955:
0956: if ((child == null)
0957: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0958: continue;
0959: }
0960: String childName = child.getLocalName();
0961: if (childName == null) {
0962: childName = child.getNodeName();
0963: }
0964: if (childName.equalsIgnoreCase(geomSt)) {
0965: symbol
0966: .setGeometryPropertyName(parseGeometryName(child));
0967: }
0968:
0969: if (childName.equalsIgnoreCase("Stroke")) {
0970: symbol.setStroke(parseStroke(child));
0971: }
0972: }
0973:
0974: return symbol;
0975: }
0976:
0977: /**
0978: * parses the SLD for a polygonsymbolizer
0979: *
0980: * @param root
0981: * w3c dom node
0982: *
0983: * @return the polygon symbolizer
0984: */
0985: private PolygonSymbolizer parsePolygonSymbolizer(Node root) {
0986: PolygonSymbolizer symbol = factory.createPolygonSymbolizer();
0987: symbol.setFill((Fill) null);
0988: symbol.setStroke((Stroke) null);
0989:
0990: NodeList children = root.getChildNodes();
0991:
0992: for (int i = 0; i < children.getLength(); i++) {
0993: Node child = children.item(i);
0994:
0995: if ((child == null)
0996: || (child.getNodeType() != Node.ELEMENT_NODE)) {
0997: continue;
0998: }
0999: String childName = child.getLocalName();
1000: if (childName == null) {
1001: childName = child.getNodeName();
1002: }
1003: if (childName.equalsIgnoreCase(geomSt)) {
1004: symbol
1005: .setGeometryPropertyName(parseGeometryName(child));
1006: }
1007:
1008: if (childName.equalsIgnoreCase("Stroke")) {
1009: symbol.setStroke(parseStroke(child));
1010: }
1011:
1012: if (childName.equalsIgnoreCase(fillSt)) {
1013: symbol.setFill(parseFill(child));
1014: }
1015: }
1016:
1017: return symbol;
1018: }
1019:
1020: /**
1021: * parses the SLD for a text symbolizer
1022: *
1023: * @param root
1024: * w3c dom node
1025: *
1026: * @return the TextSymbolizer
1027: */
1028: private TextSymbolizer parseTextSymbolizer(Node root) {
1029: TextSymbolizer symbol = factory.createTextSymbolizer();
1030: symbol.setFill(null);
1031:
1032: ArrayList fonts = new ArrayList();
1033: NodeList children = root.getChildNodes();
1034:
1035: for (int i = 0; i < children.getLength(); i++) {
1036: Node child = children.item(i);
1037:
1038: if ((child == null)
1039: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1040: continue;
1041: }
1042: String childName = child.getLocalName();
1043: if (childName == null) {
1044: childName = child.getNodeName();
1045: }
1046: if (childName.equalsIgnoreCase(geomSt)) {
1047: symbol
1048: .setGeometryPropertyName(parseGeometryName(child));
1049: }
1050:
1051: if (childName.equalsIgnoreCase(fillSt)) {
1052: symbol.setFill(parseFill(child));
1053: }
1054:
1055: if (childName.equalsIgnoreCase("Label")) {
1056: LOGGER.finest("parsing label " + child.getNodeValue());
1057: // the label parser should preserve whitespaces, so
1058: // we call parseCssParameter with trimWhiteSpace=false
1059: symbol.setLabel(parseCssParameter(child, false));
1060: if (symbol.getLabel() == null) {
1061: LOGGER
1062: .warning("parsing TextSymbolizer node - couldnt find anything in the Label element!");
1063: }
1064: }
1065:
1066: if (childName.equalsIgnoreCase("Font")) {
1067: fonts.add(parseFont(child));
1068: }
1069:
1070: if (childName.equalsIgnoreCase("LabelPlacement")) {
1071: symbol.setPlacement(parseLabelPlacement(child));
1072: }
1073:
1074: if (childName.equalsIgnoreCase("Halo")) {
1075: symbol.setHalo(parseHalo(child));
1076: }
1077: if (childName.equalsIgnoreCase("Graphic")) {
1078: if (LOGGER.isLoggable(Level.FINEST)) {
1079: LOGGER
1080: .finest("Parsing non-standard Graphic in TextSymbolizer");
1081: }
1082: if (symbol instanceof TextSymbolizer2) {
1083: ((TextSymbolizer2) symbol)
1084: .setGraphic(parseGraphic(child));
1085: }
1086: }
1087:
1088: if (childName.equalsIgnoreCase("priority")) {
1089: symbol.setPriority(parseCssParameter(child));
1090: }
1091: if (childName.equalsIgnoreCase("vendoroption")) {
1092: parseVendorOption(symbol, child);
1093: }
1094:
1095: }
1096:
1097: symbol.setFonts((Font[]) fonts.toArray(new Font[0]));
1098:
1099: return symbol;
1100: }
1101:
1102: /**
1103: * adds the key/value pair from the node ("<VendorOption name="...">...</VendorOption>").
1104: * This can be generalized for other symbolizers in the future
1105: * @param symbol
1106: * @param child
1107: */
1108: private void parseVendorOption(TextSymbolizer symbol, Node child) {
1109: String key = child.getAttributes().getNamedItem("name")
1110: .getNodeValue();
1111: String value = child.getFirstChild().getNodeValue();
1112:
1113: symbol.addToOptions(key, value);
1114: }
1115:
1116: private Expression parseLiteral(Node root) {
1117: NodeList children = root.getChildNodes();
1118: for (int i = 0; i < children.getLength(); i++) {
1119: Node child = children.item(i);
1120: if ((child == null)
1121: || child.getNodeType() != Node.ELEMENT_NODE) {
1122: continue;
1123: }
1124: String childName = child.getLocalName();
1125: if (childName == null) {
1126: childName = child.getNodeName();
1127: }
1128: if (childName.equalsIgnoreCase("Literal")) {
1129: try {
1130: return (Expression) ExpressionBuilder.parse(child
1131: .getFirstChild().getNodeValue());
1132: } catch (Exception e) {
1133: // TODO: handle exception
1134: }
1135: }
1136: }
1137: return null;
1138: }
1139:
1140: /**
1141: * parses the SLD for a text symbolizer
1142: *
1143: * @param root
1144: * w3c dom node
1145: *
1146: * @return the TextSymbolizer
1147: */
1148: private RasterSymbolizer parseRasterSymbolizer(Node root) {
1149: RasterSymbolizer symbol = factory.getDefaultRasterSymbolizer();
1150: // symbol.setGraphic(null);
1151:
1152: NodeList children = root.getChildNodes();
1153:
1154: for (int i = 0; i < children.getLength(); i++) {
1155: Node child = children.item(i);
1156:
1157: if ((child == null)
1158: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1159: continue;
1160: }
1161: String childName = child.getLocalName();
1162: if (childName == null) {
1163: childName = child.getNodeName();
1164: }
1165:
1166: if (childName.equalsIgnoreCase(geomSt)) {
1167: symbol
1168: .setGeometryPropertyName(parseGeometryName(child));
1169: }
1170:
1171: if (childName.equalsIgnoreCase("Opacity")) {
1172: try {
1173: symbol
1174: .setOpacity((Expression) ExpressionBuilder
1175: .parse(child.getFirstChild()
1176: .getNodeValue()));
1177: } catch (Exception e) {
1178: // TODO: handle exception
1179: }
1180: }
1181:
1182: if (childName.equalsIgnoreCase("ChannelSelection")) {
1183: symbol
1184: .setChannelSelection(parseChannelSelection(child));
1185: }
1186:
1187: if (childName.equalsIgnoreCase("OverlapBehavior")) {
1188: try {
1189: symbol
1190: .setOverlap((Expression) ExpressionBuilder
1191: .parse(child.getFirstChild()
1192: .getNodeValue()));
1193: } catch (Exception e) {
1194: // TODO: handle exception
1195: }
1196: }
1197:
1198: if (childName.equalsIgnoreCase("ColorMap")) {
1199: symbol.setColorMap(parseColorMap(child));
1200: }
1201:
1202: if (childName.equalsIgnoreCase("ContrastEnhancement")) {
1203: symbol
1204: .setContrastEnhancement(parseContrastEnhancement(child));
1205: }
1206:
1207: if (childName.equalsIgnoreCase("ShadedRelief")) {
1208: symbol.setShadedRelief(parseShadedRelief(child));
1209: }
1210:
1211: if (childName.equalsIgnoreCase("ImageOutline")) {
1212: symbol.setImageOutline(parseLineSymbolizer(child));
1213: }
1214: }
1215:
1216: return symbol;
1217: }
1218:
1219: private ColorMapEntry parseColorMapEntry(Node root) {
1220: ColorMapEntry symbol = factory.createColorMapEntry();
1221:
1222: //Expression exp = null;
1223:
1224: NamedNodeMap atts = root.getAttributes();
1225:
1226: if (atts.getNamedItem("label") != null) {
1227: symbol.setLabel(atts.getNamedItem("label").getNodeValue());
1228: }
1229:
1230: if (atts.getNamedItem("color") != null) {
1231: symbol.setColor(ff.literal(atts.getNamedItem("color")
1232: .getNodeValue()));
1233: }
1234:
1235: if (atts.getNamedItem("opacity") != null) {
1236: symbol.setOpacity(ff.literal(atts.getNamedItem("opacity")
1237: .getNodeValue()));
1238: }
1239:
1240: if (atts.getNamedItem("quantity") != null) {
1241: symbol.setQuantity(ff.literal(atts.getNamedItem("quantity")
1242: .getNodeValue()));
1243: }
1244:
1245: return symbol;
1246: }
1247:
1248: private ColorMap parseColorMap(Node root) {
1249: ColorMap symbol = factory.createColorMap();
1250:
1251: NodeList children = root.getChildNodes();
1252:
1253: for (int i = 0; i < children.getLength(); i++) {
1254: Node child = children.item(i);
1255:
1256: if ((child == null)
1257: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1258: continue;
1259: }
1260: String childName = child.getLocalName();
1261: if (childName == null) {
1262: childName = child.getNodeName();
1263: }
1264:
1265: if (childName.equalsIgnoreCase("ColorMapEntry")) {
1266: symbol.addColorMapEntry(parseColorMapEntry(child));
1267: }
1268: }
1269:
1270: return symbol;
1271: }
1272:
1273: private SelectedChannelType parseSelectedChannel(Node root) {
1274: SelectedChannelType symbol = new SelectedChannelTypeImpl();
1275:
1276: NodeList children = root.getChildNodes();
1277:
1278: for (int i = 0; i < children.getLength(); i++) {
1279: Node child = children.item(i);
1280:
1281: if ((child == null)
1282: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1283: continue;
1284: }
1285: String childName = child.getLocalName();
1286: if (childName == null) {
1287: childName = child.getNodeName();
1288: }
1289:
1290: if (childName.equalsIgnoreCase("SourceChannelName")) {
1291: symbol.setChannelName(child.getNodeValue());
1292: }
1293:
1294: if (childName.equalsIgnoreCase("ContrastEnhancement")) {
1295: try {
1296: symbol
1297: .setContrastEnhancement((Expression) ExpressionBuilder
1298: .parse(child.getNodeValue()));
1299: } catch (Exception e) {
1300: // TODO: handle exception
1301: }
1302: }
1303: }
1304:
1305: return symbol;
1306: }
1307:
1308: private ChannelSelection parseChannelSelection(Node root) {
1309: List channels = new LinkedList();
1310:
1311: NodeList children = root.getChildNodes();
1312:
1313: for (int i = 0; i < children.getLength(); i++) {
1314: Node child = children.item(i);
1315:
1316: if ((child == null)
1317: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1318: continue;
1319: }
1320: String childName = child.getLocalName();
1321: if (childName == null) {
1322: childName = child.getNodeName();
1323: }
1324:
1325: if (childName.equalsIgnoreCase("GrayChannel")) {
1326: channels.add(parseSelectedChannel(child));
1327: }
1328:
1329: if (childName.equalsIgnoreCase("RedChannel")) {
1330: channels.add(parseSelectedChannel(child));
1331: }
1332:
1333: if (childName.equalsIgnoreCase("GreenChannel")) {
1334: channels.add(parseSelectedChannel(child));
1335: }
1336:
1337: if (childName.equalsIgnoreCase("BlueChannel")) {
1338: channels.add(parseSelectedChannel(child));
1339: }
1340: }
1341:
1342: ChannelSelection dap = factory
1343: .createChannelSelection((SelectedChannelType[]) channels
1344: .toArray(new SelectedChannelType[channels
1345: .size()]));
1346:
1347: return dap;
1348: }
1349:
1350: private ContrastEnhancement parseContrastEnhancement(Node root) {
1351: ContrastEnhancement symbol = new ContrastEnhancementImpl();
1352:
1353: NodeList children = root.getChildNodes();
1354:
1355: for (int i = 0; i < children.getLength(); i++) {
1356: Node child = children.item(i);
1357:
1358: if ((child == null)
1359: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1360: continue;
1361: }
1362: String childName = child.getLocalName();
1363: if (childName == null) {
1364: childName = child.getNodeName();
1365: }
1366: if (childName.equalsIgnoreCase("Normalize")) {
1367: symbol.setNormalize();
1368: }
1369:
1370: if (childName.equalsIgnoreCase("Histogram")) {
1371: symbol.setHistogram();
1372: }
1373:
1374: if (childName.equalsIgnoreCase("GammaValue")) {
1375: try {
1376: symbol.setGammaValue((Expression) ExpressionBuilder
1377: .parse(child.getNodeValue()));
1378: } catch (Exception e) {
1379: // TODO: handle exception
1380: }
1381: }
1382: }
1383:
1384: return symbol;
1385: }
1386:
1387: private ShadedRelief parseShadedRelief(Node root) {
1388: ShadedRelief symbol = new ShadedReliefImpl();
1389:
1390: NodeList children = root.getChildNodes();
1391:
1392: for (int i = 0; i < children.getLength(); i++) {
1393: Node child = children.item(i);
1394:
1395: if ((child == null)
1396: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1397: continue;
1398: }
1399: String childName = child.getLocalName();
1400: if (childName == null) {
1401: childName = child.getNodeName();
1402: }
1403: if (childName.equalsIgnoreCase("BrightnessOnly")) {
1404: symbol.setBrightnessOnly(Boolean.getBoolean(child
1405: .getFirstChild().getNodeValue()));
1406: }
1407:
1408: if (childName.equalsIgnoreCase("ReliefFactor")) {
1409: try {
1410: symbol
1411: .setReliefFactor((Expression) ExpressionBuilder
1412: .parse(child.getNodeValue()));
1413: } catch (Exception e) {
1414: // TODO: handle exception
1415: }
1416: }
1417: }
1418:
1419: return symbol;
1420: }
1421:
1422: /**
1423: * parses the SLD for a point symbolizer
1424: *
1425: * @param root
1426: * a w3c dom node
1427: *
1428: * @return the pointsymbolizer
1429: */
1430: private PointSymbolizer parsePointSymbolizer(Node root) {
1431: PointSymbolizer symbol = factory.getDefaultPointSymbolizer();
1432: // symbol.setGraphic(null);
1433:
1434: NodeList children = root.getChildNodes();
1435:
1436: for (int i = 0; i < children.getLength(); i++) {
1437: Node child = children.item(i);
1438:
1439: if ((child == null)
1440: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1441: continue;
1442: }
1443: String childName = child.getLocalName();
1444: if (childName == null) {
1445: childName = child.getNodeName();
1446: }
1447: if (childName.equalsIgnoreCase(geomSt)) {
1448: symbol
1449: .setGeometryPropertyName(parseGeometryName(child));
1450: }
1451:
1452: if (childName.equalsIgnoreCase(graphicSt)) {
1453: symbol.setGraphic(parseGraphic(child));
1454: }
1455: }
1456:
1457: return symbol;
1458: }
1459:
1460: private Graphic parseGraphic(Node root) {
1461: if (LOGGER.isLoggable(Level.FINEST)) {
1462: LOGGER.finest("processing graphic " + root);
1463: }
1464:
1465: Graphic graphic = factory.getDefaultGraphic();
1466:
1467: NodeList children = root.getChildNodes();
1468:
1469: for (int i = 0; i < children.getLength(); i++) {
1470: Node child = children.item(i);
1471:
1472: if ((child == null)
1473: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1474: continue;
1475: }
1476: String childName = child.getLocalName();
1477: if (childName == null) {
1478: childName = child.getNodeName();
1479: }
1480: if (childName.equalsIgnoreCase(geomSt)) {
1481: graphic
1482: .setGeometryPropertyName(parseGeometryName(child));
1483: }
1484:
1485: if (childName.equalsIgnoreCase("ExternalGraphic")) {
1486: LOGGER.finest("parsing extgraphic " + child);
1487: graphic.addExternalGraphic(parseExternalGraphic(child));
1488: }
1489:
1490: if (childName.equalsIgnoreCase("Mark")) {
1491: graphic.addMark(parseMark(child));
1492: }
1493:
1494: if (childName.equalsIgnoreCase("opacity")) {
1495: graphic.setOpacity(parseCssParameter(child));
1496: }
1497:
1498: if (childName.equalsIgnoreCase("size")) {
1499: graphic.setSize(parseCssParameter(child));
1500: }
1501:
1502: if (childName.equalsIgnoreCase("displacement")) {
1503: graphic.setDisplacement(parseDisplacement(child));
1504: }
1505:
1506: if (childName.equalsIgnoreCase("rotation")) {
1507: graphic.setRotation(parseCssParameter(child));
1508: }
1509: }
1510:
1511: return graphic;
1512: }
1513:
1514: private String parseGeometryName(Node root) {
1515: if (LOGGER.isLoggable(Level.FINEST)) {
1516: LOGGER.finest("parsing GeometryName");
1517: }
1518:
1519: String ret = null;
1520: NodeList children = root.getChildNodes();
1521:
1522: for (int i = 0; i < children.getLength(); i++) {
1523: Node child = children.item(i);
1524:
1525: if ((child == null)
1526: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1527: continue;
1528: }
1529:
1530: ret = parseCssParameter(child).toString();
1531: }
1532:
1533: return ret;
1534: }
1535:
1536: private Mark parseMark(Node root) {
1537: if (LOGGER.isLoggable(Level.FINEST)) {
1538: LOGGER.finest("parsing mark");
1539: }
1540:
1541: Mark mark = factory.createMark();
1542: mark.setFill(null);
1543: mark.setStroke(null);
1544:
1545: NodeList children = root.getChildNodes();
1546:
1547: for (int i = 0; i < children.getLength(); i++) {
1548: Node child = children.item(i);
1549:
1550: if ((child == null)
1551: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1552: continue;
1553: }
1554: String childName = child.getLocalName();
1555: if (childName == null) {
1556: childName = child.getNodeName();
1557: }
1558: if (childName.equalsIgnoreCase("Stroke")) {
1559: mark.setStroke(parseStroke(child));
1560: }
1561:
1562: if (childName.equalsIgnoreCase(fillSt)) {
1563: mark.setFill(parseFill(child));
1564: }
1565:
1566: if (childName.equalsIgnoreCase("WellKnownName")) {
1567: LOGGER.finest("setting mark to "
1568: + child.getFirstChild().getNodeValue());
1569: mark.setWellKnownName(parseCssParameter(child));
1570: }
1571: }
1572:
1573: return mark;
1574: }
1575:
1576: private ExternalGraphic parseExternalGraphic(Node root) {
1577: if (LOGGER.isLoggable(Level.FINEST)) {
1578: LOGGER.finest("processing external graphic ");
1579: }
1580:
1581: String format = "";
1582: String uri = "";
1583: Map paramList = new HashMap();
1584:
1585: NodeList children = root.getChildNodes();
1586:
1587: for (int i = 0; i < children.getLength(); i++) {
1588: Node child = children.item(i);
1589:
1590: if ((child == null)
1591: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1592: continue;
1593: }
1594: String childName = child.getLocalName();
1595: if (childName == null) {
1596: childName = child.getNodeName();
1597: }
1598: if (childName.equalsIgnoreCase("OnLineResource")) {
1599: uri = parseOnlineResource(child);
1600: }
1601:
1602: if (childName.equalsIgnoreCase("format")) {
1603: LOGGER.finest("format child is " + child);
1604: LOGGER.finest("seting ExtGraph format "
1605: + child.getFirstChild().getNodeValue());
1606: format = (child.getFirstChild().getNodeValue());
1607: }
1608: if (childName.equalsIgnoreCase("customProperty")) {
1609: LOGGER.finest("custom child is " + child);
1610: String propName = child.getAttributes().getNamedItem(
1611: "name").getNodeValue();
1612: LOGGER
1613: .finest("seting custom property " + propName
1614: + " to "
1615: + child.getFirstChild().getNodeValue());
1616: Expression value = parseCssParameter(child);
1617: paramList.put(propName, value);
1618:
1619: }
1620: }
1621:
1622: URL url = null;
1623: try {
1624: url = new URL(uri);
1625: } catch (MalformedURLException mfe) {
1626: LOGGER.fine("Looks like " + uri + " is a relative path..");
1627: if (sourceUrl != null) {
1628: try {
1629: url = new URL(sourceUrl, uri);
1630: } catch (MalformedURLException e) {
1631: LOGGER.warning("can't parse " + uri
1632: + " as relative to"
1633: + sourceUrl.toExternalForm());
1634: }
1635: }
1636: }
1637:
1638: ExternalGraphic extgraph;
1639: if (url == null) {
1640: extgraph = factory.createExternalGraphic(uri, format);
1641: } else {
1642: extgraph = factory.createExternalGraphic(url, format);
1643: }
1644: extgraph.setCustomProperties(paramList);
1645: return extgraph;
1646: }
1647:
1648: private String parseOnlineResource(Node root) {
1649: Element param = (Element) root;
1650: org.w3c.dom.NamedNodeMap map = param.getAttributes();
1651:
1652: LOGGER.finest("attributes " + map.toString());
1653:
1654: for (int k = 0; k < map.getLength(); k++) {
1655: String res = map.item(k).getNodeValue();
1656: String name = map.item(k).getNodeName();
1657: // if(name == null){
1658: // name = map.item(k).getNodeName();
1659: // }
1660: if (LOGGER.isLoggable(Level.FINEST)) {
1661: LOGGER.finest("processing attribute " + name + "="
1662: + res);
1663: }
1664:
1665: // TODO: process the name space properly
1666: if (name.equalsIgnoreCase("xlink:href")) {
1667: LOGGER.finest("seting ExtGraph uri " + res);
1668: return res;
1669: }
1670: }
1671: return null;
1672: }
1673:
1674: private Stroke parseStroke(Node root) {
1675: Stroke stroke = factory.getDefaultStroke();
1676: NodeList list = findElements(((Element) root), "GraphicFill");
1677:
1678: if (list.getLength() > 0) {
1679: LOGGER.finest("stroke: found a graphic fill "
1680: + list.item(0));
1681:
1682: NodeList kids = list.item(0).getChildNodes();
1683:
1684: for (int i = 0; i < kids.getLength(); i++) {
1685: Node child = kids.item(i);
1686:
1687: if ((child == null)
1688: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1689: continue;
1690: }
1691: String childName = child.getLocalName();
1692: if (childName == null) {
1693: childName = child.getNodeName();
1694: }
1695: if (childName.equalsIgnoreCase(graphicSt)) {
1696: Graphic g = parseGraphic(child);
1697: LOGGER.finest("setting stroke graphicfill with "
1698: + g);
1699: stroke.setGraphicFill(g);
1700: }
1701: }
1702: }
1703:
1704: list = findElements(((Element) root), "GraphicStroke");
1705:
1706: if (list.getLength() > 0) {
1707: LOGGER.finest("stroke: found a graphic stroke "
1708: + list.item(0));
1709:
1710: NodeList kids = list.item(0).getChildNodes();
1711:
1712: for (int i = 0; i < kids.getLength(); i++) {
1713: Node child = kids.item(i);
1714:
1715: if ((child == null)
1716: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1717: continue;
1718: }
1719: String childName = child.getLocalName();
1720: if (childName == null) {
1721: childName = child.getNodeName();
1722: }
1723: if (childName.equalsIgnoreCase(graphicSt)) {
1724: Graphic g = parseGraphic(child);
1725: LOGGER.finest("setting stroke graphicStroke with "
1726: + g);
1727: stroke.setGraphicStroke(g);
1728: }
1729: }
1730: }
1731:
1732: list = findElements(((Element) root), "CssParameter");
1733:
1734: for (int i = 0; i < list.getLength(); i++) {
1735: Node child = list.item(i);
1736:
1737: if ((child == null)
1738: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1739: continue;
1740: }
1741:
1742: if (LOGGER.isLoggable(Level.FINEST)) {
1743: LOGGER.finest("now I am processing " + child);
1744: }
1745:
1746: Element param = (Element) child;
1747: org.w3c.dom.NamedNodeMap map = param.getAttributes();
1748:
1749: if (LOGGER.isLoggable(Level.FINEST)) {
1750: LOGGER.finest("attributes " + map.toString());
1751: }
1752:
1753: for (int k = 0; k < map.getLength(); k++) {
1754: String res = map.item(k).getNodeValue();
1755:
1756: if (LOGGER.isLoggable(Level.FINEST)) {
1757: LOGGER.finest("processing attribute " + res);
1758: }
1759:
1760: if (res.equalsIgnoreCase("stroke")) {
1761: stroke.setColor(parseCssParameter(child));
1762: }
1763:
1764: if (res.equalsIgnoreCase("width")
1765: || res.equalsIgnoreCase("stroke-width")) {
1766: stroke.setWidth(parseCssParameter(child));
1767: }
1768:
1769: if (res.equalsIgnoreCase("opacity")
1770: || res.equalsIgnoreCase("stroke-opacity")) {
1771: stroke.setOpacity(parseCssParameter(child));
1772: }
1773:
1774: if (res.equalsIgnoreCase("linecap")
1775: || res.equalsIgnoreCase("stroke-linecap")) {
1776: // since these are system-dependent just pass them through
1777: // and hope.
1778: stroke.setLineCap(parseCssParameter(child));
1779: }
1780:
1781: if (res.equalsIgnoreCase("linejoin")
1782: || res.equalsIgnoreCase("stroke-linejoin")) {
1783: // since these are system-dependent just pass them through
1784: // and hope.
1785: stroke.setLineJoin(parseCssParameter(child));
1786: }
1787:
1788: if (res.equalsIgnoreCase("dasharray")
1789: || res.equalsIgnoreCase("stroke-dasharray")) {
1790: String dashString = child.getFirstChild()
1791: .getNodeValue();
1792: StringTokenizer stok = new StringTokenizer(
1793: dashString, " ");
1794: float[] dashes = new float[stok.countTokens()];
1795:
1796: for (int l = 0; l < dashes.length; l++) {
1797: dashes[l] = Float.parseFloat(stok.nextToken());
1798: }
1799:
1800: stroke.setDashArray(dashes);
1801: }
1802:
1803: if (res.equalsIgnoreCase("dashoffset")
1804: || res.equalsIgnoreCase("stroke-dashoffset")) {
1805: stroke.setDashOffset(parseCssParameter(child));
1806: }
1807: }
1808: }
1809:
1810: return stroke;
1811: }
1812:
1813: private Fill parseFill(Node root) {
1814: if (LOGGER.isLoggable(Level.FINEST)) {
1815: LOGGER.finest("parsing fill ");
1816: }
1817:
1818: Fill fill = factory.getDefaultFill();
1819: NodeList list = findElements(((Element) root), "GraphicFill");
1820:
1821: if (list.getLength() > 0) {
1822: LOGGER.finest("fill found a graphic fill " + list.item(0));
1823:
1824: NodeList kids = list.item(0).getChildNodes();
1825:
1826: for (int i = 0; i < kids.getLength(); i++) {
1827: Node child = kids.item(i);
1828:
1829: if ((child == null)
1830: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1831: continue;
1832: }
1833: String childName = child.getLocalName();
1834: if (childName == null) {
1835: childName = child.getNodeName();
1836: }
1837: if (childName.equalsIgnoreCase(graphicSt)) {
1838: Graphic g = parseGraphic(child);
1839: LOGGER.finest("setting fill graphic with " + g);
1840: fill.setGraphicFill(g);
1841: }
1842: }
1843: }
1844:
1845: list = findElements(((Element) root), "CssParameter");
1846:
1847: for (int i = 0; i < list.getLength(); i++) {
1848: Node child = list.item(i);
1849:
1850: if ((child == null)
1851: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1852: continue;
1853: }
1854:
1855: Element param = (Element) child;
1856: org.w3c.dom.NamedNodeMap map = param.getAttributes();
1857:
1858: if (LOGGER.isLoggable(Level.FINEST)) {
1859: LOGGER.finest("now I am processing " + child);
1860: }
1861:
1862: if (LOGGER.isLoggable(Level.FINEST)) {
1863: LOGGER.finest("attributes " + map.toString());
1864: }
1865:
1866: for (int k = 0; k < map.getLength(); k++) {
1867: String res = map.item(k).getNodeValue();
1868:
1869: if (LOGGER.isLoggable(Level.FINEST)) {
1870: LOGGER.finest("processing attribute " + res);
1871: }
1872:
1873: if (res.equalsIgnoreCase(fillSt)) {
1874: fill.setColor(parseCssParameter(child));
1875: }
1876:
1877: if (res.equalsIgnoreCase("opacity")
1878: || res.equalsIgnoreCase("fill-opacity")) {
1879: fill.setOpacity(parseCssParameter(child));
1880: }
1881: }
1882: }
1883:
1884: if (LOGGER.isLoggable(Level.FINEST)) {
1885: LOGGER.finest("fill graphic " + fill.getGraphicFill());
1886: }
1887:
1888: return fill;
1889: }
1890:
1891: /**
1892: * Concatenates the given expressions (through the strConcat FunctionFilter expression)
1893: * @param left
1894: * @param right
1895: * @return
1896: */
1897: private Expression manageMixed(Expression left, Expression right) {
1898: if (left == null)
1899: return right;
1900: if (right == null)
1901: return left;
1902: Function mixed = ff.function("strConcat", new Expression[] {
1903: left, right });
1904: return mixed;
1905: }
1906:
1907: /**
1908: * Parses a css parameter. Default implementation trims whitespaces from text nodes.
1909: * @param root node to parse
1910: * @return
1911: */
1912: private Expression parseCssParameter(Node root) {
1913: return parseCssParameter(root, true);
1914: }
1915:
1916: /**
1917: * Parses a css parameter. You can choose if the parser must trim whitespace
1918: * from text nodes or not.
1919: * @param root node to parse
1920: * @param trimWhiteSpace true to trim whitespace from text nodes
1921: * @return
1922: */
1923: private Expression parseCssParameter(Node root,
1924: boolean trimWhiteSpace) {
1925: Expression ret = null;
1926:
1927: if (LOGGER.isLoggable(Level.FINEST)) {
1928: LOGGER.finest("parsingCssParam " + root);
1929: }
1930:
1931: NodeList children = root.getChildNodes();
1932:
1933: for (int i = 0; i < children.getLength(); i++) {
1934: Node child = children.item(i);
1935:
1936: // Added mixed="true" management through concatenation of text and expression nodes
1937: if ((child == null)) {
1938: continue;
1939: } else if (child.getNodeType() == Node.TEXT_NODE) {
1940: String value = child.getNodeValue();
1941: // trim whitespace if asked to do so
1942: value = (value != null && trimWhiteSpace) ? value
1943: .trim() : value;
1944: if (value != null && value.length() != 0) {
1945: Element literal = dom.createElement("literal");
1946: Node text = dom.createTextNode(value);
1947:
1948: literal.appendChild(text);
1949:
1950: if (LOGGER.isLoggable(Level.FINEST)) {
1951: LOGGER.finest("Built new literal " + literal);
1952: }
1953: // add the text node as a literal
1954: ret = manageMixed(ret,
1955: org.geotools.filter.ExpressionDOMParser
1956: .parseExpression(literal));
1957: }
1958: } else if (child.getNodeType() == Node.ELEMENT_NODE) {
1959:
1960: if (LOGGER.isLoggable(Level.FINEST)) {
1961: LOGGER.finest("about to parse "
1962: + child.getLocalName());
1963: }
1964: // add the element node as an expression
1965: ret = manageMixed(ret,
1966: org.geotools.filter.ExpressionDOMParser
1967: .parseExpression(child));
1968: } else
1969: continue;
1970:
1971: }
1972:
1973: if (ret == null && LOGGER.isLoggable(Level.FINEST)) {
1974: LOGGER.finest("no children in CssParam");
1975: }
1976:
1977: return ret;
1978: }
1979:
1980: private Font parseFont(Node root) {
1981: if (LOGGER.isLoggable(Level.FINEST)) {
1982: LOGGER.finest("parsing font");
1983: }
1984:
1985: Font font = factory.getDefaultFont();
1986: NodeList list = findElements(((Element) root), "CssParameter");
1987:
1988: for (int i = 0; i < list.getLength(); i++) {
1989: Node child = list.item(i);
1990:
1991: if ((child == null)
1992: || (child.getNodeType() != Node.ELEMENT_NODE)) {
1993: continue;
1994: }
1995:
1996: Element param = (Element) child;
1997: org.w3c.dom.NamedNodeMap map = param.getAttributes();
1998:
1999: for (int k = 0; k < map.getLength(); k++) {
2000: String res = map.item(k).getNodeValue();
2001:
2002: if (res.equalsIgnoreCase("font-family")) {
2003: font.setFontFamily(parseCssParameter(child));
2004: }
2005:
2006: if (res.equalsIgnoreCase("font-style")) {
2007: font.setFontStyle(parseCssParameter(child));
2008: }
2009:
2010: if (res.equalsIgnoreCase("font-size")) {
2011: font.setFontSize(parseCssParameter(child));
2012: }
2013:
2014: if (res.equalsIgnoreCase("font-weight")) {
2015: font.setFontWeight(parseCssParameter(child));
2016: }
2017: }
2018: }
2019:
2020: return font;
2021: }
2022:
2023: private LabelPlacement parseLabelPlacement(Node root) {
2024: if (LOGGER.isLoggable(Level.FINEST)) {
2025: LOGGER.finest("parsing labelPlacement");
2026: }
2027:
2028: LabelPlacement ret = null;
2029: NodeList children = root.getChildNodes();
2030:
2031: for (int i = 0; i < children.getLength(); i++) {
2032: Node child = children.item(i);
2033:
2034: if ((child == null)
2035: || (child.getNodeType() != Node.ELEMENT_NODE)) {
2036: continue;
2037: }
2038: String childName = child.getLocalName();
2039: if (childName == null) {
2040: childName = child.getNodeName();
2041: }
2042: if (childName.equalsIgnoreCase("PointPlacement")) {
2043: ret = parsePointPlacement(child);
2044: }
2045:
2046: if (childName.equalsIgnoreCase("LinePlacement")) {
2047: ret = parseLinePlacement(child);
2048: }
2049: }
2050:
2051: return ret;
2052: }
2053:
2054: private PointPlacement parsePointPlacement(Node root) {
2055: if (LOGGER.isLoggable(Level.FINEST)) {
2056: LOGGER.finest("parsing pointPlacement");
2057: }
2058:
2059: Expression rotation = ff.literal(0.0);
2060: AnchorPoint ap = null;
2061: Displacement dp = null;
2062:
2063: NodeList children = root.getChildNodes();
2064:
2065: for (int i = 0; i < children.getLength(); i++) {
2066: Node child = children.item(i);
2067:
2068: if ((child == null)
2069: || (child.getNodeType() != Node.ELEMENT_NODE)) {
2070: continue;
2071: }
2072: String childName = child.getLocalName();
2073: if (childName == null) {
2074: childName = child.getNodeName();
2075: }
2076: if (childName.equalsIgnoreCase("AnchorPoint")) {
2077: ap = (parseAnchorPoint(child));
2078: }
2079:
2080: if (childName.equalsIgnoreCase("Displacement")) {
2081: dp = (parseDisplacement(child));
2082: }
2083:
2084: if (childName.equalsIgnoreCase("Rotation")) {
2085: rotation = (parseCssParameter(child));
2086: }
2087: }
2088:
2089: LOGGER.fine("setting anchorPoint " + ap);
2090: LOGGER.fine("setting displacement " + dp);
2091:
2092: PointPlacement dpp = factory.createPointPlacement(ap, dp,
2093: rotation);
2094:
2095: return dpp;
2096: }
2097:
2098: private LinePlacement parseLinePlacement(Node root) {
2099: if (LOGGER.isLoggable(Level.FINEST)) {
2100: LOGGER.finest("parsing linePlacement");
2101: }
2102:
2103: Expression offset = ff.literal(0.0);
2104: NodeList children = root.getChildNodes();
2105:
2106: for (int i = 0; i < children.getLength(); i++) {
2107: Node child = children.item(i);
2108:
2109: if ((child == null)
2110: || (child.getNodeType() != Node.ELEMENT_NODE)) {
2111: continue;
2112: }
2113: String childName = child.getLocalName();
2114: if (childName == null) {
2115: childName = child.getNodeName();
2116: }
2117: if (childName.equalsIgnoreCase("PerpendicularOffset")) {
2118: offset = parseCssParameter(child);
2119: }
2120: }
2121:
2122: LinePlacement dlp = factory.createLinePlacement(offset);
2123:
2124: return dlp;
2125: }
2126:
2127: private AnchorPoint parseAnchorPoint(Node root) {
2128: if (LOGGER.isLoggable(Level.FINEST)) {
2129: LOGGER.finest("parsing anchorPoint");
2130: }
2131:
2132: Expression x = null;
2133: Expression y = null;
2134:
2135: NodeList children = root.getChildNodes();
2136:
2137: for (int i = 0; i < children.getLength(); i++) {
2138: Node child = children.item(i);
2139:
2140: if ((child == null)
2141: || (child.getNodeType() != Node.ELEMENT_NODE)) {
2142: continue;
2143: }
2144: String childName = child.getLocalName();
2145: if (childName == null) {
2146: childName = child.getNodeName();
2147: }
2148: if (childName.equalsIgnoreCase("AnchorPointX")) {
2149: x = (parseCssParameter(child));
2150: }
2151:
2152: if (childName.equalsIgnoreCase("AnchorPointY")) {
2153: y = (parseCssParameter(child));
2154: }
2155: }
2156:
2157: AnchorPoint dap = factory.createAnchorPoint(x, y);
2158:
2159: return dap;
2160: }
2161:
2162: private Displacement parseDisplacement(Node root) {
2163: if (LOGGER.isLoggable(Level.FINEST)) {
2164: LOGGER.finest("parsing displacment");
2165: }
2166:
2167: Expression x = null;
2168: Expression y = null;
2169: NodeList children = root.getChildNodes();
2170:
2171: for (int i = 0; i < children.getLength(); i++) {
2172: Node child = children.item(i);
2173:
2174: if ((child == null)
2175: || (child.getNodeType() != Node.ELEMENT_NODE)) {
2176: continue;
2177: }
2178: String childName = child.getLocalName();
2179: if (childName == null) {
2180: childName = child.getNodeName();
2181: }
2182: if (childName.equalsIgnoreCase("DisplacementX")) {
2183: x = (parseCssParameter(child));
2184: }
2185:
2186: if (childName.equalsIgnoreCase("DisplacementY")) {
2187: y = (parseCssParameter(child));
2188: }
2189: }
2190:
2191: Displacement dd = factory.createDisplacement(x, y);
2192:
2193: return dd;
2194: }
2195:
2196: /**
2197: * DOCUMENT ME!
2198: *
2199: * @param root
2200: *
2201: */
2202: private Halo parseHalo(Node root) {
2203: if (LOGGER.isLoggable(Level.FINEST)) {
2204: LOGGER.finest("parsing halo");
2205: }
2206: Halo halo = factory.createHalo(factory.createFill(ff
2207: .literal("#FFFFFF")), ff.literal(1.0));
2208:
2209: NodeList children = root.getChildNodes();
2210:
2211: for (int i = 0; i < children.getLength(); i++) {
2212: Node child = children.item(i);
2213:
2214: if ((child == null)
2215: || (child.getNodeType() != Node.ELEMENT_NODE)) {
2216: continue;
2217: }
2218: String childName = child.getLocalName();
2219: if (childName == null) {
2220: childName = child.getNodeName();
2221: }
2222: if (childName.equalsIgnoreCase(fillSt)) {
2223: halo.setFill(parseFill(child));
2224: }
2225:
2226: if (childName.equalsIgnoreCase("Radius")) {
2227: halo.setRadius(parseCssParameter(child));
2228: }
2229: }
2230:
2231: return halo;
2232: }
2233:
2234: }
|