blob: 425a415dd8c8f2f5ccbf809471d7c10a3412be5b [file] [log] [blame]
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 com.sun.org.apache.xerces.internal.util;
import com.sun.org.apache.xerces.internal.xni.Augmentations;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/**
* This class provides an implementation for Augmentations interface.
* Augmentations interface defines a map 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() {
StringBuilder buff = new StringBuilder();
buff.append("SmallContainer - fNumEntries == ").append(fNumEntries);
for (int i = 0; i < SIZE_LIMIT*2; i=i+2) {
buff.append("\nfAugmentations[")
.append(i)
.append("] == ")
.append(fAugmentations[i])
.append("; fAugmentations[")
.append(i+1)
.append("] == ")
.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 Map<Object, Object> fAugmentations = new HashMap<>();
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 Collections.enumeration(fAugmentations.keySet());
}
public void clear() {
fAugmentations.clear();
}
public boolean isFull() {
return false;
}
public AugmentationsItemsContainer expand() {
return this;
}
public String toString() {
StringBuilder buff = new StringBuilder();
buff.append("LargeContainer");
for(Object key : fAugmentations.keySet()) {
buff.append("\nkey == ");
buff.append(key);
buff.append("; value == ");
buff.append(fAugmentations.get(key));
}
return buff.toString();
}
}
}