/**
   * Parse Contact Information
   *
   * @return ContactInfo
   * @throws XMLParsingException
   */
  protected ContactInfo parseContactInfo() throws XMLParsingException {
    LOG.entering();

    LOG.logDebug("Parsing contact information parameter.");
    Node contactInfo =
        XMLTools.getNode(getRootElement(), "./Service/ContactInformation", nsContext);
    String[] addr = XMLTools.getNodesAsStrings(contactInfo, "./ContactAddress/Address", nsContext);
    // String addrType = XMLTools.getNodeAsString( contactInfo, "./ContactAddress/AddressType",
    // nsContext, null );
    String city = XMLTools.getNodeAsString(contactInfo, "./ContactAddress/City", nsContext, null);
    String state =
        XMLTools.getNodeAsString(contactInfo, "./ContactAddress/StateOrProvince", nsContext, null);
    String pc = XMLTools.getNodeAsString(contactInfo, "./ContactAddress/PostCode", nsContext, null);
    String country =
        XMLTools.getNodeAsString(contactInfo, "./ContactAddress/Country", nsContext, null);
    String[] mail =
        XMLTools.getNodesAsStrings(contactInfo, "./ContactElectronicMailAddress", nsContext);
    Address address = new Address(state, city, country, addr, mail, pc);

    String[] phone = XMLTools.getNodesAsStrings(contactInfo, "./ContactVoiceTelephone", nsContext);
    String[] fax =
        XMLTools.getNodesAsStrings(contactInfo, "./ContactFacsimileTelephone", nsContext);

    Phone ph = new Phone(fax, phone);

    ContactInfo cont = new ContactInfo(address, null, null, null, ph);

    LOG.exiting();
    return cont;
  }
  /**
   * returns the services indentification read from the WMPS capabilities service section
   *
   * @return ServiceIdentification
   * @throws XMLParsingException
   */
  protected ServiceIdentification parseServiceIdentification() throws XMLParsingException {
    LOG.entering();

    LOG.logDebug("Parsing service identification parameter.");
    String name = XMLTools.getNodeAsString(getRootElement(), "./Service/Name", nsContext, null);
    String title = XMLTools.getNodeAsString(getRootElement(), "./Service/Title", nsContext, name);
    String serviceAbstract =
        XMLTools.getNodeAsString(getRootElement(), "./Service/Abstract", nsContext, null);

    String[] kw =
        XMLTools.getNodesAsStrings(getRootElement(), "./Service/KeywordList/Keyword", nsContext);

    Keywords[] keywords = new Keywords[] {new Keywords(kw)};

    String fees = XMLTools.getNodeAsString(getRootElement(), "./Service/Fees", nsContext, null);

    String[] accessConstraints =
        XMLTools.getNodesAsStrings(getRootElement(), "./Service/AccessConstraints", nsContext);

    String[] acceptedVersion = new String[] {"1.0.0"};
    Code code = new Code("WMPS");
    ServiceIdentification serviceIdentification =
        new ServiceIdentification(
            code, acceptedVersion, title, serviceAbstract, keywords, fees, accessConstraints);
    LOG.exiting();
    return serviceIdentification;
  }
  /**
   * returns the layers offered by the WMPS
   *
   * @param layerElem
   * @param parent
   * @return Layer
   * @throws XMLParsingException
   * @throws UnknownCRSException
   */
  protected Layer parseLayers(Element layerElem, Layer parent)
      throws XMLParsingException, UnknownCRSException {
    LOG.entering();

    boolean queryable = XMLTools.getNodeAsBoolean(layerElem, "./@queryable", nsContext, false);

    int cascaded = XMLTools.getNodeAsInt(layerElem, "./@cascaded", nsContext, 0);
    boolean opaque = XMLTools.getNodeAsBoolean(layerElem, "./@opaque", nsContext, false);
    boolean noSubsets = XMLTools.getNodeAsBoolean(layerElem, "./@noSubsets", nsContext, false);
    int fixedWidth = XMLTools.getNodeAsInt(layerElem, "./@fixedWidth", nsContext, 0);
    int fixedHeight = XMLTools.getNodeAsInt(layerElem, "./@fixedHeight", nsContext, 0);
    String name = XMLTools.getNodeAsString(layerElem, "./Name", nsContext, null);
    String title = XMLTools.getRequiredNodeAsString(layerElem, "./Title", nsContext);
    String layerAbstract = XMLTools.getNodeAsString(layerElem, "./Abstract", nsContext, null);
    String[] keywords = XMLTools.getNodesAsStrings(layerElem, "./KeywordList/Keyword", nsContext);
    String[] srs = XMLTools.getNodesAsStrings(layerElem, "./SRS", nsContext);

    List nl = XMLTools.getNodes(layerElem, "./BoundingBox", nsContext);
    // TODO substitue with Envelope
    LayerBoundingBox[] bboxes = null;
    if (nl.size() == 0 && parent != null) {
      // inherit BoundingBoxes from parent layer
      bboxes = parent.getBoundingBoxes();
    } else {
      bboxes = parseLayerBoundingBoxes(nl);
    }

    Element llBox = (Element) XMLTools.getNode(layerElem, "./LatLonBoundingBox", nsContext);
    Envelope llBoundingBox = null;

    if (llBox == null && parent != null) {
      // inherit LatLonBoundingBox parent layer
      llBoundingBox = parent.getLatLonBoundingBox();
    } else if (llBox != null) {
      llBoundingBox = parseLatLonBoundingBox(llBox);
    } else {
      /** Default crs = EPSG:4326 */
      CoordinateSystem crs = CRSFactory.create("EPSG:4326");
      llBoundingBox = GeometryFactory.createEnvelope(-180, -90, 180, 90, crs);
    }

    Dimension[] dimensions = parseDimensions(layerElem);

    Extent[] extents = parseExtents(layerElem);

    Attribution attribution = parseAttribution(layerElem);

    AuthorityURL[] authorityURLs = parseAuthorityURLs(layerElem);

    MetadataURL[] metadataURLs = parseMetadataURLs(layerElem);

    DataURL[] dataURLs = parseDataURL(layerElem);

    Identifier[] identifiers = parseIdentifiers(layerElem);

    FeatureListURL[] featureListURLs = parseFeatureListURL(layerElem);

    Style[] styles = parseStyles(layerElem);

    ScaleHint scaleHint = parseScaleHint(layerElem);

    Layer layer =
        new Layer(
            queryable,
            cascaded,
            opaque,
            noSubsets,
            fixedWidth,
            fixedHeight,
            name,
            title,
            layerAbstract,
            llBoundingBox,
            attribution,
            scaleHint,
            keywords,
            srs,
            bboxes,
            dimensions,
            extents,
            authorityURLs,
            identifiers,
            metadataURLs,
            dataURLs,
            featureListURLs,
            styles,
            null,
            null,
            parent);

    // get Child layers
    nl = XMLTools.getNodes(layerElem, "./Layer", nsContext);
    Layer[] layers = new Layer[nl.size()];
    for (int i = 0; i < layers.length; i++) {
      layers[i] = parseLayers((Element) nl.get(i), layer);
    }

    // set child layers
    layer.setLayer(layers);

    LOG.exiting();
    return layer;
  }