alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 *
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 *
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
package org.netbeans.modules.javacore.jmiimpl.javamodel;

import java.util.*;
import org.openide.ErrorManager;
import javax.jmi.model.MofClass;
import javax.jmi.model.NameNotFoundException;
import javax.jmi.reflect.*;
import org.netbeans.api.mdr.MDRObject;
import org.netbeans.api.mdr.MDRepository;
import org.netbeans.api.mdr.events.MDRChangeListener;
import org.netbeans.jmi.javamodel.*;
import org.netbeans.mdr.handlers.InstanceHandler;
import org.netbeans.mdr.handlers.BaseObjectHandler;
import org.netbeans.mdr.storagemodel.StorableObject;
import org.netbeans.modules.javacore.JMManager;

/**
 *
 * @author  Dusan Balek, Martin Matula
 */
public abstract class ParameterizedTypeImpl extends InstanceHandler implements ParameterizedType {

    JavaClass definition = null;
    List parameters = null;
    ParameterizedType outerCls = null;
    Map substMap = null;
    int wildcards[];

    private WrapperList featureList = null;
    private WrapperList contentsList = null;

    public ParameterizedTypeImpl(StorableObject s) {
        super(s);
    }

    // ParameterizedType implementation .........................................

    public JavaClass getDefinition() {
        return definition;
    }

    public List getParameters() {
        return parameters;
    }
    
    public int getWildCardStatus(int paramIndex) {
        return wildcards != null ? wildcards[paramIndex] : 0;
    }
    
    public void setWildCardStatus(int paramIndex, int status) {
        if (wildcards == null) {
            wildcards = new int[parameters.size()];
        }
        wildcards[paramIndex] = status;
    }
    
    public boolean isValid() {
        return true;
    }

    public void setDefinition(JavaClass newValue) {
        throw constructIsReadOnly(this, "definition"); // NOI18N
    }

    // JavaClass implementation .................................................

    public String getSimpleName() {
        return constructName(definition, parameters, outerCls, false);
    }

    public boolean isInterface() {
        return definition.isInterface();
    }
    
    public boolean isInner() {
        return definition.isInner();
    }
    
    public void setInterface(boolean newValue) {
        throw constructIsReadOnly(this, "interface"); // NOI18N
    }

    public void setSimpleName(String newValue) {
        throw constructIsReadOnly(this, "simpleName"); // NOI18N
    }

    public java.util.Collection findSubTypes(boolean recursively) {
        return definition.findSubTypes(recursively);
    }

    public java.util.Collection getImplementors() {
        return definition.getImplementors();
    }
    
    public java.util.Collection getSubClasses() {
        return definition.getSubClasses();
    }
    
    // Feature implementation ...............................................

    public boolean isDeprecated() {
        return definition.isDeprecated();
    }

    public void setDeprecated(boolean newValue) {
        definition.setDeprecated(newValue);
    }
    
    // ClassMember implementation ...............................................

    public ClassDefinition getDeclaringClass() {
        return outerCls != null ? outerCls : definition.getDeclaringClass();
    }

    public JavaDoc getJavadoc() {
        return definition.getJavadoc();
    }

    public String getJavadocText() {
        return definition.getJavadocText();
    }

    public int getModifiers() {
        return definition.getModifiers();
    }

    public void setJavadoc(JavaDoc newValue) {
        throw constructIsReadOnly(this, "javaDoc"); // NOI18N
    }

    public void setJavadocText(String newValue) {
        throw constructIsReadOnly(this, "javaDocText"); // NOI18N
    }

    public void setModifiers(int newValue) {
        throw constructIsReadOnly(this, "modifiers"); // NOI18N
    }

    // AnnotableElement implementation ..........................................

    public List getAnnotations() {
        return definition.getAnnotations();
    }

    // NamedElement implementation ..............................................

    public String getName() {
        return constructName(definition, parameters, outerCls, true);
    }

    public void setName(String newValue) {
        throw constructIsReadOnly(this, "name"); // NOI18N
    }

    // ClassDefinition implementation ...........................................

