content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *   along with AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * reserved comment block
   * DO NOT REMOVE OR ALTER!
   */
  /*
   * Copyright 2000-2002,2004 The Apache Software Foundation.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package jaxp.sun.org.apache.xerces.internal.util;
  
  import java.util.Hashtable;
  import java.util.Enumeration;
  
  import jaxp.sun.org.apache.xerces.internal.xni.Augmentations;
  
  /**
   * This class provides an implementation for Augmentations interface.
   * Augmentations interface defines a hashtable of additional data that could
   * be passed along the document pipeline. The information can contain extra
   * arguments or infoset augmentations, for example PSVI. This additional
   * information is identified by a String key.
   * <p>
   *
   * @author Elena Litani, IBM
   */
  public class AugmentationsImpl implements Augmentations {
  
      private AugmentationsItemsContainer fAugmentationsContainer =
                                          new SmallContainer();
  
      /**
       * Add additional information identified by a key to the Augmentations structure.
       *
       * @param key    Identifier, can't be <code>null</code>
       * @param item   Additional information
       *
       * @return the previous value of the specified key in the Augmentations strucutre,
       *         or <code>null</code> if it did not have one.
       */
      public Object putItem (String key, Object item){
          Object oldValue = fAugmentationsContainer.putItem(key, item);
  
          if (oldValue == null && fAugmentationsContainer.isFull()) {
              fAugmentationsContainer = fAugmentationsContainer.expand();
          }
  
          return oldValue;
      }
  
  
      /**
       * Get information identified by a key from the Augmentations structure
       *
       * @param key    Identifier, can't be <code>null</code>
       *
       * @return the value to which the key is mapped in the Augmentations structure;
       *         <code>null</code> if the key is not mapped to any value.
       */
      public Object getItem(String key){
          return fAugmentationsContainer.getItem(key);
      }
  
  
      /**
       * Remove additional info from the Augmentations structure
       *
       * @param key    Identifier, can't be <code>null</code>
       */
      public Object removeItem (String key){
          return fAugmentationsContainer.removeItem(key);
      }
  
      /**
       * Returns an enumeration of the keys in the Augmentations structure
       *
       */
      public Enumeration keys (){
          return fAugmentationsContainer.keys();
      }
  
      /**
       * Remove all objects from the Augmentations structure.
       */
      public void removeAllItems() {
          fAugmentationsContainer.clear();
      }
  
      public String toString() {
          return fAugmentationsContainer.toString();
      }
  
      abstract class AugmentationsItemsContainer {
          abstract public Object putItem(Object key, Object item);
          abstract public Object getItem(Object key);
          abstract public Object removeItem(Object key);
          abstract public Enumeration keys();
          abstract public void clear();
          abstract public boolean isFull();
          abstract public AugmentationsItemsContainer expand();
      }
  
      class SmallContainer extends AugmentationsItemsContainer {
          final static int SIZE_LIMIT = 10;
          final Object[] fAugmentations = new Object[SIZE_LIMIT*2];
          int fNumEntries = 0;
  
          public Enumeration keys() {
              return new SmallContainerKeyEnumeration();
          }
  
          public Object getItem(Object key) {
              for (int i = 0; i < fNumEntries*2; i = i + 2) {
                  if (fAugmentations[i].equals(key)) {
                      return fAugmentations[i+1];
                  }
              }
  
              return null;
          }
  
          public Object putItem(Object key, Object item) {
              for (int i = 0; i < fNumEntries*2; i = i + 2) {
                  if (fAugmentations[i].equals(key)) {
                      Object oldValue = fAugmentations[i+1];
                      fAugmentations[i+1] = item;
  
                      return oldValue;
                  }
              }
  
              fAugmentations[fNumEntries*2] = key;
              fAugmentations[fNumEntries*2+1] = item;
              fNumEntries++;
  
              return null;
          }
  
  
          public Object removeItem(Object key) {
              for (int i = 0; i < fNumEntries*2; i = i + 2) {
                  if (fAugmentations[i].equals(key)) {
                      Object oldValue = fAugmentations[i+1];
  
                      for (int j = i; j < fNumEntries*2 - 2; j = j + 2) {
                          fAugmentations[j] = fAugmentations[j+2];
                          fAugmentations[j+1] = fAugmentations[j+3];
                      }
  
                      fAugmentations[fNumEntries*2-2] = null;
                      fAugmentations[fNumEntries*2-1] = null;
                      fNumEntries--;
  
                      return oldValue;
                  }
              }
  
              return null;
          }
  
          public void clear() {
              for (int i = 0; i < fNumEntries*2; i = i + 2) {
                  fAugmentations[i] = null;
                  fAugmentations[i+1] = null;
              }
  
              fNumEntries = 0;
          }
  
          public boolean isFull() {
              return (fNumEntries == SIZE_LIMIT);
          }
  
          public AugmentationsItemsContainer expand() {
              LargeContainer expandedContainer = new LargeContainer();
  
              for (int i = 0; i < fNumEntries*2; i = i + 2) {
                  expandedContainer.putItem(fAugmentations[i],
                                            fAugmentations[i+1]);
              }
  
              return expandedContainer;
          }
  
          public String toString() {
              StringBuffer buff = new StringBuffer();
              buff.append("SmallContainer - fNumEntries == " + fNumEntries);
  
              for (int i = 0; i < SIZE_LIMIT*2; i=i+2) {
                  buff.append("\nfAugmentations[");
                  buff.append(i);
                  buff.append("] == ");
                  buff.append(fAugmentations[i]);
                  buff.append("; fAugmentations[");
                  buff.append(i+1);
                  buff.append("] == ");
                  buff.append(fAugmentations[i+1]);
              }
  
              return buff.toString();
          }
  
          class SmallContainerKeyEnumeration implements Enumeration {
              Object [] enumArray = new Object[fNumEntries];
              int next = 0;
  
              SmallContainerKeyEnumeration() {
                  for (int i = 0; i < fNumEntries; i++) {
                      enumArray[i] = fAugmentations[i*2];
                  }
              }
  
              public boolean hasMoreElements() {
                  return next < enumArray.length;
              }
  
              public Object nextElement() {
                  if (next >= enumArray.length) {
                      throw new java.util.NoSuchElementException();
                  }
  
                  Object nextVal = enumArray[next];
                  enumArray[next] = null;
                  next++;
  
                  return nextVal;
              }
          }
      }
  
      class LargeContainer extends AugmentationsItemsContainer {
          final Hashtable fAugmentations = new Hashtable();
  
          public Object getItem(Object key) {
              return fAugmentations.get(key);
          }
  
          public Object putItem(Object key, Object item) {
              return fAugmentations.put(key, item);
          }
  
          public Object removeItem(Object key) {
              return fAugmentations.remove(key);
          }
  
          public Enumeration keys() {
              return fAugmentations.keys();
          }
  
          public void clear() {
              fAugmentations.clear();
          }
  
          public boolean isFull() {
              return false;
          }
  
          public AugmentationsItemsContainer expand() {
              return this;
          }
  
          public String toString() {
              StringBuffer buff = new StringBuffer();
              buff.append("LargeContainer");
              Enumeration keys = fAugmentations.keys();
  
              while (keys.hasMoreElements()) {
                  Object key = keys.nextElement();
                  buff.append("\nkey == ");
                  buff.append(key);
                  buff.append("; value == ");
                  buff.append(fAugmentations.get(key));
              }
  
              return buff.toString();
          }
      }
  }
  