1 /*
   2  * Copyright (c) 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.impl.xs.util;
  23 
  24 import com.sun.org.apache.xerces.internal.xs.XSObject;
  25 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  26 import java.lang.reflect.Array;
  27 import java.util.AbstractList;
  28 import java.util.Iterator;
  29 import java.util.ListIterator;
  30 import java.util.NoSuchElementException;
  31 
  32 /**
  33  * Containts a list of XSObject's.
  34  *
  35  * @xerces.internal
  36  *
  37  * @author Sandy Gao, IBM
  38  *
  39  */
  40 @SuppressWarnings("unchecked") // method <T>toArray(T[])
  41 public class XSObjectListImpl extends AbstractList<XSObject> implements XSObjectList {
  42 
  43     /**
  44      * An immutable empty list.
  45      */
  46     public static final XSObjectListImpl EMPTY_LIST = new XSObjectListImpl(new XSObject[0], 0);
  47     private static final ListIterator<XSObject> EMPTY_ITERATOR = new EmptyIterator();
  48     static class EmptyIterator implements ListIterator<XSObject> {
  49         public boolean hasNext() {
  50             return false;
  51         }
  52         public XSObject next() {
  53             throw new NoSuchElementException();
  54         }
  55         public boolean hasPrevious() {
  56             return false;
  57         }
  58         public XSObject previous() {
  59             throw new NoSuchElementException();
  60         }
  61         public int nextIndex() {
  62             return 0;
  63         }
  64         public int previousIndex() {
  65             return -1;
  66         }
  67         public void remove() {
  68             throw new UnsupportedOperationException();
  69         }
  70         public void set(XSObject object) {
  71             throw new UnsupportedOperationException();
  72         }
  73         public void add(XSObject object) {
  74             throw new UnsupportedOperationException();
  75         }
  76     }
  77     private static final int DEFAULT_SIZE = 4;
  78 
  79     // The array to hold all data
  80     private XSObject[] fArray = null;
  81     // Number of elements in this list
  82     private int fLength = 0;
  83 
  84     public XSObjectListImpl() {
  85         fArray = new XSObject[DEFAULT_SIZE];
  86         fLength = 0;
  87     }
  88 
  89     /**
  90      * Construct an XSObjectList implementation
  91      *
  92      * @param array     the data array
  93      * @param length    the number of elements
  94      */
  95     public XSObjectListImpl(XSObject[] array, int length) {
  96         fArray = array;
  97         fLength = length;
  98     }
  99 
 100     /**
 101      * The number of <code>XSObjects</code> in the list. The range of valid
 102      * child node indices is 0 to <code>length-1</code> inclusive.
 103      */
 104     public int getLength() {
 105         return fLength;
 106     }
 107 
 108     /**
 109      * Returns the <code>index</code>th item in the collection. The index
 110      * starts at 0. If <code>index</code> is greater than or equal to the
 111      * number of nodes in the list, this returns <code>null</code>.
 112      * @param index index into the collection.
 113      * @return The XSObject at the <code>index</code>th position in the
 114      *   <code>XSObjectList</code>, or <code>null</code> if that is not a
 115      *   valid index.
 116      */
 117     public XSObject item(int index) {
 118         if (index < 0 || index >= fLength) {
 119             return null;
 120         }
 121         return fArray[index];
 122     }
 123 
 124     // clear this object
 125     public void clearXSObjectList() {
 126         for (int i=0; i<fLength; i++) {
 127             fArray[i] = null;
 128         }
 129         fArray = null;
 130         fLength = 0;
 131     }
 132 
 133     public void addXSObject(XSObject object) {
 134        if (fLength == fArray.length) {
 135            XSObject[] temp = new XSObject[fLength + 4];
 136            System.arraycopy(fArray, 0, temp, 0, fLength);
 137            fArray = temp;
 138        }
 139        fArray[fLength++] = object;
 140     }
 141 
 142     public void addXSObject(int index, XSObject object) {
 143         fArray[index] = object;
 144     }
 145 
 146     /*
 147      * List methods
 148      */
 149 
 150     public boolean contains(Object value) {
 151         return (value == null) ? containsNull() : containsObject(value);
 152     }
 153 
 154     public XSObject get(int index) {
 155         if (index >= 0 && index < fLength) {
 156             return fArray[index];
 157         }
 158         throw new IndexOutOfBoundsException("Index: " + index);
 159     }
 160 
 161     public int size() {
 162         return getLength();
 163     }
 164 
 165     public Iterator<XSObject> iterator() {
 166         return listIterator0(0);
 167     }
 168 
 169     public ListIterator<XSObject> listIterator() {
 170         return listIterator0(0);
 171     }
 172 
 173     public ListIterator<XSObject> listIterator(int index) {
 174         if (index >= 0 && index < fLength) {
 175             return listIterator0(index);
 176         }
 177         throw new IndexOutOfBoundsException("Index: " + index);
 178     }
 179 
 180     private ListIterator<XSObject> listIterator0(int index) {
 181         return fLength == 0 ? EMPTY_ITERATOR : new XSObjectListIterator(index);
 182     }
 183 
 184     private boolean containsObject(Object value) {
 185         for (int i = fLength - 1; i >= 0; --i) {
 186             if (value.equals(fArray[i])) {
 187                 return true;
 188             }
 189         }
 190         return false;
 191     }
 192 
 193     private boolean containsNull() {
 194         for (int i = fLength - 1; i >= 0; --i) {
 195             if (fArray[i] == null) {
 196                 return true;
 197             }
 198         }
 199         return false;
 200     }
 201 
 202     public Object[] toArray() {
 203         Object[] a = new Object[fLength];
 204         toArray0(a);
 205         return a;
 206     }
 207 
 208     public Object[] toArray(Object[] a) {
 209         if (a.length < fLength) {
 210             Class<?> arrayClass = a.getClass();
 211             Class<?> componentType = arrayClass.getComponentType();
 212             a = (Object[]) Array.newInstance(componentType, fLength);
 213         }
 214         toArray0(a);
 215         if (a.length > fLength) {
 216             a[fLength] = null;
 217         }
 218         return a;
 219     }
 220 
 221     private void toArray0(Object[] a) {
 222         if (fLength > 0) {
 223             System.arraycopy(fArray, 0, a, 0, fLength);
 224         }
 225     }
 226 
 227     private final class XSObjectListIterator implements ListIterator<XSObject> {
 228         private int index;
 229         public XSObjectListIterator(int index) {
 230             this.index = index;
 231         }
 232         public boolean hasNext() {
 233             return (index < fLength);
 234         }
 235         public XSObject next() {
 236             if (index < fLength) {
 237                 return fArray[index++];
 238             }
 239             throw new NoSuchElementException();
 240         }
 241         public boolean hasPrevious() {
 242             return (index > 0);
 243         }
 244         public XSObject previous() {
 245             if (index > 0) {
 246                 return fArray[--index];
 247             }
 248             throw new NoSuchElementException();
 249         }
 250         public int nextIndex() {
 251             return index;
 252         }
 253         public int previousIndex() {
 254             return index - 1;
 255         }
 256         public void remove() {
 257             throw new UnsupportedOperationException();
 258         }
 259         public void set(XSObject o) {
 260             throw new UnsupportedOperationException();
 261         }
 262         public void add(XSObject o) {
 263             throw new UnsupportedOperationException();
 264         }
 265     }
 266 
 267 } // class XSObjectListImpl