    public Constructor getConstructor(List parameters, boolean includeSupertypes) {
        initSubstitutionMap();
        return (Constructor)wrap(definition.getConstructor(parameters, includeSupertypes));
    }

    public List getContents() {
        initSubstitutionMap();
        if (contentsList == null)
            contentsList = new WrapperList(definition.getContents(), "contents"); // NOI18N
        return contentsList;
    }

    public List getFeatures() {
        initSubstitutionMap();
        if (featureList == null)
            featureList = new WrapperList(definition.getFeatures(), "features"); // NOI18N
        return featureList;
    }

    public Field getField(String name, boolean includeSupertypes) {
        initSubstitutionMap();
        return (Field)wrap(definition.getField(name, includeSupertypes));
    }

    public JavaClass getInnerClass(String simpleName, boolean includeSupertypes) {
        initSubstitutionMap();
        return (JavaClass)wrap(definition.getInnerClass(simpleName, includeSupertypes));
    }

    public List getInterfaceNames() {
        return definition.getInterfaceNames();
    }

    public List getInterfaces() {
        initSubstitutionMap();
        return new SubstitutionList(definition.getInterfaces());
    }

    public Method getMethod(String name, List parameters, boolean includeSupertypes) {
        initSubstitutionMap();
        return (Method)wrap(definition.getMethod(name, parameters, includeSupertypes));
    }

    public JavaClass getSuperClass() {
        return (JavaClass) rebuildObject(definition.getSuperClass());
    }

    public MultipartId getSuperClassName() {
        return definition.getSuperClassName();
    }

    public void setSuperClass(JavaClass newValue) {
        throw constructIsReadOnly(this, "superClass"); // NOI18N
    }

    public void setSuperClassName(MultipartId newValue) {
        throw constructIsReadOnly(this, "superClassName"); // NOI18N
    }
    
    public boolean isSubTypeOf(ClassDefinition cls) {
        return definition.isSubTypeOf(cls);
    }

    // GenericElement implementation ............................................

    public List getTypeParameters() {
        return definition.getTypeParameters();
    }

    // Element implementation ............................................
    
    public Resource getResource() {
        return definition.getResource();
    }

    // helper methods ...........................................................
    
    static ConstraintViolationException constructIsReadOnly(RefObject obj, String attrName) {
        RefObject attr = null;
        try {
            attr = ((MofClass) obj.refMetaObject()).lookupElementExtended(attrName);
        } catch (NameNotFoundException e) {
            // ignore
        }
        attrName = attrName.substring(0, 1).toUpperCase() + attrName.substring(1);
        return new ConstraintViolationException(obj, attr, attrName + " is readonly."); // NOI18N
    }

    static String constructName(JavaClass definition, List parameters, ParameterizedType outerCls, boolean useFQN) {
        StringBuffer sb = new StringBuffer();
        if (useFQN) {
            if (outerCls != null) {
                sb.append(outerCls.getName());
                sb.append('.'); // NOI18N
                sb.append(definition.getSimpleName());
            } else {
                sb.append(definition.getName());
            }
        } else {
            sb.append(definition.getSimpleName());
        }
        if (parameters != null && parameters.size() > 0) {
            sb.append('<'); // NOI18N
            for (Iterator it = parameters.iterator(); it.hasNext();) {
                Type param = (Type) it.next();
                sb.append(!useFQN && param instanceof JavaClass ? ((JavaClass)param).getSimpleName() : param.getName());
                if (it.hasNext())
                    sb.append(',');
            }
            sb.append('>'); // NOI18N
        }
        return sb.toString();
    }
    
    void initSubstitutionMap() {
        if (substMap != null) return;
        substMap = new HashMap();
        ClassDefinition cd = this;
        while (cd instanceof ParameterizedType) {
            List parameters = ((ParameterizedType)cd).getParameters();
            Iterator itt = parameters.iterator();
            if (itt.hasNext()) {
                for (Iterator it = ((ParameterizedType)cd).getDefinition().getTypeParameters().iterator(); it.hasNext() && itt.hasNext();) {
                    substMap.put(it.next(), itt.next());
                }
            }
            cd = ((ParameterizedType)cd).getDeclaringClass();
        }
    }

