/**
   * Initializes HashMaps for MetaMetadata selectors by URL or pattern. Uses the Media and Document
   * base classes to ensure that maps are only filled with appropriate matching MetaMetadata.
   */
  private void initializeLocationBasedMaps() {
    // 1st pass -- resolve nested and collection types as needed -- fill in all child metadata
    // fields
    /*
     * for (MetaMetadata metaMetadata : repositoryByTagName) { metaMetadata.bindNonScalarChildren();
     * }
     */

    for (MetaMetadata metaMetadata : repositoryByTagName) {
      metaMetadata.inheritMetaMetadata(this);
      Class<? extends Metadata> metadataClass = metaMetadata.getMetadataClass(metadataTScope);
      if (metadataClass == null) {
        error(metaMetadata + "\tCan't resolve in TranslationScope " + metadataTScope);
        continue;
      }

      HashMap<String, MetaMetadata> repositoryByPURL;
      HashMap<String, ArrayList<RepositoryPatternEntry>> repositoryByPattern;

      if (Media.class.isAssignableFrom(metadataClass)) {
        repositoryByPURL = mediaRepositoryByURL;
        repositoryByPattern = mediaRepositoryByPattern;
      } else if (Document.class.isAssignableFrom(metadataClass)) {
        repositoryByPURL = documentRepositoryByURL;
        repositoryByPattern = documentRepositoryByPattern;
      } else continue;

      ParsedURL purl = metaMetadata.getUrlBase();
      if (purl != null) repositoryByPURL.put(purl.noAnchorNoQueryPageString(), metaMetadata);
      else {
        ParsedURL urlPrefix = metaMetadata.getUrlPrefix();
        if (urlPrefix != null) {
          urlprefixCollection.add(urlPrefix);
          repositoryByPURL.put(urlPrefix.toString(), metaMetadata);
        } else {
          String domain = metaMetadata.getDomain();
          Pattern urlPattern = metaMetadata.getUrlRegex();
          if (domain != null && urlPattern != null) {
            ArrayList<RepositoryPatternEntry> bucket = repositoryByPattern.get(domain);
            if (bucket == null) {
              bucket = new ArrayList<RepositoryPatternEntry>(2);
              repositoryByPattern.put(domain, bucket);
            }
            bucket.add(new RepositoryPatternEntry(urlPattern, metaMetadata));
          }
        }
      }
    }
  }
 @Override
 public Object operateOn(Object rawValue) {
   if (rawValue != null && name != null && value != null) {
     ParsedURL purl =
         (rawValue instanceof ParsedURL)
             ? ((ParsedURL) rawValue)
             : ParsedURL.getAbsolute(rawValue.toString());
     HashMap<String, String> params = purl.extractParams(true);
     if (!onlyWhenNotSet || !params.containsKey(name)) {
       params.put(name, value);
     }
     return purl.updateParams(params);
   }
   return rawValue;
 }
  public boolean checkForParams(final ParsedURL purl) {
    if (params != null) {
      HashMap<String, String> purlParams = purl.extractParams(true);
      for (MetaMetadataSelectorParam param : params) {
        String paramName = param.getName();
        String paramValue = param.getValue();
        String paramValueIsNot = param.getValueIsNot();
        String actualValue = purlParams == null ? null : purlParams.get(paramName);
        if (actualValue == null) {
          actualValue = "";
        }

        if (paramValue != null && paramValue.length() > 0) {

          boolean allowEmptyAndIsEmpty = param.isAllowEmptyValue() && actualValue.length() == 0;
          if (!allowEmptyAndIsEmpty && !paramValue.equals(actualValue)) {
            return false;
          }
        }

        if (paramValueIsNot != null && paramValueIsNot.length() > 0) {
          if (paramValueIsNot.equals(actualValue)) {
            return false;
          }
        }
      }
    }
    return true;
  }
  public MetaMetadata getMediaMM(ParsedURL purl, String tagName) {
    MetaMetadata result = null;
    if (purl != null && !purl.isFile()) {
      result = mediaRepositoryByURL.get(purl.noAnchorNoQueryPageString());

      if (result == null) {
        String protocolStrippedURL = purl.toString().split("://")[1];

        String key =
            purl.url().getProtocol()
                + "://"
                + urlprefixCollection.getMatchingPhrase(protocolStrippedURL, '/');

        result = mediaRepositoryByURL.get(key);

        if (result == null) {
          String domain = purl.domain();
          if (domain != null) {
            ArrayList<RepositoryPatternEntry> entries = mediaRepositoryByPattern.get(domain);
            if (entries != null) {
              for (RepositoryPatternEntry entry : entries) {
                Matcher matcher = entry.getPattern().matcher(purl.toString());
                if (matcher.find()) {
                  result = entry.getMetaMetadata();
                }
              }
            }
          }
        }
      }
    }
    return (result != null) ? result : getByTagName(tagName);
  }
  public void performDownload() throws IOException {
    System.out.println("Downloading: " + purl);

    InputStream inputStream = purl.url().openConnection().getInputStream();
    InputStreamReader isReader = new InputStreamReader(inputStream);

    char[] charBuffer = new char[initialBufferSize];

    int beginIndex = 0;
    int endIndex = charChunkSize - 1;
    while (isReader.read(charBuffer, beginIndex, endIndex - beginIndex) != -1) {
      beginIndex += charChunkSize;
      endIndex += charChunkSize;
    }

    finalContent = String.valueOf(charBuffer);
    isDone = true;
  }
  /**
   * Get MetaMetadata. First, try matching by url_base. If this fails, including if the attribute is
   * null, then try by url_prefix. If this fails, including if the attribute is null, then try by
   * url_pattern (regular expression).
   *
   * <p>If that lookup fails, then lookup by tag name, to acquire the default.
   *
   * @param purl
   * @param tagName
   * @return
   */
  public MetaMetadata getDocumentMM(ParsedURL purl, String tagName) {
    MetaMetadata result = null;
    if (purl != null) {
      if (!purl.isFile()) {
        result = documentRepositoryByURL.get(purl.noAnchorNoQueryPageString());

        if (result == null) {
          String protocolStrippedURL = purl.toString().split("://")[1];
          String matchingPhrase = urlprefixCollection.getMatchingPhrase(protocolStrippedURL, '/');
          // FIXME -- andruid needs abhinav to explain this code better and make more clear!!!
          if (matchingPhrase != null) {
            String key = purl.url().getProtocol() + "://" + matchingPhrase;

            result = documentRepositoryByURL.get(key);
          }
        }

        if (result == null) {
          String domain = purl.domain();
          if (domain != null) {
            ArrayList<RepositoryPatternEntry> entries = documentRepositoryByPattern.get(domain);
            if (entries != null) {
              for (RepositoryPatternEntry entry : entries) {
                Matcher matcher = entry.getPattern().matcher(purl.toString());
                if (matcher.find()) {
                  result = entry.getMetaMetadata();
                }
              }
            }
          }
        }
      }
      // Lastly, check for MMD by suffix
      if (result == null) {
        String suffix = purl.suffix();

        if (suffix != null) result = getMMBySuffix(suffix);
      }
    }

    return (result != null) ? result : getByTagName(tagName);
  }
 /** @return What to tell the user about what is being downloaded. */
 public String message() {
   return purl.toString();
 }