Index: /FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/Layer.java
===================================================================
--- /FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/Layer.java	(revision 6837)
+++ /FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/Layer.java	(revision 6838)
@@ -27,5 +27,5 @@
     private final String qualifier;
     private final String altValueInfo;
-    private final String altValueInfoURI;
+    private final URI altValueInfoURI;
 
 
@@ -51,5 +51,5 @@
     public Layer(String id, URI resultId, String type,
             ContentEncoding encoding, String qualifier, String altValueInfo,
-            String altValueInfoURI) {
+            URI altValueInfoURI) {
         if (id == null) {
             throw new NullPointerException("id == null");
@@ -161,5 +161,5 @@
      *         layer or <code>null</code>
      */
-    public String getAltValueInfoURI() {
+    public URI getAltValueInfoURI() {
         return altValueInfoURI;
     }
Index: /FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/SimpleEndpointSearchEngineBase.java
===================================================================
--- /FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/SimpleEndpointSearchEngineBase.java	(revision 6837)
+++ /FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/SimpleEndpointSearchEngineBase.java	(revision 6838)
@@ -292,5 +292,5 @@
                     if (layer.getAltValueInfoURI() != null) {
                         writer.writeAttribute("alt-value-info-uri",
-                                layer.getAltValueInfoURI());
+                                layer.getAltValueInfoURI().toString());
                     }
                 }
Index: /FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/utils/SimpleEndpointDescriptionParser.java
===================================================================
--- /FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/utils/SimpleEndpointDescriptionParser.java	(revision 6837)
+++ /FCSSimpleEndpoint/trunk/src/main/java/eu/clarin/sru/server/fcs/utils/SimpleEndpointDescriptionParser.java	(revision 6838)
@@ -59,7 +59,11 @@
     private static final URI CAP_ADVANCED_SEARCH =
             URI.create("http://clarin.eu/fcs/capability/advanced-search");
+    private static final String MINETYPE_HITS = "application/x-clarin-fcs-hits+xml";
+    private static final String MINETYPE_ADV = "application/x-clarin-fcs-adv+xml";
     private static final String LANG_EN = "en";
     private static final String POLICY_SEND_DEFAULT = "send-by-default";
     private static final String POLICY_NEED_REQUEST = "need-to-request";
+    private static final String LAYER_ENCODING_VALUE = "value";
+    private static final String LAYER_ENCODING_EMPTY = "empty";
     private static final Logger logger =
             LoggerFactory.getLogger(SimpleEndpointDescriptionParser.class);
@@ -153,9 +157,10 @@
                 try {
                     URI uri = new URI(s);
-                    if (capabilities.contains(uri)) {
+                    if (!capabilities.contains(uri)) {
+                        capabilities.add(uri);
+                    } else {
                         logger.warn("ignoring duplicate capability " +
                                 "entry for '{}'", uri);
                     }
-                    capabilities.add(uri);
                 } catch (URISyntaxException e) {
                     throw new SRUConfigException("capability is not encoded " +
@@ -174,4 +179,7 @@
         }
         logger.debug("CAPS:'{}'", capabilities);
+
+        // used to check for id attribute uniqueness
+        final Set<String> xml_ids = new HashSet<String>();
 
         // supported data views
@@ -188,4 +196,11 @@
                             + "must carry a proper 'id' attribute");
                 }
+
+                if (xml_ids.contains(id)) {
+                    throw new SRUConfigException("The value of attribute " +
+                            "'id' of element <SupportedDataView> must be unique: " + id);
+                }
+                xml_ids.add(id);
+
                 String p = getAttribute(item, "delivery-policy");
                 if (p == null) {
@@ -239,4 +254,26 @@
         logger.debug("DV: {}", supportedDataViews);
 
+        // sanity check on data views
+        boolean hasHitsView = false;
+        boolean hasAdvView = false;
+
+        for (DataView dataView : supportedDataViews) {
+            if (dataView.getMimeType().equals(MINETYPE_HITS)) {
+                hasHitsView = true;
+            } else if (dataView.getMimeType().equals(MINETYPE_ADV)) {
+                hasAdvView = true;
+            }
+        }
+        if (!hasHitsView) {
+            throw new SRUConfigException("Generic Hits Data View (" +
+                    MINETYPE_HITS + ") was not declared in <SupportedDataViews>");
+        }
+        if (capabilities.contains(CAP_ADVANCED_SEARCH) && !hasAdvView) {
+            throw new SRUConfigException("Endpoint claimes to support " +
+                    "Advanced FCS but does not declare Advanced Data View (" +
+                    MINETYPE_ADV + ") in <SupportedDataViews>");
+
+        }
+
 
         // supported layers
@@ -250,10 +287,17 @@
                 String id = getAttribute(item, "id");
                 if (id == null) {
-                    throw new SRUConfigException("Element <ed:SupportedLayer> "
+                    throw new SRUConfigException("Element <SupportedLayer> "
                             + "must carry a proper 'id' attribute");
                 }
+
+                if (xml_ids.contains(id)) {
+                    throw new SRUConfigException("The value of attribute " +
+                            "'id' of element <SupportedLayer> must be unique: " + id);
+                }
+                xml_ids.add(id);
+
                 String s = getAttribute(item, "result-id");
                 if (s == null) {
-                    throw new SRUConfigException("Element <ed:SupportedLayer> "
+                    throw new SRUConfigException("Element <SupportedLayer> "
                             + "must carry a proper 'result-id' attribute");
                 }
@@ -263,5 +307,5 @@
                 } catch (URISyntaxException e) {
                     throw new SRUConfigException("Attribute 'result-id' on " +
-                            "Element <ed:SupportedLayer> is not encoded " +
+                            "Element <SupportedLayer> is not encoded " +
                             "as proper URI: " + s);
                 }
@@ -269,20 +313,50 @@
                 String type = cleanString(item.getTextContent());
                 if ((type != null) && !type.isEmpty()) {
-
+                    // sanity check on layer types
+                    if (!(type.equals("text") ||
+                            type.equals("lemma") ||
+                            type.equals("pos") ||
+                            type.equals("orth") ||
+                            type.equals("norm") ||
+                            type.equals("phonetic") ||
+                            type.startsWith("x-"))) {
+                        logger.warn("layer type '{}' is not defined by specification", type);
+                    }
                 } else {
-                    throw new SRUConfigException("Element <ed:SupportedLayer> "
-                            + "as no proper type");
+                    throw new SRUConfigException("Element <SupportedLayer> " +
+                            "does not define a proper layer type");
                 }
 
                 String qualifier = getAttribute(item, "qualifier");
 
-                // FIXME: implement parsing of content encoding!
                 Layer.ContentEncoding encoding =
                         Layer.ContentEncoding.VALUE;
+                s = getAttribute(item, "type");
+                if (s != null) {
+                    if (LAYER_ENCODING_VALUE.equals(s)) {
+                        encoding = Layer.ContentEncoding.VALUE;
+                    } else if (LAYER_ENCODING_EMPTY.equals(s)) {
+                        encoding = Layer.ContentEncoding.EMPTY;
+                    } else {
+                        throw new SRUConfigException("invalid layer encoding: " + s);
+                    }
+                }
+
 
                 String altValueInfo = getAttribute(item, "alt-value-info");
-                String altValueInfoURI = null;
+                URI altValueInfoURI = null;
                 if (altValueInfo != null) {
-                    altValueInfoURI = getAttribute(item, "alt-value-info-uri");
+                    s = getAttribute(item, "alt-value-info-uri");
+                    if (s != null) {
+                        try {
+                          altValueInfoURI = new URI(s);
+                        } catch (URISyntaxException e) {
+                            throw new SRUConfigException("Attribute 'alt-value-info-uri' on " +
+                                    "Element <SupportedLayer> is not encoded " +
+                                    "as proper URI: " + s);
+                        }
+                    } else {
+
+                    }
                 }
 
@@ -309,7 +383,7 @@
         exp = xpath.compile("/ed:EndpointDescription/ed:Resources/ed:Resource");
         list = (NodeList) exp.evaluate(doc, XPathConstants.NODESET);
-        final Set<String> ids = new HashSet<String>();
-        List<ResourceInfo> resources = parseRessources(xpath, list, ids,
-                supportedDataViews, supportedLayers);
+        final Set<String> pids = new HashSet<String>();
+        List<ResourceInfo> resources = parseRessources(xpath, list, pids,
+                supportedDataViews, supportedLayers, hasAdvView);
         if ((resources == null) || resources.isEmpty()) {
             throw new SRUConfigException("No resources where " +
@@ -326,6 +400,6 @@
 
     private static List<ResourceInfo> parseRessources(XPath xpath,
-            NodeList nodes, Set<String> ids, List<DataView> supportedDataViews,
-            List<Layer> supportedLayers)
+            NodeList nodes, Set<String> pids, List<DataView> supportedDataViews,
+            List<Layer> supportedLayers, boolean hasAdv)
                     throws SRUConfigException, XPathExpressionException {
         List<ResourceInfo> ris = null;
@@ -346,15 +420,15 @@
                       "must carry a proper 'pid' attribute");
           }
-          if (ids.contains(pid)) {
+          if (pids.contains(pid)) {
               throw new SRUConfigException("Another element <Resource> " +
                       "with pid '" + pid + "' already exists");
           }
-          ids.add(pid);
-
-          XPathExpression x1 = xpath.compile("ed:Title");
-          NodeList l1 = (NodeList) x1.evaluate(node, XPathConstants.NODESET);
-          if ((l1 != null) && (l1.getLength() > 0)) {
-              for (int i = 0; i < l1.getLength(); i++) {
-                  final Element n = (Element) l1.item(i);
+          pids.add(pid);
+
+          XPathExpression exp = xpath.compile("ed:Title");
+          NodeList list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
+          if ((list != null) && (list.getLength() > 0)) {
+              for (int i = 0; i < list.getLength(); i++) {
+                  final Element n = (Element) list.item(i);
 
                   final String lang = getLangAttribute(n);
@@ -387,9 +461,9 @@
           }
 
-          XPathExpression x2 = xpath.compile("ed:Description");
-          NodeList l2 = (NodeList) x2.evaluate(node, XPathConstants.NODESET);
-          if ((l2 != null) && (l2.getLength() > 0)) {
-              for (int i = 0; i < l2.getLength(); i++) {
-                  Element n = (Element) l2.item(i);
+          exp = xpath.compile("ed:Description");
+          list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
+          if ((list != null) && (list.getLength() > 0)) {
+              for (int i = 0; i < list.getLength(); i++) {
+                  Element n = (Element) list.item(i);
 
                   String lang = getLangAttribute(n);
@@ -419,18 +493,18 @@
           }
 
-          XPathExpression x3 = xpath.compile("ed:LandingPageURI");
-          NodeList l3 = (NodeList) x3.evaluate(node, XPathConstants.NODESET);
-          if ((l3 != null) && (l3.getLength() > 0)) {
-              for (int i = 0; i < l3.getLength(); i++) {
-                  Element n = (Element) l3.item(i);
+          exp = xpath.compile("ed:LandingPageURI");
+          list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
+          if ((list != null) && (list.getLength() > 0)) {
+              for (int i = 0; i < list.getLength(); i++) {
+                  Element n = (Element) list.item(i);
                   link = cleanString(n.getTextContent());
               }
           }
 
-          XPathExpression x4 = xpath.compile("ed:Languages/ed:Language");
-          NodeList l4 = (NodeList) x4.evaluate(node, XPathConstants.NODESET);
-          if ((l4 != null) && (l4.getLength() > 0)) {
-              for (int i = 0; i < l4.getLength(); i++) {
-                  Element n = (Element) l4.item(i);
+          exp = xpath.compile("ed:Languages/ed:Language");
+          list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
+          if ((list != null) && (list.getLength() > 0)) {
+              for (int i = 0; i < list.getLength(); i++) {
+                  Element n = (Element) list.item(i);
 
                   String s = n.getTextContent();
@@ -458,6 +532,6 @@
           }
 
-          XPathExpression x5 = xpath.compile("ed:AvailableDataViews");
-          Node n = (Node) x5.evaluate(node, XPathConstants.NODE);
+          exp = xpath.compile("ed:AvailableDataViews");
+          Node n = (Node) exp.evaluate(node, XPathConstants.NODE);
           if ((n != null) && (n instanceof Element)) {
               String ref = getAttribute((Element) n, "ref");
@@ -495,5 +569,5 @@
           } else {
               throw new SRUConfigException(
-                      "missing element <ed:AvailableDataViews>");
+                      "missing element <AvailableDataViews>");
           }
           if (availableDataViews == null) {
@@ -502,9 +576,50 @@
           }
 
-          XPathExpression x6 = xpath.compile("ed:Resources/ed:Resource");
-          NodeList l6 = (NodeList) x6.evaluate(node, XPathConstants.NODESET);
-          if ((l6 != null) && (l6.getLength() > 0)) {
-              sub = parseRessources(xpath, l6, ids,
-                      supportedDataViews, supportedLayers);
+          exp = xpath.compile("ed:AvailableLayers");
+          n = (Node) exp.evaluate(node, XPathConstants.NODE);
+          if ((n != null) && (n instanceof Element)) {
+              String ref = getAttribute((Element) n, "ref");
+              if (ref == null) {
+                  throw new SRUConfigException("Element <AvailableLayers> " +
+                          "must carry a 'ref' attribute");
+              }
+              String[] refs = ref.split("\\s+");
+              if ((refs == null) || (refs.length < 1)) {
+                  throw new SRUConfigException("Attribute 'ref' on element " +
+                          "<AvailableLayers> must contain a whitespace " +
+                          "seperated list of data view references");
+              }
+
+
+              for (int i = 0; i < refs.length; i++) {
+                  Layer layer = null;
+                  for (Layer l : supportedLayers) {
+                      if (refs[i].equals(l.getId())) {
+                          layer = l;
+                          break;
+                      }
+                  }
+                  if (layer != null) {
+                      if (availableLayers == null) {
+                          availableLayers = new ArrayList<Layer>();
+                      }
+                      availableLayers.add(layer);
+                  } else {
+                      throw new SRUConfigException("A layer with " +
+                              "identifier '" + refs[i] + "' was not defined " +
+                              "in <SupportedLayers>");
+                  }
+              }
+          } else {
+              if (hasAdv) {
+                  logger.debug("no <SupportedLayers> for ressource '{}'", pid);
+              }
+          }
+
+          exp = xpath.compile("ed:Resources/ed:Resource");
+          list = (NodeList) exp.evaluate(node, XPathConstants.NODESET);
+          if ((list != null) && (list.getLength() > 0)) {
+              sub = parseRessources(xpath, list, pids,
+                      supportedDataViews, supportedLayers, hasAdv);
           }
 
@@ -526,9 +641,9 @@
 
     private static String getAttribute(Element el, String localName) {
-        String lang = el.getAttribute(localName);
-        if (lang != null) {
-            lang = lang.trim();
-            if (!lang.isEmpty()) {
-                return lang;
+        String value = el.getAttribute(localName);
+        if (value != null) {
+            value = value.trim();
+            if (!value.isEmpty()) {
+                return value;
             }
         }
