All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.el.MapELResolver Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 1997-2018 Oracle and/or its affiliates. All rights reserved.
 * Copyright 2004 The Apache Software Foundation
 *
 * 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 javax.el;

import java.beans.FeatureDescriptor;
import java.util.Map;
import java.util.Iterator;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;

/**
 * Defines property resolution behavior on instances of {@link java.util.Map}.
 *
 * 

This resolver handles base objects of type java.util.Map. * It accepts any object as a property and uses that object as a key in * the map. The resulting value is the value in the map that is associated with * that key.

* *

This resolver can be constructed in read-only mode, which means that * {@link #isReadOnly} will always return true and * {@link #setValue} will always throw * PropertyNotWritableException.

* *

ELResolvers are combined together using * {@link CompositeELResolver}s, to define rich semantics for evaluating * an expression. See the javadocs for {@link ELResolver} for details.

* * @see CompositeELResolver * @see ELResolver * @see java.util.Map * @since JSP 2.1 */ public class MapELResolver extends ELResolver { /** * Creates a new read/write MapELResolver. */ public MapELResolver() { this.isReadOnly = false; } /** * Creates a new MapELResolver whose read-only status is * determined by the given parameter. * * @param isReadOnly true if this resolver cannot modify * maps; false otherwise. */ public MapELResolver(boolean isReadOnly) { this.isReadOnly = isReadOnly; } /** * If the base object is a map, returns the most general acceptable type * for a value in this map. * *

If the base is a Map, the propertyResolved * property of the ELContext object must be set to * true by this resolver, before returning. If this property * is not true after this method is called, the caller * should ignore the return value.

* *

Assuming the base is a Map, this method will always * return Object.class. This is because Maps * accept any object as the value for a given key.

* * @param context The context of this evaluation. * @param base The map to analyze. Only bases of type Map * are handled by this resolver. * @param property The key to return the acceptable type for. * Ignored by this resolver. * @return If the propertyResolved property of * ELContext was set to true, then * the most general acceptable type; otherwise undefined. * @throws NullPointerException if context is null * @throws ELException if an exception was thrown while performing * the property or variable resolution. The thrown exception * must be included as the cause property of this exception, if * available. */ public Class getType(ELContext context, Object base, Object property) { if (context == null) { throw new NullPointerException(); } if (base != null && base instanceof Map) { context.setPropertyResolved(true); return Object.class; } return null; } /** * If the base object is a map, returns the value associated with the * given key, as specified by the property argument. If the * key was not found, null is returned. * *

If the base is a Map, the propertyResolved * property of the ELContext object must be set to * true by this resolver, before returning. If this property * is not true after this method is called, the caller * should ignore the return value.

* *

Just as in {@link java.util.Map#get}, just because null * is returned doesn't mean there is no mapping for the key; it's also * possible that the Map explicitly maps the key to * null.

* * @param context The context of this evaluation. * @param base The map to be analyzed. Only bases of type Map * are handled by this resolver. * @param property The key whose associated value is to be returned. * @return If the propertyResolved property of * ELContext was set to true, then * the value associated with the given key or null * if the key was not found. Otherwise, undefined. * @throws ClassCastException if the key is of an inappropriate type * for this map (optionally thrown by the underlying Map). * @throws NullPointerException if context is null, or if * the key is null and this map does not permit null keys (the * latter is optionally thrown by the underlying Map). * @throws ELException if an exception was thrown while performing * the property or variable resolution. The thrown exception * must be included as the cause property of this exception, if * available. */ public Object getValue(ELContext context, Object base, Object property) { if (context == null) { throw new NullPointerException(); } if (base != null && base instanceof Map) { context.setPropertyResolved(base, property); Map map = (Map) base; return map.get(property); } return null; } static private Class theUnmodifiableMapClass = Collections.unmodifiableMap(new HashMap()).getClass(); /** * If the base object is a map, attempts to set the value associated with * the given key, as specified by the property argument. * *

If the base is a Map, the propertyResolved * property of the ELContext object must be set to * true by this resolver, before returning. If this property * is not true after this method is called, the caller * can safely assume no value was set.

* *

If this resolver was constructed in read-only mode, this method will * always throw PropertyNotWritableException.

* *

If a Map was created using * {@link java.util.Collections#unmodifiableMap}, this method must * throw PropertyNotWritableException. Unfortunately, * there is no Collections API method to detect this. However, an * implementation can create a prototype unmodifiable Map * and query its runtime type to see if it matches the runtime type of * the base object as a workaround.

* * @param context The context of this evaluation. * @param base The map to be modified. Only bases of type Map * are handled by this resolver. * @param property The key with which the specified value is to be * associated. * @param val The value to be associated with the specified key. * @throws ClassCastException if the class of the specified key or * value prevents it from being stored in this map. * @throws NullPointerException if context is null, or if * this map does not permit null keys or values, and * the specified key or value is null. * @throws IllegalArgumentException if some aspect of this key or * value prevents it from being stored in this map. * @throws ELException if an exception was thrown while performing * the property or variable resolution. The thrown exception * must be included as the cause property of this exception, if * available. * @throws PropertyNotWritableException if this resolver was constructed * in read-only mode, or if the put operation is not supported by * the underlying map. */ public void setValue(ELContext context, Object base, Object property, Object val) { if (context == null) { throw new NullPointerException(); } if (base != null && base instanceof Map) { context.setPropertyResolved(base, property); // The cast is safe @SuppressWarnings("unchecked") Map map = (Map)base; if (isReadOnly || map.getClass() == theUnmodifiableMapClass) { throw new PropertyNotWritableException(); } try { map.put(property, val); } catch (UnsupportedOperationException ex) { throw new PropertyNotWritableException(); } } } /** * If the base object is a map, returns whether a call to * {@link #setValue} will always fail. * *

If the base is a Map, the propertyResolved * property of the ELContext object must be set to * true by this resolver, before returning. If this property * is not true after this method is called, the caller * should ignore the return value.

* *

If this resolver was constructed in read-only mode, this method will * always return true.

* *

If a Map was created using * {@link java.util.Collections#unmodifiableMap}, this method must * return true. Unfortunately, there is no Collections API * method to detect this. However, an implementation can create a * prototype unmodifiable Map and query its runtime type * to see if it matches the runtime type of the base object as a * workaround.

* * @param context The context of this evaluation. * @param base The map to analyze. Only bases of type Map * are handled by this resolver. * @param property The key to return the read-only status for. * Ignored by this resolver. * @return If the propertyResolved property of * ELContext was set to true, then * true if calling the setValue method * will always fail or false if it is possible that * such a call may succeed; otherwise undefined. * @throws NullPointerException if context is null * @throws ELException if an exception was thrown while performing * the property or variable resolution. The thrown exception * must be included as the cause property of this exception, if * available. */ public boolean isReadOnly(ELContext context, Object base, Object property) { if (context == null) { throw new NullPointerException(); } if (base != null && base instanceof Map) { context.setPropertyResolved(true); Map map = (Map) base; return isReadOnly || map.getClass() == theUnmodifiableMapClass; } return false; } /** * If the base object is a map, returns an Iterator * containing the set of keys available in the Map. * Otherwise, returns null. * *

The Iterator returned must contain zero or more * instances of {@link java.beans.FeatureDescriptor}. Each info object * contains information about a key in the Map, and is initialized as * follows: *

*
  • displayName - The return value of calling the * toString method on this key, or * "null" if the key is null.
  • *
  • name - Same as displayName property.
  • *
  • shortDescription - Empty string
  • *
  • expert - false
  • *
  • hidden - false
  • *
  • preferred - true
  • *
    * In addition, the following named attributes must be set in the * returned FeatureDescriptors: *
    *
  • {@link ELResolver#TYPE} - The return value of calling the getClass() * method on this key, or null if the key is * null.
  • *
  • {@link ELResolver#RESOLVABLE_AT_DESIGN_TIME} - true
  • *
    *

    * * @param context The context of this evaluation. * @param base The map whose keys are to be iterated over. Only bases * of type Map are handled by this resolver. * @return An Iterator containing zero or more (possibly * infinitely more) FeatureDescriptor objects, each * representing a key in this map, or null if * the base object is not a map. */ public Iterator getFeatureDescriptors( ELContext context, Object base) { if (base != null && base instanceof Map) { Map map = (Map) base; Iterator iter = map.keySet().iterator(); List list = new ArrayList(); while (iter.hasNext()) { Object key = iter.next(); FeatureDescriptor descriptor = new FeatureDescriptor(); String name = (key==null)? null: key.toString(); descriptor.setName(name); descriptor.setDisplayName(name); descriptor.setShortDescription(""); descriptor.setExpert(false); descriptor.setHidden(false); descriptor.setPreferred(true); if (key != null) { descriptor.setValue("type", key.getClass()); } descriptor.setValue("resolvableAtDesignTime", Boolean.TRUE); list.add(descriptor); } return list.iterator(); } return null; } /** * If the base object is a map, returns the most general type that * this resolver accepts for the property argument. * Otherwise, returns null. * *

    Assuming the base is a Map, this method will always * return Object.class. This is because Maps * accept any object as a key.

    * * @param context The context of this evaluation. * @param base The map to analyze. Only bases of type Map * are handled by this resolver. * @return null if base is not a Map; otherwise * Object.class. */ public Class getCommonPropertyType(ELContext context, Object base) { if (base != null && base instanceof Map) { return Object.class; } return null; } private boolean isReadOnly; }




    © 2015 - 2024 Weber Informatics LLC | Privacy Policy