/**
   * Merges an existing annotation index into the currently-generated one.
   *
   * <p>This method is used to read previously-indexed annotations and reconcile them with the
   * newly-generated ones just.
   *
   * @param annotationName the name of the annotation for which the index contains the annotated
   *     classes
   * @param factory the factory to generate input and output streams given an annotation name
   * @throws IOException
   */
  protected synchronized void merge(final String annotationName, final StreamFactory factory)
      throws IOException {
    final InputStream in = factory.openInput(annotationName);
    if (in == null) {
      return;
    }
    Map<String, Object> map = this.map.get(annotationName);
    if (map == null) {
      map = new LinkedHashMap<String, Object>();
      this.map.put(annotationName, map);
    }
    /*
     * To determine whether the index needs to be written out,
     * we need to keep track of changed entries.
     */
    int changedCount = map.size();
    boolean hasObsoletes = false;

    final IndexReader reader = new IndexReader(in);
    try {
      for (; ; ) {
        @SuppressWarnings("unchecked")
        final Map<String, Object> entry = (Map<String, Object>) reader.next();
        if (entry == null) {
          break;
        }
        final String className = (String) entry.get("class");
        if (factory.isClassObsolete(className)) {
          hasObsoletes = true;
        } else if (map.containsKey(className)) {
          if (!hasObsoletes && entry.equals(map.get(className))) {
            changedCount--;
          }
        } else {
          map.put(className, entry);
        }
      }
    } finally {
      reader.close();
    }
    // if this annotation index is unchanged, no need to write it out again
    if (changedCount == 0 && !hasObsoletes) {
      this.map.remove(annotationName);
    }
  }
  protected void destroyed(context c) {
    synchronized (lock) {
      if (current_context == c) {

        current_context = null;
      }
    }

    stream_factory.destroyed(c);
  }
 protected synchronized void write(final StreamFactory factory) throws IOException {
   for (Entry<String, Map<String, Object>> entry : map.entrySet()) {
     final String annotationName = entry.getKey();
     merge(annotationName, factory);
     final PrintStream out = new PrintStream(factory.openOutput(annotationName));
     for (Object o : entry.getValue().values()) {
       writeObject(out, adapt(o));
     }
     out.close();
   }
   map.clear();
 }