/* * Copyright (c) 2001-2010, 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.Type; import java.util.Map; import org.primeframework.mvc.parameter.convert.ConversionException; import org.primeframework.mvc.parameter.convert.ConverterProvider; import org.primeframework.mvc.parameter.convert.GlobalConverter; import org.primeframework.mvc.util.TypeTools; /** * This class models a Map accessor during expression evaluation. * * @author Brian Pontarelli */ public class MapAccessor extends Accessor { final Object key; final MemberAccessor memberAccessor; public MapAccessor(ConverterProvider converterProvider, Accessor accessor, String index, MemberAccessor memberAccessor) { super(converterProvider, accessor); String path = memberAccessor.toString(); Type objectType = super.type; this.memberAccessor = memberAccessor; Type[] types = TypeTools.mapTypes(objectType, path); super.type = types[1]; // Value type Class<?> keyType = TypeTools.rawType(types[0]); // Key type GlobalConverter converter = converterProvider.lookup(keyType); if (converter == null) { throw new ConversionException("No type converter is registered for the type [" + keyType + "], which is the " + "type for the key of the map at [" + path + "]"); } this.key = converter.convertFromStrings(keyType, null, path, index); } /** * @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 ((Map) this.object).get(key); } public void set(String[] values, Expression expression) { set(convert(expression, memberAccessor.field, values), expression); } @SuppressWarnings("unchecked") public void set(Object value, Expression expression) { ((Map) this.object).put(key, 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); } }