/* * Copyright (c) 2001-2007, Inversoft Inc., All Rights Reserved * * 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 org.primeframework.mvc.parameter.el; import java.lang.annotation.Annotation; import java.lang.reflect.Array; import java.util.List; import org.primeframework.mvc.parameter.convert.ConverterProvider; import org.primeframework.mvc.util.TypeTools; /** * This class models a collection accessor during expression evaluation. * * @author Brian Pontarelli */ public class IndexedCollectionAccessor extends Accessor { Integer index; MemberAccessor memberAccessor; public IndexedCollectionAccessor(ConverterProvider converterProvider, Accessor accessor, Integer index, MemberAccessor memberAccessor) { super(converterProvider, accessor); this.index = index; super.type = TypeTools.componentType(super.type, memberAccessor.toString()); this.memberAccessor = memberAccessor; } /** * @return The memberAccessor member variable. */ public MemberAccessor getMemberAccessor() { return memberAccessor; } /** * @return Always false. The reason is that since this retrieves from a Collection, we want it to look like a * non-indexed property so that the context will invoke the method. */ public boolean isIndexed() { return false; } public Object get(Expression expression) { return getValueFromCollection(index); } public void set(String[] values, Expression expression) { set(convert(expression, memberAccessor.field, values), expression); } public void set(Object value, Expression expression) { object = pad(object, expression); setValueIntoCollection(index, value); } /** * Returns the annotation of the member this collection belongs to. * * @param type The annotation type. * @return The annotation or null. */ @Override protected <T extends Annotation> T getAnnotation(Class<T> type) { return memberAccessor.getAnnotation(type); } /** * Adds padding to the array or list so that it can hold the item being inserted. * * @param object The object to pad. If this isn't a List or an array, this method does nothing and just returns the * Object. * @param expression The current expression. * @return The padded list or array. */ @SuppressWarnings("unchecked") private Object pad(Object object, Expression expression) { if (object instanceof List) { List list = ((List) object); int length = list.size(); if (length <= index) { for (int i = length; i <= index; i++) { list.add(null); } } } else if (object.getClass().isArray()) { int length = Array.getLength(object); if (length <= index) { Object newArray = Array.newInstance(object.getClass().getComponentType(), index + 1); System.arraycopy(object, 0, newArray, 0, length); object = newArray; // Set the new array into the member memberAccessor.update(newArray, expression); } } return object; } }