    private void lock() {
        ((BaseObjectHandler) definition).repository().beginTrans(false);
    }

    private void unlock() {
        ((BaseObjectHandler) definition).repository().endTrans(false);
    }

    private class WrapperList implements List {

        private List list;
        private String attrName;

        public WrapperList(List list, String attrName) {
            this.list = list;
            this.attrName = attrName;
        }

        public int size() {
            return list.size();
        }

        public boolean isEmpty() {
            return list.isEmpty();
        }

        public boolean contains(Object o) {
            Object obj = o;
            if (obj instanceof Wrapper) {
                obj = ((Wrapper)obj).getWrappedObject();
            }
            return list.contains(obj);
        }

        public Iterator iterator() {
            return listIterator();
        }

        public Object[] toArray() {
            lock();
            try {
                Object[] result = new Object[size()];
                Iterator it = iterator();
                for (int i = 0; it.hasNext(); i++) {
                    result[i] = it.next();
                }
                return result;
            } finally {
                unlock();
            }
        }

        public Object[] toArray(Object a[]) {
            lock();
            try {
                int size = size();
                if (a.length < size) {
                    a = (Object[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
                }
                Iterator it = iterator();
                for (int i = 0; i size)
                    a[size] = null;
                return a;
            } finally {
                unlock();
            }
        }

        public boolean add(Object o) {
            throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
        }

        public boolean remove(Object o) {
            throw constructIsReadOnly(null, attrName);
        }

        public boolean containsAll(Collection c) {
            lock();
            try {
                for (Iterator it = c.iterator(); it.hasNext();) {
                    if (!contains(it.next())) {
                        return false;
                    }
                }
                return true;
            } finally {
                unlock();
            }
        }

        public boolean addAll(Collection c) {
            throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
        }

        public boolean addAll(int index, Collection c) {
            throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
        }

        public boolean removeAll(Collection c) {
            throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
        }

        public boolean retainAll(Collection c) {
            throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
        }

        public void clear() {
            throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
        }

        public Object get(int index) {
            lock();
            try {
                return listIterator(index).next();
            } finally {
                unlock();
            }
        }

        public Object set(int index, Object element) {
            throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
        }

        public void add(int index, Object element) {
            throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
        }

        public Object remove(int index) {
            throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
        }

        public int indexOf(Object o) {
            lock();
            try {
                for (ListIterator it = listIterator(); it.hasNext();) {
                    if (it.next().equals(o)) {
                        return it.previousIndex();
                    }
                }
                return -1;
            } finally {
                unlock();
            }
        }

        public int lastIndexOf(Object o) {
            lock();
            try {
                int result = -1;
                for (ListIterator it = listIterator(); it.hasNext();) {
                    if (it.next().equals(o)) {
                        result = it.previousIndex();
                    }
                }
                return result;
            } finally {
                unlock();
            }
        }

        public ListIterator listIterator() {
            return new WrapperListIterator(list.listIterator());
        }

        public ListIterator listIterator(int index) {
            lock();
            try {
                ListIterator result = listIterator();
                while (result.nextIndex() < index) {
                    result.next();
                }
                return result;
            } finally {
                unlock();
            }
        }

        public List subList(int fromIndex, int toIndex) {
            throw new UnsupportedOperationException();
        }

        private class WrapperListIterator implements ListIterator {

            private ListIterator delegate;

            public WrapperListIterator(ListIterator delegate) {
                this.delegate = delegate;
            }

            public boolean hasNext() {
                return delegate.hasNext();
            }

            public Object next() {
                return wrap(delegate.next());
            }

            public boolean hasPrevious() {
                return delegate.hasPrevious();
            }

            public Object previous() {
                return wrap(delegate.previous());
            }

            public int nextIndex() {
                return delegate.nextIndex();
            }

            public int previousIndex() {
                return delegate.previousIndex();
            }

            public void remove() {
                throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
            }

            public void set(Object o) {
                throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
            }

            public void add(Object o) {
                throw constructIsReadOnly(ParameterizedTypeImpl.this, attrName);
            }
        }
    }

    public abstract class Wrapper implements MDRObject {

        private Object obj;

        public Wrapper(Object obj) {
            this.obj = obj;
        }

        public Object getWrappedObject() {
            return obj;
        }
        
        public MDRepository repository() {
            return ((MDRObject) obj).repository();
        }

        public void addListener(MDRChangeListener listener) {
            ((MDRObject) obj).addListener(listener);
        }
        
        public void addListener(MDRChangeListener listener, int mask) {
            ((MDRObject) obj).addListener(listener, mask);
        }
        
        public void removeListener(MDRChangeListener listener) {
            ((MDRObject) obj).removeListener(listener);
        }
        
        public void removeListener(MDRChangeListener listener, int mask) {
            ((MDRObject) obj).removeListener(listener, mask);
        }
    }

    private Object wrap(Object obj) {
        if (obj instanceof Field)
            return new FieldWrapper(obj);
        if (obj instanceof Method)
            return new MethodWrapper(obj);
        if (obj instanceof Constructor)
            return new ConstructorWrapper(obj);
        if (obj instanceof Parameter)
            return new ParameterWrapper(obj);
        if (obj instanceof TypeParameter)
            return substitute((Type)obj);
        if (obj instanceof JavaClass) {
            ParameterizedTypeClass ptc = ((JavaModelPackage)((JavaClass)obj).refImmediatePackage()).getParameterizedType();
            return ptc.resolveParameterizedType((JavaClass)obj, null, this);
        }
        return obj;
    }

    private Type substitute(Type typ) {
        initSubstitutionMap();
        if (typ instanceof TypeParameter) {
            Type subst = (Type) substMap.get(typ);
            if (subst == null) {
                subst = JMManager.getManager().getDefaultExtent().getType().resolve("java.lang.Object"); // NOI18N
                substMap.put(typ, subst);
            }
            typ = subst;
        } else if (typ instanceof Array) {
            Type subst = substitute(((Array)typ).getType());
            return subst != null ? ((ArrayClass)typ.refClass()).resolveArray(subst) : typ;
        }
        return (Type) rebuildObject(typ);
    }
    
    private Object rebuildObject(Object obj) {
        initSubstitutionMap();
        if (obj instanceof ParameterizedTypeImpl) {
            ParameterizedTypeImpl pt = (ParameterizedTypeImpl) obj;
            List parameters = pt.getParameters();
            List newParameters = new ArrayList(parameters.size());
            boolean createNew = false;
            for (Iterator it = parameters.iterator(); it.hasNext();) {
                Type oldType = (Type) it.next();
                Type newType = substitute(oldType);
                newParameters.add(newType);
                if (!oldType.equals(newType)) {
                    createNew = true;
                }
            }
            if (createNew) {
                obj = ((ParameterizedTypeClass) pt.refClass()).resolveParameterizedType(pt.definition, newParameters, pt.outerCls);
            }
        }
        return obj;
    }

    private class TypedElementWrapper extends Wrapper implements TypedElement {

        public TypedElementWrapper(Object typedElement) {
            super(typedElement);
        }
        
        private TypedElement typedElement() {
            return (TypedElement) getWrappedObject();
        }

        public Type getType() {
            return substitute(typedElement().getType());
        }

        public void setType(Type newValue) {
            throw constructIsReadOnly(this, "type"); // NOI18N
        }
        
        public Element duplicate() {
            return typedElement().duplicate();
        }

        public List getChildren() {
            return typedElement().getChildren();
        }

        public int getEndOffset() {
            return typedElement().getEndOffset();
        }

        public int getPartEndOffset(ElementPartKind part) {
            return typedElement().getPartEndOffset(part);
        }

        public int getPartStartOffset(ElementPartKind part) {
            return typedElement().getPartStartOffset(part);
        }

        public Resource getResource() {
            return typedElement().getResource();
        }

        public int getStartOffset() {
            return typedElement().getStartOffset();
        }

        public boolean isValid() {
            return typedElement().isValid();
        }

        public void replaceChild(Element oldChild, Element newChild) {
            typedElement().replaceChild(oldChild, newChild);
        }

        public RefClass refClass() {
            return typedElement().refClass();
        }

        public void refDelete() {
            typedElement().refDelete();
        }

        public RefFeatured refImmediateComposite() {
            return typedElement().refImmediateComposite();
        }

        public boolean refIsInstanceOf(RefObject refObject, boolean b) {
            return typedElement().refIsInstanceOf(refObject, b);
        }

        public RefFeatured refOutermostComposite() {
            return typedElement().refOutermostComposite();
        }

        public Object refGetValue(RefObject refObject) {
            return typedElement().refGetValue(refObject);
        }

        public Object refGetValue(String s) {
            return typedElement().refGetValue(s);
        }

        public Object refInvokeOperation(RefObject refObject, List list) throws RefException {
            return typedElement().refInvokeOperation(refObject, list);
        }

        public Object refInvokeOperation(String s, List list) throws RefException {
            return typedElement().refInvokeOperation(s, list);
        }

        public void refSetValue(RefObject refObject, Object o) {
            typedElement().refSetValue(refObject, o);
        }

        public void refSetValue(String s, Object o) {
            typedElement().refSetValue(s, o);
        }

        public RefPackage refImmediatePackage() {
            return typedElement().refImmediatePackage();
        }

        public RefObject refMetaObject() {
            return typedElement().refMetaObject();
        }

        public String refMofId() {
            return typedElement().refMofId();
        }

        public RefPackage refOutermostPackage() {
            return typedElement().refOutermostPackage();
        }

        public Collection refVerifyConstraints(boolean b) {
            return typedElement().refVerifyConstraints(b);
        }
    }

    private class FeatureWrapper extends TypedElementWrapper implements Feature {

        public FeatureWrapper(Object feature) {
            super(feature);
        }
        
        private Feature feature() {
            return (Feature) getWrappedObject();
        }

        public ClassDefinition getDeclaringClass() {
            return feature().getDeclaringClass();
        }

        public int getModifiers() {
            return feature().getModifiers();
        }

        public void setModifiers(int newValue) {
            feature().setModifiers(newValue);
        }
        
        public boolean isDeprecated() {
            return feature().isDeprecated();
        }

        public String getJavadocText() {
            return feature().getJavadocText();
        }

        public void setJavadocText(String newValue) {
            feature().setJavadocText(newValue);
        }

        public JavaDoc getJavadoc() {
            return feature().getJavadoc();
        }

        public void setJavadoc(JavaDoc newValue) {
            feature().setJavadoc(newValue);
        }

        public List getAnnotations() {
            return feature().getAnnotations();
        }

        public String getName() {
            return feature().getName();
        }

        public void setName(String newValue) {
            feature().setName(newValue);
        }

        public Collection getReferences() {
            return feature().getReferences();
        }
        
        public void setDeprecated(boolean deprecated) {
            feature().setDeprecated(deprecated);
        }
    }

    private class FieldWrapper extends FeatureWrapper implements Field {

        public FieldWrapper(Object field) {
            super(field);
        }
        
        private Field field() {
            return (Field) getWrappedObject();
        }

        public InitialValue getInitialValue() {
            return field().getInitialValue();
        }

        public void setInitialValue(InitialValue newValue) {
            field().setInitialValue(newValue);
        }

        public String getInitialValueText() {
            return field().getInitialValueText();
        }

        public void setInitialValueText(String newValue) {
            field().setInitialValueText(newValue);
        }

        public boolean isFinal() {
            return field().isFinal();
        }

        public void setFinal(boolean newValue) {
            field().setFinal(newValue);
        }

        public TypeReference getTypeName() {
            return field().getTypeName();
        }

        public void setTypeName(TypeReference newValue) {
            field().setTypeName(newValue);
        }

        public int getDimCount() {
            return field().getDimCount();
        }

        public void setDimCount(int newValue) {
            field().setDimCount(newValue);
        }

        public String toString() {
            return "field " + getName(); // NOI18N
        }
    }

    private class CallableFeatureWrapper extends FeatureWrapper implements CallableFeature {

        private WrapperList paramList = null;
        private WrapperList exceptionList = null;

        public CallableFeatureWrapper(Object callableFeature) {
            super(callableFeature);
        }
        
        private CallableFeature callableFeature() {
            return (CallableFeature) getWrappedObject();
        }

        public List getParameters() {
            if (paramList == null)
                paramList = new WrapperList(callableFeature().getParameters(), "parameters"); // NOI18N
            return paramList;
        }

        public List getExceptionNames() {
            return callableFeature().getExceptionNames();
        }

        public List getExceptions() {
            if (exceptionList == null)
                exceptionList = new WrapperList(callableFeature().getExceptions(), "exceptions"); // NOI18N
            return exceptionList;
        }

        public StatementBlock getBody() {
            return callableFeature().getBody();
        }

        public void setBody(StatementBlock newValue) {
            callableFeature().setBody(newValue);
        }

        public String getBodyText() {
            return callableFeature().getBodyText();
        }

        public void setBodyText(String newValue) {
            callableFeature().setBodyText(newValue);
        }

        public List getTypeParameters() {
            return callableFeature().getTypeParameters();
        }
    }

    private class MethodWrapper extends CallableFeatureWrapper implements Method {

        public MethodWrapper(Object method) {
            super(method);
        }
        
        private Method method() {
            return (Method) getWrappedObject();
        }

        public TypeReference getTypeName() {
            return method().getTypeName();
        }

        public void setTypeName(TypeReference newValue) {
            method().setTypeName(newValue);
        }

        public int getDimCount() {
            return method().getDimCount();
        }

        public void setDimCount(int newValue) {
            method().setDimCount(newValue);
        }
        
        public Collection findDependencies(boolean usages, boolean overridenMethods, boolean fromBaseClass) {
            return method().findDependencies(usages, overridenMethods, fromBaseClass);
        }
        
        public boolean signatureEquals(Method method) {
            return method().signatureEquals(method);
        }
        
        public String toString() {
            return "method " + getName(); // NOI18N
        }
    }

    private class ConstructorWrapper extends CallableFeatureWrapper implements Constructor {

        public ConstructorWrapper(Object constructor) {
            super(constructor);
        }
    }

    private class ParameterWrapper extends TypedElementWrapper implements Parameter {

        public ParameterWrapper(Object parameter) {
            super(parameter);
        }
        
        private Parameter parameter() {
            return (Parameter) getWrappedObject();
        }

        public boolean isVarArg() {
            return parameter().isVarArg();
        }

        public void setVarArg(boolean newValue) {
            parameter().setVarArg(newValue);
        }

        public boolean isFinal() {
            return parameter().isFinal();
        }

        public void setFinal(boolean newValue) {
            parameter().setFinal(newValue);
        }

        public TypeReference getTypeName() {
            return parameter().getTypeName();
        }

        public void setTypeName(TypeReference newValue) {
            parameter().setTypeName(newValue);
        }

        public int getDimCount() {
            return parameter().getDimCount();
        }

        public void setDimCount(int newValue) {
            parameter().setDimCount(newValue);
        }

        public List getAnnotations() {
            return parameter().getAnnotations();
        }

        public String getName() {
            return parameter().getName();
        }

        public void setName(String newValue) {
            parameter().setName(newValue);
        }

        public Collection getReferences() {
            return parameter().getReferences();
        }
    }
    
    private class SubstitutionList extends AbstractList {
        private final List inner;
        
        SubstitutionList(List inner) {
            this.inner = inner;
        }
        
        public void add(int index, Object object) {
            inner.add(index, object);
        }
        
        public Object remove(int index) {
            return rebuildObject(inner.remove(index));
        }
        
        public Object set(int index, Object object) {
            return rebuildObject(inner.set(index, object));
        }
        
        public Object get(int index) {
            return rebuildObject(inner.get(index));
        }
        
        public int size() {
            return inner.size();
        }
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.