Changeset 7115


Ignore:
Timestamp:
03/07/17 15:52:25 (7 years ago)
Author:
Oliver Schonefeld
Message:
  • add version to endpoint description
Location:
FCSSimpleEndpoint/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • FCSSimpleEndpoint/trunk/pom.xml

    r7071 r7115  
    4646            <groupId>eu.clarin.sru.fcs</groupId>
    4747            <artifactId>fcs-ql</artifactId>
    48             <version>0.1</version>
     48            <version>0.1-SNAPSHOT</version>
    4949        </dependency>
    5050       
  • FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/EndpointDescription.java

    r6935 r7115  
    3333public interface EndpointDescription {
    3434    /**
     35     * Constant for endpoint description version number for FCS 1.0
     36     */
     37    public static final int VERSION_1 = 1;
     38    /**
     39     * Constant for endpoint description version number for FCS 1.0
     40     */
     41    public static final int VERSION_2 = 2;
     42   
     43    /**
    3544     * Constant for a (synthetic) persistent identifier identifying the top-most
    3645     * (= root) resources in the resource inventory.
    3746     */
    3847    public static final String PID_ROOT = "root";
     48
    3949
    4050    /**
     
    4656
    4757
     58    /**
     59     * Get the version number of this endpoint description. <br>
     60     * Valid version are 1 for FCS 1.0 and 2 fpr FCS 2.0.
     61     *
     62     * @return the version number for this endpoint description
     63     */
     64    public int getVersion();
     65
     66
     67    /**
     68     * Check if this endpoint description is in a certain version.
     69     *
     70     * @param version
     71     *            the version to check for
     72     *
     73     * @return <code>true</code>, if version number matches
     74     */
     75    public boolean isVersion(int version);
     76
     77   
    4878    /**
    4979     * Get the list of capabilities supported by this endpoint. The list
  • FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/SimpleEndpointSearchEngineBase.java

    r6937 r7115  
    5656            "http://clarin.eu/fcs/endpoint-description";
    5757    private static final String ED_PREFIX = "ed";
    58     private static final int ED_VERSION = 2;
    5958    private static final Logger logger =
    6059            LoggerFactory.getLogger(SimpleEndpointSearchEngineBase.class);
     
    257256        writer.writeStartElement(ED_NS, "EndpointDescription");
    258257        writer.writeNamespace(ED_PREFIX, ED_NS);
    259         writer.writeAttribute("version", Integer.toString(ED_VERSION));
     258        writer.writeAttribute("version",
     259                Integer.toString(endpointDescription.getVersion()));
    260260
    261261        // Capabilities
     
    292292        writer.writeEndElement(); // "SupportedDataViews" element
    293293
    294         // SupportedLayers
    295         final List<Layer> layers = endpointDescription.getSupportedLayers();
    296         if (layers != null) {
    297             writer.writeStartElement(ED_NS, "SupportedLayers");
    298             for (Layer layer : layers) {
    299                 writer.writeStartElement(ED_NS, "SupportedLayer");
    300                 writer.writeAttribute("id", layer.getId());
    301                 writer.writeAttribute("result-id",
    302                         layer.getResultId().toString());
    303                 if (layer.getContentEncoding() == Layer.ContentEncoding.EMPTY) {
    304                     writer.writeAttribute("type", "empty");
    305                 }
    306                 if (layer.getQualifier() != null) {
    307                     writer.writeAttribute("qualifier", layer.getQualifier());
    308                 }
    309                 if (layer.getAltValueInfo() != null) {
    310                     writer.writeAttribute("alt-value-info",
    311                             layer.getAltValueInfo());
    312                     if (layer.getAltValueInfoURI() != null) {
    313                         writer.writeAttribute("alt-value-info-uri",
    314                                 layer.getAltValueInfoURI().toString());
    315                     }
    316                 }
    317                 writer.writeCharacters(layer.getType());
    318                 writer.writeEndElement(); // "SupportedLayer" element
     294        if (endpointDescription.isVersion(EndpointDescription.VERSION_2)) {
     295            // SupportedLayers
     296            final List<Layer> layers = endpointDescription.getSupportedLayers();
     297            if (layers != null) {
     298                writer.writeStartElement(ED_NS, "SupportedLayers");
     299                for (Layer layer : layers) {
     300                    writer.writeStartElement(ED_NS, "SupportedLayer");
     301                    writer.writeAttribute("id", layer.getId());
     302                    writer.writeAttribute("result-id",
     303                            layer.getResultId().toString());
     304                    if (layer.getContentEncoding() ==
     305                            Layer.ContentEncoding.EMPTY) {
     306                        writer.writeAttribute("type", "empty");
     307                    }
     308                    if (layer.getQualifier() != null) {
     309                        writer.writeAttribute("qualifier",
     310                                layer.getQualifier());
     311                    }
     312                    if (layer.getAltValueInfo() != null) {
     313                        writer.writeAttribute("alt-value-info",
     314                                layer.getAltValueInfo());
     315                        if (layer.getAltValueInfoURI() != null) {
     316                            writer.writeAttribute("alt-value-info-uri",
     317                                    layer.getAltValueInfoURI().toString());
     318                        }
     319                    }
     320                    writer.writeCharacters(layer.getType());
     321                    writer.writeEndElement(); // "SupportedLayer" element
     322                }
     323                writer.writeEndElement(); // "SupportedLayers" element
    319324            }
    320             writer.writeEndElement(); // "SupportedLayers" element
    321 
    322325        }
    323326
     
    329332            writeResourceInfos(writer, resources);
    330333        } catch (SRUException e) {
    331             throw new XMLStreamException("error retriving top-level resources",
    332                     e);
     334            throw new XMLStreamException(
     335                    "error retriving top-level resources", e);
    333336        }
    334337        writer.writeEndElement(); // "EndpointDescription" element
     
    401404                writer.writeAttribute("ref", sb.toString());
    402405
    403                 final List<Layer> layers = resource.getAvailableLayers();
    404                 if (layers != null) {
    405                     sb = new StringBuilder();
    406                     for (Layer layer : resource.getAvailableLayers()) {
    407                         if (sb.length() > 0) {
    408                             sb.append(" ");
     406                if (endpointDescription.isVersion(
     407                        EndpointDescription.VERSION_2)) {
     408                    final List<Layer> layers = resource.getAvailableLayers();
     409                    if (layers != null) {
     410                        sb = new StringBuilder();
     411                        for (Layer layer : resource.getAvailableLayers()) {
     412                            if (sb.length() > 0) {
     413                                sb.append(" ");
     414                            }
     415                            sb.append(layer.getId());
    409416                        }
    410                         sb.append(layer.getId());
    411                     }
    412                     writer.writeEmptyElement(ED_NS, "AvailableLayers");
    413                     writer.writeAttribute("ref", sb.toString());
     417                        writer.writeEmptyElement(ED_NS, "AvailableLayers");
     418                        writer.writeAttribute("ref", sb.toString());
     419                    }
    414420                }
    415421
  • FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/utils/AbstractEndpointDescriptionBase.java

    r6937 r7115  
    3333 *
    3434 */
    35 public abstract class AbstractEndpointDescriptionBase implements EndpointDescription {
     35public abstract class AbstractEndpointDescriptionBase
     36        implements EndpointDescription {
     37    protected final int version;
    3638    protected final List<URI> capabilities;
    3739    protected final List<DataView> supportedDataViews;
     
    4244     * Constructor.
    4345     *
     46     * @param version
     47     *            version of this endpoint description
    4448     * @param capabilities
    4549     *            a list of capabilities supported by this endpoint
     
    4953     *            a list of layers that are supported by this endpoint
    5054     */
    51     protected AbstractEndpointDescriptionBase(List<URI> capabilities,
    52             List<DataView> supportedDataViews, List<Layer> supportedLayers) {
     55    protected AbstractEndpointDescriptionBase(int version,
     56            List<URI> capabilities, List<DataView> supportedDataViews,
     57            List<Layer> supportedLayers) {
     58        if ((version != 1) && (version != 2)) {
     59            throw new IllegalArgumentException("version must be either 1 or 2");
     60        }
     61        this.version = version;
     62
    5363        if (capabilities == null) {
    5464            throw new NullPointerException("capabilities == null");
     
    96106
    97107    @Override
     108    public int getVersion() {
     109        return version;
     110    }
     111
     112
     113    @Override
     114    public boolean isVersion(int version) {
     115        return this.version == version;
     116    }
     117
     118
     119    @Override
    98120    public List<URI> getCapabilities() {
    99121        return capabilities;
  • FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/utils/SimpleEndpointDescription.java

    r6935 r7115  
    4545     * Constructor.
    4646     *
     47     * @param version
     48     *            version of this endpoint description
    4749     * @param capabilities
    4850     *            a list of capabilities supported by this endpoint
     
    5961     *            otherwise
    6062     */
    61     public SimpleEndpointDescription(List<URI> capabilities,
     63    public SimpleEndpointDescription(int version, List<URI> capabilities,
    6264            List<DataView> supportedDataViews,
    6365            List<Layer> supportedLayers,
    6466            List<ResourceInfo> resources,
    6567            boolean pidCaseSensitive) {
    66         super(capabilities, supportedDataViews, supportedLayers);
     68        super(version, capabilities, supportedDataViews, supportedLayers);
    6769
    6870        if (resources == null) {
  • FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/utils/SimpleEndpointDescriptionParser.java

    r7005 r7115  
    161161        });
    162162
     163        // version
     164        int version = -1;
     165        XPathExpression exp =
     166                xpath.compile("//ed:EndpointDescription/@version");
     167        String v = (String) exp.evaluate(doc, XPathConstants.STRING);
     168        if (v != null) {
     169            try {
     170                version = Integer.parseInt(v);
     171                if ((version != 1) && (version != 2)) {
     172                    throw new SRUConfigException("Attribute @version " +
     173                            "element <EndpointDescription> must have a " +
     174                            "value of either '1' or '2' ");
     175                }
     176            } catch (NumberFormatException e) {
     177                throw new SRUConfigException("Cannot parse version number", e);
     178            }
     179        }
     180        if (version == -1) {
     181            throw new SRUConfigException("Attribute @version missing on "+
     182                    "element <EndpointDescription>");
     183        }
     184        logger.debug("endpoint description version is {}", version);
     185
    163186        // capabilities
    164187        List<URI> capabilities = new ArrayList<URI>();
    165         XPathExpression exp =
    166                 xpath.compile("//ed:Capabilities/ed:Capability");
     188        exp = xpath.compile("//ed:Capabilities/ed:Capability");
    167189        NodeList list =
    168190                (NodeList) exp.evaluate(doc, XPathConstants.NODESET);
     
    194216            capabilities.add(CAP_BASIC_SEARCH);
    195217        }
     218        if (capabilities.contains(CAP_ADVANCED_SEARCH) && (version < 2)) {
     219            logger.warn("Endpoint description is declared as version " +
     220                    "FCS 1.0 (@version = 1), but contains support for " +
     221                    "Advanced Search in capabilities list! FCS 1.0 only " +
     222                    "supports Basic Search");
     223        }
    196224        logger.debug("CAPS:'{}'", capabilities);
    197225
    198         // used to check for id attribute uniqueness
     226        // used to check for uniqueness of id attribute
    199227        final Set<String> xml_ids = new HashSet<String>();
    200228
     
    215243                if (xml_ids.contains(id)) {
    216244                    throw new SRUConfigException("The value of attribute " +
    217                             "'id' of element <SupportedDataView> must be unique: " + id);
     245                            "'id' of element <SupportedDataView> must be " +
     246                            "unique: " + id);
    218247                }
    219248                xml_ids.add(id);
     
    289318                    "Advanced FCS but does not declare Advanced Data View (" +
    290319                    MIMETYPE_ADV + ") in <SupportedDataViews>");
    291 
    292         }
    293 
     320        }
    294321
    295322        // supported layers
     
    309336                if (xml_ids.contains(id)) {
    310337                    throw new SRUConfigException("The value of attribute " +
    311                             "'id' of element <SupportedLayer> must be unique: " + id);
     338                            "'id' of element <SupportedLayer> must be " +
     339                            "unique: " + id);
    312340                }
    313341                xml_ids.add(id);
     
    355383                        encoding = Layer.ContentEncoding.EMPTY;
    356384                    } else {
    357                         throw new SRUConfigException("invalid layer encoding: " + s);
     385                        throw new SRUConfigException(
     386                                "invalid layer encoding: " + s);
    358387                    }
    359388                }
     
    368397                          altValueInfoURI = new URI(s);
    369398                        } catch (URISyntaxException e) {
    370                             throw new SRUConfigException("Attribute 'alt-value-info-uri' on " +
    371                                     "Element <SupportedLayer> is not encoded " +
     399                            throw new SRUConfigException("Attribute " +
     400                                    "'alt-value-info-uri' on Element " +
     401                                    "<SupportedLayer> is not encoded " +
    372402                                    "as proper URI: " + s);
    373403                        }
    374                     } else {
    375 
    376404                    }
    377405                }
     
    401429        final Set<String> pids = new HashSet<String>();
    402430        List<ResourceInfo> resources = parseResources(xpath, list, pids,
    403                 supportedDataViews, supportedLayers, hasAdvView);
     431                supportedDataViews, supportedLayers, version, hasAdvView);
    404432        if ((resources == null) || resources.isEmpty()) {
    405433            throw new SRUConfigException("No resources where " +
     
    407435        }
    408436
    409         return new SimpleEndpointDescription(capabilities,
     437        return new SimpleEndpointDescription(version,
     438                capabilities,
    410439                supportedDataViews,
    411440                supportedLayers,
     
    417446    private static List<ResourceInfo> parseResources(XPath xpath,
    418447            NodeList nodes, Set<String> pids, List<DataView> supportedDataViews,
    419             List<Layer> supportedLayers, boolean hasAdv)
     448            List<Layer> supportedLayers, int version, boolean hasAdv)
    420449                    throws SRUConfigException, XPathExpressionException {
    421450        List<ResourceInfo> ris = null;
    422       for (int k = 0; k < nodes.getLength(); k++) {
    423           final Element node                = (Element) nodes.item(k);
    424           String pid                        = null;
    425           Map<String, String> titles        = null;
    426           Map<String, String> descrs        = null;
    427           String link                       = null;
    428           List<String> langs                = null;
    429           List<DataView> availableDataViews = null;
    430           List<Layer> availableLayers       = null;
    431           List<ResourceInfo> sub            = null;
    432 
    433           pid = getAttribute(node, "pid");
    434           if (pid == null) {
    435               throw new SRUConfigException("Element <ResourceInfo> " +
    436                       "must have a proper 'pid' attribute");
    437           }
    438           if (pids.contains(pid)) {
    439               throw new SRUConfigException("Another element <Resource> " +
    440                       "with pid '" + pid + "' already exists");
    441           }
    442           pids.add(pid);
    443 
    444           XPathExpression exp = xpath.compile("ed:Title");
    445           NodeList list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
    446           if ((list != null) && (list.getLength() > 0)) {
    447               for (int i = 0; i < list.getLength(); i++) {
    448                   final Element n = (Element) list.item(i);
    449 
    450                   final String lang = getLangAttribute(n);
    451                   if (lang == null) {
    452                       throw new SRUConfigException("Element <Title> " +
    453                               "must have a proper 'xml:lang' attribute");
    454                   }
    455 
    456                   final String title = cleanString(n.getTextContent());
    457                   if (title == null) {
    458                       throw new SRUConfigException("Element <Title> " +
    459                               "must have a non-empty 'xml:lang' attribute");
    460                   }
    461 
    462                   if (titles == null) {
    463                       titles = new HashMap<String, String>();
    464                   }
    465                   if (titles.containsKey(lang)) {
    466                       logger.warn("title with language '{}' already exists",
    467                               lang);
    468                   } else {
    469                       logger.debug("title: '{}' '{}'", lang, title);
    470                       titles.put(lang, title);
    471                   }
    472               }
    473               if ((titles != null) && !titles.containsKey(LANG_EN)) {
    474                   throw new SRUConfigException(
    475                           "A <Title> with language 'en' is mandatory");
    476               }
    477           }
    478 
    479           exp = xpath.compile("ed:Description");
    480           list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
    481           if ((list != null) && (list.getLength() > 0)) {
    482               for (int i = 0; i < list.getLength(); i++) {
    483                   Element n = (Element) list.item(i);
    484 
    485                   String lang = getLangAttribute(n);
    486                   if (lang == null) {
    487                       throw new SRUConfigException("Element <Description> " +
    488                               "must have a proper 'xml:lang' attribute");
    489 
    490                   }
    491                   String desc = cleanString(n.getTextContent());
    492 
    493                   if (descrs == null) {
    494                       descrs = new HashMap<String, String>();
    495                   }
    496 
    497                   if (descrs.containsKey(lang)) {
    498                       logger.warn("description with language '{}' "
    499                               + "already exists", lang);
    500                   } else {
    501                       logger.debug("description: '{}' '{}'", lang, desc);
    502                       descrs.put(lang, desc);
    503                   }
    504               }
    505               if ((descrs != null) && !descrs.containsKey(LANG_EN)) {
    506                   throw new SRUConfigException(
    507                           "A <Description> with language 'en' is mandatory");
    508               }
    509           }
    510 
    511           exp = xpath.compile("ed:LandingPageURI");
    512           list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
    513           if ((list != null) && (list.getLength() > 0)) {
    514               for (int i = 0; i < list.getLength(); i++) {
    515                   Element n = (Element) list.item(i);
    516                   link = cleanString(n.getTextContent());
    517               }
    518           }
    519 
    520           exp = xpath.compile("ed:Languages/ed:Language");
    521           list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
    522           if ((list != null) && (list.getLength() > 0)) {
    523               for (int i = 0; i < list.getLength(); i++) {
    524                   Element n = (Element) list.item(i);
    525 
    526                   String s = n.getTextContent();
    527                   if (s != null) {
    528                       s = s.trim();
    529                       if (s.isEmpty()) {
    530                           s = null;
    531                       }
    532                   }
    533 
    534                   /*
    535                    * enforce three letter codes
    536                    */
    537                   if ((s == null) || (s.length() != 3)) {
    538                       throw new SRUConfigException("Element <Language> " +
    539                               "must use ISO-639-3 three letter " +
    540                               "language codes");
    541                   }
    542 
    543                   if (langs == null) {
    544                       langs = new ArrayList<String>();
    545                   }
    546                   langs.add(s);
    547               }
    548           }
    549 
    550           exp = xpath.compile("ed:AvailableDataViews");
    551           Node n = (Node) exp.evaluate(node, XPathConstants.NODE);
    552           if ((n != null) && (n instanceof Element)) {
    553               String ref = getAttribute((Element) n, "ref");
    554               if (ref == null) {
    555                   throw new SRUConfigException("Element <AvailableDataViews> " +
    556                           "must have a 'ref' attribute");
    557               }
    558               String[] refs = ref.split("\\s+");
    559               if ((refs == null) || (refs.length < 1)) {
    560                   throw new SRUConfigException("Attribute 'ref' on element " +
    561                           "<AvailableDataViews> must contain a whitespace " +
    562                           "seperated list of data view references");
    563               }
    564 
    565 
    566               for (int i = 0; i < refs.length; i++) {
    567                   DataView dataview = null;
    568                   for (DataView dv : supportedDataViews) {
    569                       if (refs[i].equals(dv.getIdentifier())) {
    570                           dataview = dv;
    571                           break;
    572                       }
    573                   }
    574                   if (dataview != null) {
    575                       if (availableDataViews == null) {
    576                           availableDataViews = new ArrayList<DataView>();
    577                       }
    578                       availableDataViews.add(dataview);
    579                   } else {
    580                       throw new SRUConfigException("A data view with " +
    581                               "identifier '" + refs[i] + "' was not defined " +
    582                               "in <SupportedDataViews>");
    583                   }
    584               }
    585           } else {
    586               throw new SRUConfigException(
    587                       "missing element <AvailableDataViews>");
    588           }
    589           if (availableDataViews == null) {
    590               throw new SRUConfigException("No available data views where " +
    591                       "defined for resource with PID '" + pid + "'");
    592           }
    593 
    594           exp = xpath.compile("ed:AvailableLayers");
    595           n = (Node) exp.evaluate(node, XPathConstants.NODE);
    596           if ((n != null) && (n instanceof Element)) {
    597               String ref = getAttribute((Element) n, "ref");
    598               if (ref == null) {
    599                   throw new SRUConfigException("Element <AvailableLayers> " +
    600                           "must have a 'ref' attribute");
    601               }
    602               String[] refs = ref.split("\\s+");
    603               if ((refs == null) || (refs.length < 1)) {
    604                   throw new SRUConfigException("Attribute 'ref' on element " +
    605                           "<AvailableLayers> must contain a whitespace " +
    606                           "seperated list of data view references");
    607               }
    608 
    609 
    610               for (int i = 0; i < refs.length; i++) {
    611                   Layer layer = null;
    612                   for (Layer l : supportedLayers) {
    613                       if (refs[i].equals(l.getId())) {
    614                           layer = l;
    615                           break;
    616                       }
    617                   }
    618                   if (layer != null) {
    619                       if (availableLayers == null) {
    620                           availableLayers = new ArrayList<Layer>();
    621                       }
    622                       availableLayers.add(layer);
    623                   } else {
    624                       throw new SRUConfigException("A layer with " +
    625                               "identifier '" + refs[i] + "' was not defined " +
    626                               "in <SupportedLayers>");
    627                   }
    628               }
    629           } else {
    630               if (hasAdv) {
    631                   logger.debug("no <SupportedLayers> for ressource '{}'", pid);
    632               }
    633           }
    634 
    635           exp = xpath.compile("ed:Resources/ed:Resource");
    636           list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
    637           if ((list != null) && (list.getLength() > 0)) {
    638               sub = parseResources(xpath, list, pids,
    639                       supportedDataViews, supportedLayers, hasAdv);
    640           }
    641 
    642           if (ris == null) {
    643               ris = new ArrayList<ResourceInfo>();
    644           }
    645           ris.add(new ResourceInfo(pid,
    646                   titles,
    647                   descrs,
    648                   link,
    649                   langs,
    650                   availableDataViews,
    651                   availableLayers,
    652                   sub));
    653       }
    654       return ris;
     451        for (int k = 0; k < nodes.getLength(); k++) {
     452            final Element node = (Element) nodes.item(k);
     453            String pid = null;
     454            Map<String, String> titles = null;
     455            Map<String, String> descrs = null;
     456            String link = null;
     457            List<String> langs = null;
     458            List<DataView> availableDataViews = null;
     459            List<Layer> availableLayers = null;
     460            List<ResourceInfo> sub = null;
     461
     462            pid = getAttribute(node, "pid");
     463            if (pid == null) {
     464                throw new SRUConfigException("Element <ResourceInfo> " +
     465                        "must have a proper 'pid' attribute");
     466            }
     467            if (pids.contains(pid)) {
     468                throw new SRUConfigException("Another element <Resource> " +
     469                        "with pid '" + pid + "' already exists");
     470            }
     471            pids.add(pid);
     472
     473            XPathExpression exp = xpath.compile("ed:Title");
     474            NodeList list = (NodeList) exp.evaluate(node,
     475                    XPathConstants.NODESET);
     476            if ((list != null) && (list.getLength() > 0)) {
     477                for (int i = 0; i < list.getLength(); i++) {
     478                    final Element n = (Element) list.item(i);
     479
     480                    final String lang = getLangAttribute(n);
     481                    if (lang == null) {
     482                        throw new SRUConfigException("Element <Title> " +
     483                                "must have a proper 'xml:lang' attribute");
     484                    }
     485
     486                    final String title = cleanString(n.getTextContent());
     487                    if (title == null) {
     488                        throw new SRUConfigException("Element <Title> " +
     489                                "must have a non-empty 'xml:lang' attribute");
     490                    }
     491
     492                    if (titles == null) {
     493                        titles = new HashMap<String, String>();
     494                    }
     495                    if (titles.containsKey(lang)) {
     496                        logger.warn("title with language '{}' already exists",
     497                                lang);
     498                    } else {
     499                        logger.debug("title: '{}' '{}'", lang, title);
     500                        titles.put(lang, title);
     501                    }
     502                }
     503                if ((titles != null) && !titles.containsKey(LANG_EN)) {
     504                    throw new SRUConfigException(
     505                            "A <Title> with language 'en' is mandatory");
     506                }
     507            }
     508
     509            exp = xpath.compile("ed:Description");
     510            list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
     511            if ((list != null) && (list.getLength() > 0)) {
     512                for (int i = 0; i < list.getLength(); i++) {
     513                    Element n = (Element) list.item(i);
     514
     515                    String lang = getLangAttribute(n);
     516                    if (lang == null) {
     517                        throw new SRUConfigException("Element <Description> " +
     518                                "must have a proper 'xml:lang' attribute");
     519
     520                    }
     521                    String desc = cleanString(n.getTextContent());
     522
     523                    if (descrs == null) {
     524                        descrs = new HashMap<String, String>();
     525                    }
     526
     527                    if (descrs.containsKey(lang)) {
     528                        logger.warn("description with language '{}' " +
     529                                "already exists", lang);
     530                    } else {
     531                        logger.debug("description: '{}' '{}'", lang, desc);
     532                        descrs.put(lang, desc);
     533                    }
     534                }
     535                if ((descrs != null) && !descrs.containsKey(LANG_EN)) {
     536                    throw new SRUConfigException(
     537                            "A <Description> with language 'en' is mandatory");
     538                }
     539            }
     540
     541            exp = xpath.compile("ed:LandingPageURI");
     542            list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
     543            if ((list != null) && (list.getLength() > 0)) {
     544                for (int i = 0; i < list.getLength(); i++) {
     545                    Element n = (Element) list.item(i);
     546                    link = cleanString(n.getTextContent());
     547                }
     548            }
     549
     550            exp = xpath.compile("ed:Languages/ed:Language");
     551            list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
     552            if ((list != null) && (list.getLength() > 0)) {
     553                for (int i = 0; i < list.getLength(); i++) {
     554                    Element n = (Element) list.item(i);
     555
     556                    String s = n.getTextContent();
     557                    if (s != null) {
     558                        s = s.trim();
     559                        if (s.isEmpty()) {
     560                            s = null;
     561                        }
     562                    }
     563
     564                    /*
     565                     * enforce three letter codes
     566                     */
     567                    if ((s == null) || (s.length() != 3)) {
     568                        throw new SRUConfigException("Element <Language> " +
     569                                "must use ISO-639-3 three letter " +
     570                                "language codes");
     571                    }
     572
     573                    if (langs == null) {
     574                        langs = new ArrayList<String>();
     575                    }
     576                    langs.add(s);
     577                }
     578            }
     579
     580            exp = xpath.compile("ed:AvailableDataViews");
     581            Node n = (Node) exp.evaluate(node, XPathConstants.NODE);
     582            if ((n != null) && (n instanceof Element)) {
     583                String ref = getAttribute((Element) n, "ref");
     584                if (ref == null) {
     585                    throw new SRUConfigException(
     586                            "Element <AvailableDataViews> " +
     587                                    "must have a 'ref' attribute");
     588                }
     589                String[] refs = ref.split("\\s+");
     590                if ((refs == null) || (refs.length < 1)) {
     591                    throw new SRUConfigException("Attribute 'ref' on element " +
     592                            "<AvailableDataViews> must contain a whitespace " +
     593                            "seperated list of data view references");
     594                }
     595
     596                for (int i = 0; i < refs.length; i++) {
     597                    DataView dataview = null;
     598                    for (DataView dv : supportedDataViews) {
     599                        if (refs[i].equals(dv.getIdentifier())) {
     600                            dataview = dv;
     601                            break;
     602                        }
     603                    }
     604                    if (dataview != null) {
     605                        if (availableDataViews == null) {
     606                            availableDataViews = new ArrayList<DataView>();
     607                        }
     608                        availableDataViews.add(dataview);
     609                    } else {
     610                        throw new SRUConfigException(
     611                                "A data view with " + "identifier '" + refs[i] +
     612                                        "' was not defined " +
     613                                        "in <SupportedDataViews>");
     614                    }
     615                }
     616            } else {
     617                throw new SRUConfigException(
     618                        "missing element <AvailableDataViews>");
     619            }
     620            if (availableDataViews == null) {
     621                throw new SRUConfigException("No available data views where " +
     622                        "defined for resource with PID '" + pid + "'");
     623            }
     624
     625            exp = xpath.compile("ed:AvailableLayers");
     626            n = (Node) exp.evaluate(node, XPathConstants.NODE);
     627            if ((n != null) && (n instanceof Element)) {
     628                String ref = getAttribute((Element) n, "ref");
     629                if (ref == null) {
     630                    throw new SRUConfigException("Element <AvailableLayers> " +
     631                            "must have a 'ref' attribute");
     632                }
     633                String[] refs = ref.split("\\s+");
     634                if ((refs == null) || (refs.length < 1)) {
     635                    throw new SRUConfigException("Attribute 'ref' on element " +
     636                            "<AvailableLayers> must contain a whitespace " +
     637                            "seperated list of data view references");
     638                }
     639
     640                for (int i = 0; i < refs.length; i++) {
     641                    Layer layer = null;
     642                    for (Layer l : supportedLayers) {
     643                        if (refs[i].equals(l.getId())) {
     644                            layer = l;
     645                            break;
     646                        }
     647                    }
     648                    if (layer != null) {
     649                        if (availableLayers == null) {
     650                            availableLayers = new ArrayList<Layer>();
     651                        }
     652                        availableLayers.add(layer);
     653                    } else {
     654                        throw new SRUConfigException("A layer with " +
     655                                "identifier '" + refs[i] +
     656                                "' was not defined " + "in <SupportedLayers>");
     657                    }
     658                }
     659            } else {
     660                if (hasAdv) {
     661                    logger.debug("no <SupportedLayers> for ressource '{}'",
     662                            pid);
     663                }
     664            }
     665
     666            exp = xpath.compile("ed:Resources/ed:Resource");
     667            list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
     668            if ((list != null) && (list.getLength() > 0)) {
     669                sub = parseResources(xpath, list, pids, supportedDataViews,
     670                        supportedLayers, version, hasAdv);
     671            }
     672
     673            if (ris == null) {
     674                ris = new ArrayList<ResourceInfo>();
     675            }
     676            if ((availableLayers != null) && (version < 1)) {
     677                logger.warn("Endpoint claims to support FCS 1.0, but " +
     678                        "includes information about <AvailableLayers> for " +
     679                        "resource with pid '{}'", pid);
     680            }
     681            ris.add(new ResourceInfo(pid, titles, descrs, link, langs,
     682                    availableDataViews, availableLayers, sub));
     683        }
     684        return ris;
    655685    }
    656686
Note: See TracChangeset for help on using the changeset viewer.