1 /* 2 * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. 3 * @LastModified: Oct 2017 4 */ 5 /* 6 * Licensed to the Apache Software Foundation (ASF) under one or more 7 * contributor license agreements. See the NOTICE file distributed with 8 * this work for additional information regarding copyright ownership. 9 * The ASF licenses this file to You under the Apache License, Version 2.0 10 * (the "License"); you may not use this file except in compliance with 11 * the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, software 16 * distributed under the License is distributed on an "AS IS" BASIS, 17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 * See the License for the specific language governing permissions and 19 * limitations under the License. 20 */ 21 22 package com.sun.org.apache.xerces.internal.util; 23 24 import com.sun.org.apache.xerces.internal.xni.Augmentations; 25 import java.util.Collections; 26 import java.util.Enumeration; 27 import java.util.HashMap; 28 import java.util.Map; 29 30 /** 31 * This class provides an implementation for Augmentations interface. 32 * Augmentations interface defines a map of additional data that could 33 * be passed along the document pipeline. The information can contain extra 34 * arguments or infoset augmentations, for example PSVI. This additional 35 * information is identified by a String key. 36 * <p> 37 * 38 * @author Elena Litani, IBM 39 */ 40 public class AugmentationsImpl implements Augmentations{ 41 42 private AugmentationsItemsContainer fAugmentationsContainer = 43 new SmallContainer(); 44 45 /** 46 * Add additional information identified by a key to the Augmentations structure. 47 * 48 * @param key Identifier, can't be <code>null</code> 49 * @param item Additional information 50 * 51 * @return the previous value of the specified key in the Augmentations strucutre, 52 * or <code>null</code> if it did not have one. 53 */ 54 public Object putItem (String key, Object item){ 55 Object oldValue = fAugmentationsContainer.putItem(key, item); 56 57 if (oldValue == null && fAugmentationsContainer.isFull()) { 58 fAugmentationsContainer = fAugmentationsContainer.expand(); 59 } 60 61 return oldValue; 62 } 63 64 65 /** 66 * Get information identified by a key from the Augmentations structure 67 * 68 * @param key Identifier, can't be <code>null</code> 69 * 70 * @return the value to which the key is mapped in the Augmentations structure; 71 * <code>null</code> if the key is not mapped to any value. 72 */ 73 public Object getItem(String key){ 74 return fAugmentationsContainer.getItem(key); 75 } 76 77 78 /** 79 * Remove additional info from the Augmentations structure 80 * 81 * @param key Identifier, can't be <code>null</code> 82 */ 83 public Object removeItem (String key){ 84 return fAugmentationsContainer.removeItem(key); 85 } 86 87 /** 88 * Returns an enumeration of the keys in the Augmentations structure 89 * 90 */ 91 public Enumeration<Object> keys (){ 92 return fAugmentationsContainer.keys(); 93 } 94 95 /** 96 * Remove all objects from the Augmentations structure. 97 */ 98 public void removeAllItems() { 99 fAugmentationsContainer.clear(); 100 } 101 102 public String toString() { 103 return fAugmentationsContainer.toString(); 104 } 105 106 abstract class AugmentationsItemsContainer { 107 abstract public Object putItem(Object key, Object item); 108 abstract public Object getItem(Object key); 109 abstract public Object removeItem(Object key); 110 abstract public Enumeration<Object> keys(); 111 abstract public void clear(); 112 abstract public boolean isFull(); 113 abstract public AugmentationsItemsContainer expand(); 114 } 115 116 class SmallContainer extends AugmentationsItemsContainer { 117 final static int SIZE_LIMIT = 10; 118 final Object[] fAugmentations = new Object[SIZE_LIMIT*2]; 119 int fNumEntries = 0; 120 121 public Enumeration<Object> keys() { 122 return new SmallContainerKeyEnumeration(); 123 } 124 125 public Object getItem(Object key) { 126 for (int i = 0; i < fNumEntries*2; i = i + 2) { 127 if (fAugmentations[i].equals(key)) { 128 return fAugmentations[i+1]; 129 } 130 } 131 132 return null; 133 } 134 135 public Object putItem(Object key, Object item) { 136 for (int i = 0; i < fNumEntries*2; i = i + 2) { 137 if (fAugmentations[i].equals(key)) { 138 Object oldValue = fAugmentations[i+1]; 139 fAugmentations[i+1] = item; 140 141 return oldValue; 142 } 143 } 144 145 fAugmentations[fNumEntries*2] = key; 146 fAugmentations[fNumEntries*2+1] = item; 147 fNumEntries++; 148 149 return null; 150 } 151 152 153 public Object removeItem(Object key) { 154 for (int i = 0; i < fNumEntries*2; i = i + 2) { 155 if (fAugmentations[i].equals(key)) { 156 Object oldValue = fAugmentations[i+1]; 157 158 for (int j = i; j < fNumEntries*2 - 2; j = j + 2) { 159 fAugmentations[j] = fAugmentations[j+2]; 160 fAugmentations[j+1] = fAugmentations[j+3]; 161 } 162 163 fAugmentations[fNumEntries*2-2] = null; 164 fAugmentations[fNumEntries*2-1] = null; 165 fNumEntries--; 166 167 return oldValue; 168 } 169 } 170 171 return null; 172 } 173 174 public void clear() { 175 for (int i = 0; i < fNumEntries*2; i = i + 2) { 176 fAugmentations[i] = null; 177 fAugmentations[i+1] = null; 178 } 179 180 fNumEntries = 0; 181 } 182 183 public boolean isFull() { 184 return (fNumEntries == SIZE_LIMIT); 185 } 186 187 public AugmentationsItemsContainer expand() { 188 LargeContainer expandedContainer = new LargeContainer(); 189 190 for (int i = 0; i < fNumEntries*2; i = i + 2) { 191 expandedContainer.putItem(fAugmentations[i], 192 fAugmentations[i+1]); 193 } 194 195 return expandedContainer; 196 } 197 198 public String toString() { 199 StringBuilder buff = new StringBuilder(); 200 buff.append("SmallContainer - fNumEntries == ").append(fNumEntries); 201 202 for (int i = 0; i < SIZE_LIMIT*2; i=i+2) { 203 buff.append("\nfAugmentations[") 204 .append(i) 205 .append("] == ") 206 .append(fAugmentations[i]) 207 .append("; fAugmentations[") 208 .append(i+1) 209 .append("] == ") 210 .append(fAugmentations[i+1]); 211 } 212 213 return buff.toString(); 214 } 215 216 class SmallContainerKeyEnumeration implements Enumeration<Object> { 217 Object [] enumArray = new Object[fNumEntries]; 218 int next = 0; 219 220 SmallContainerKeyEnumeration() { 221 for (int i = 0; i < fNumEntries; i++) { 222 enumArray[i] = fAugmentations[i*2]; 223 } 224 } 225 226 public boolean hasMoreElements() { 227 return next < enumArray.length; 228 } 229 230 public Object nextElement() { 231 if (next >= enumArray.length) { 232 throw new java.util.NoSuchElementException(); 233 } 234 235 Object nextVal = enumArray[next]; 236 enumArray[next] = null; 237 next++; 238 239 return nextVal; 240 } 241 } 242 } 243 244 class LargeContainer extends AugmentationsItemsContainer { 245 final Map<Object, Object> fAugmentations = new HashMap<>(); 246 247 public Object getItem(Object key) { 248 return fAugmentations.get(key); 249 } 250 251 public Object putItem(Object key, Object item) { 252 return fAugmentations.put(key, item); 253 } 254 255 public Object removeItem(Object key) { 256 return fAugmentations.remove(key); 257 } 258 259 public Enumeration<Object> keys() { 260 return Collections.enumeration(fAugmentations.keySet()); 261 } 262 263 public void clear() { 264 fAugmentations.clear(); 265 } 266 267 public boolean isFull() { 268 return false; 269 } 270 271 public AugmentationsItemsContainer expand() { 272 return this; 273 } 274 275 public String toString() { 276 StringBuilder buff = new StringBuilder(); 277 buff.append("LargeContainer"); 278 for(Object key : fAugmentations.keySet()) { 279 buff.append("\nkey == "); 280 buff.append(key); 281 buff.append("; value == "); 282 buff.append(fAugmentations.get(key)); 283 } 284 return buff.toString(); 285 } 286 } 287 }