private void buildCases() throws Exception {
    List<Element> cases = INDEX_CASES.get().evalAsNativeElementList(doc);
    for (Element caseEl : cases) {
      WildcardPattern matchNamespace = null;
      WildcardPattern matchName = null;

      String matchNamespaceAttr = DocumentHelper.getAttribute(caseEl, "matchNamespace", false);

      if (matchNamespaceAttr != null) {
        // If the matchNamespace attr does not contain a wildcard expression, and its value
        // happens to be an existing namespace prefix, than substitute the prefix for the full URI.
        if (!WildcardPattern.isWildcardExpression(matchNamespaceAttr)) {
          String uri = caseEl.lookupNamespaceURI(matchNamespaceAttr);
          if (uri != null) matchNamespaceAttr = uri;
        }
        matchNamespace = new WildcardPattern(matchNamespaceAttr);
      }

      String matchNameAttr = DocumentHelper.getAttribute(caseEl, "matchName", false);

      if (matchNameAttr != null) {
        matchName = new WildcardPattern(matchNameAttr);
      }

      String vtagsSpec = DocumentHelper.getAttribute(caseEl, "vtags", false);

      Map<String, String> varPropsPattern = parseVariantPropertiesPattern(caseEl);
      Set<SchemaId> vtags = parseVersionTags(vtagsSpec);

      IndexCase indexCase = new IndexCase(matchNamespace, matchName, varPropsPattern, vtags);
      conf.addIndexCase(indexCase);
    }
  }
  private Value buildValue(Element fieldEl) throws Exception {
    String valueExpr = DocumentHelper.getAttribute(fieldEl, "value", true);

    Value value;

    boolean extractContent = DocumentHelper.getBooleanAttribute(fieldEl, "extractContent", false);

    String formatter = DocumentHelper.getAttribute(fieldEl, "formatter", false);
    if (formatter != null && !conf.getFormatters().hasFormatter(formatter)) {
      throw new IndexerConfException(
          "Formatter does not exist: "
              + formatter
              + " at "
              + LocationAttributes.getLocationString(fieldEl));
    }

    //
    // An index field can basically map to two kinds of values:
    //   * plain field values
    //   * dereference expressions (following links to some other record and then taking a field
    // value from it)
    //

    // A dereference expression is specified as "somelink=>somelink=>somefield"

    if (valueExpr.contains("=>")) {
      //
      // A dereference field
      //
      value = buildDerefValue(fieldEl, valueExpr, extractContent, formatter);
    } else {
      //
      // A plain field
      //
      value = new FieldValue(getFieldType(valueExpr, fieldEl), extractContent, formatter);
    }

    if (extractContent
        && !value
            .getTargetFieldType()
            .getValueType()
            .getDeepestValueType()
            .getBaseName()
            .equals("BLOB")) {
      throw new IndexerConfException(
          "extractContent is used for a non-blob value at "
              + LocationAttributes.getLocation(fieldEl));
    }

    return value;
  }
  private Map<String, String> parseVariantPropertiesPattern(Element caseEl) throws Exception {
    String variant = DocumentHelper.getAttribute(caseEl, "matchVariant", false);

    Map<String, String> varPropsPattern = new HashMap<String, String>();

    if (variant == null) return varPropsPattern;

    for (String prop : COMMA_SPLITTER.split(variant)) {
      int eqPos = prop.indexOf("=");
      if (eqPos != -1) {
        String propName = prop.substring(0, eqPos);
        String propValue = prop.substring(eqPos + 1);
        if (propName.equals("*")) {
          throw new IndexerConfException(
              String.format(
                  "Error in matchVariant attribute: the character '*' "
                      + "can only be used as wildcard, not as variant dimension name, attribute = %1$s, at: %2$s",
                  variant, LocationAttributes.getLocation(caseEl)));
        }
        varPropsPattern.put(propName, propValue);
      } else {
        varPropsPattern.put(prop, null);
      }
    }

    return varPropsPattern;
  }
 public static IndexerConf build(InputStream is, Repository repository)
     throws IndexerConfException {
   Document doc;
   try {
     doc = DocumentHelper.parse(is);
   } catch (Exception e) {
     throw new IndexerConfException("Error parsing supplied configuration.", e);
   }
   return new IndexerConfBuilder().build(doc, repository);
 }
  private void buildFormatters() throws Exception {
    List<Element> formatters = FORMATTERS.get().evalAsNativeElementList(doc);
    for (Element formatterEl : formatters) {
      String className = DocumentHelper.getAttribute(formatterEl, "class", true);
      Formatter formatter = instantiateFormatter(className);

      String name = DocumentHelper.getAttribute(formatterEl, "name", true);

      if (name != null && conf.getFormatters().hasFormatter(name)) {
        throw new IndexerConfException("Duplicate formatter name: " + name);
      }

      conf.getFormatters().addFormatter(formatter, name);
    }

    String defaultFormatter = XPathUtils.evalString("/indexer/formatters/@default", doc);
    if (defaultFormatter.length() != 0) {
      conf.getFormatters().setDefaultFormatter(defaultFormatter);
    }
  }
  private void buildIndexFields() throws Exception {
    List<Element> indexFields = INDEX_FIELDS.get().evalAsNativeElementList(doc);
    for (Element indexFieldEl : indexFields) {
      String name = DocumentHelper.getAttribute(indexFieldEl, "name", true);
      validateName(name);

      Value value = buildValue(indexFieldEl);

      IndexField indexField = new IndexField(name, value);
      conf.addIndexField(indexField);
    }
  }
  @Override
  public int run(CommandLine cmd) throws Exception {
    int result = super.run(cmd);
    if (result != 0) {
      return result;
    }

    String collection = cmd.getOptionValue(collectionOption.getOpt());
    if (collection == null) {
      collection = DEFFAULT_COLLECTION;
    }
    String branch = cmd.getOptionValue(branchOption.getOpt());
    if (branch == null) {
      branch = DEFFAULT_BRANCH;
    }

    RepositoryManager repositoryManager =
        new RemoteRepositoryManager(
            "http://lilyproject.org:9263", new Credentials("guest", "guest"));
    Repository repository = repositoryManager.getRepository(new Credentials("guest", "guest"));
    QueryManager queryManager = repository.getQueryManager();
    RepositorySchema schema = repository.getRepositorySchema();

    String query =
        "select id, name where InCollection('" + collection + "') and branch = '" + branch + "'";
    VariantKey[] keys = queryManager.performQueryReturnKeys(query, Locale.getDefault());

    for (VariantKey key : keys) {
      Document doc = repository.getDocument(key, false);
      Version version = doc.getLiveVersion();
      if (version == null) {
        continue;
      }

      for (Part part : version.getParts().getArray()) {
        if (schema.getPartTypeById(part.getTypeId(), false).isDaisyHtml()) {
          InputStream is = part.getDataStream();
          org.w3c.dom.Document domDoc = DocumentHelper.parse(is);
          NodeList links = XPathUtils.evalNodeList("//a/@href", domDoc.getDocumentElement());
          for (int j = 0; j < links.getLength(); j++) {
            String link = ((Attr) links.item(j)).getValue();
            System.out.printf(
                "[%1$10.10s][%2$30.30s][%3$10.10s] %4$s\n",
                key.getDocumentId(), version.getDocumentName(), part.getTypeName(), link);
          }
          is.close();
        }
      }
    }

    return 0;
  }
  private void buildDynamicFields() throws Exception {
    List<Element> fields = DYNAMIC_INDEX_FIELDS.get().evalAsNativeElementList(doc);
    for (Element fieldEl : fields) {
      String matchNamespaceAttr = DocumentHelper.getAttribute(fieldEl, "matchNamespace", false);
      String matchNameAttr = DocumentHelper.getAttribute(fieldEl, "matchName", false);
      String matchTypeAttr = DocumentHelper.getAttribute(fieldEl, "matchType", false);
      String matchScopeAttr = DocumentHelper.getAttribute(fieldEl, "matchScope", false);
      String nameAttr = DocumentHelper.getAttribute(fieldEl, "name", true);

      WildcardPattern matchNamespace = null;
      if (matchNamespaceAttr != null) {
        // If the matchNamespace attr does not contain a wildcard expression, and its value
        // happens to be an existing namespace prefix, than substitute the prefix for the full URI.
        if (!WildcardPattern.isWildcardExpression(matchNamespaceAttr)) {
          String uri = fieldEl.lookupNamespaceURI(matchNamespaceAttr);
          if (uri != null) matchNamespaceAttr = uri;
        }
        matchNamespace = new WildcardPattern(matchNamespaceAttr);
      }

      WildcardPattern matchName = null;
      if (matchNameAttr != null) {
        matchName = new WildcardPattern(matchNameAttr);
      }

      TypePattern matchTypes = null;
      if (matchTypeAttr != null) {
        matchTypes = new TypePattern(matchTypeAttr);
      }

      Set<Scope> matchScopes = null;
      if (matchScopeAttr != null) {
        matchScopes = EnumSet.noneOf(Scope.class);
        for (String scope : COMMA_SPLITTER.split(matchScopeAttr)) {
          matchScopes.add(Scope.valueOf(scope));
        }
        if (matchScopes.isEmpty()) {
          matchScopes = null;
        }
      }

      // Be gentle to users of Lily 1.0 and warn them about attributes that are not supported
      // anymore
      if (DocumentHelper.getAttribute(fieldEl, "matchMultiValue", false) != null) {
        log.warn(
            "The attribute matchMultiValue on dynamicField is not supported anymore, it will be ignored.");
      }
      if (DocumentHelper.getAttribute(fieldEl, "matchHierarchical", false) != null) {
        log.warn(
            "The attribute matchHierarchical on dynamicField is not supported anymore, it will be ignored.");
      }

      Set<String> variables = new HashSet<String>();
      variables.add("namespace");
      variables.add("name");
      variables.add("type");
      variables.add("baseType");
      variables.add("nestedType");
      variables.add("nestedBaseType");
      variables.add("deepestNestedBaseType");
      if (matchName != null && matchName.hasWildcard()) variables.add("nameMatch");
      if (matchNamespace != null && matchNamespace.hasWildcard()) variables.add("namespaceMatch");

      Set<String> booleanVariables = new HashSet<String>();
      booleanVariables.add("list");
      booleanVariables.add("multiValue");

      NameTemplate name = new NameTemplate(nameAttr, variables, booleanVariables);

      boolean extractContent = DocumentHelper.getBooleanAttribute(fieldEl, "extractContent", false);

      String formatter = DocumentHelper.getAttribute(fieldEl, "formatter", false);
      if (formatter != null && !conf.getFormatters().hasFormatter(formatter)) {
        throw new IndexerConfException(
            "Formatter does not exist: "
                + formatter
                + " at "
                + LocationAttributes.getLocationString(fieldEl));
      }

      boolean continue_ = DocumentHelper.getBooleanAttribute(fieldEl, "continue", false);

      DynamicIndexField field =
          new DynamicIndexField(
              matchNamespace,
              matchName,
              matchTypes,
              matchScopes,
              name,
              extractContent,
              continue_,
              formatter);

      conf.addDynamicIndexField(field);
    }
  }