/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.zkoss.zel; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * @since EL 3.0 */ public class StandardELContext extends ELContext { private final ELContext wrappedContext; private final VariableMapper variableMapper; private final FunctionMapper functionMapper; private final CompositeELResolver standardResolver; private final CompositeELResolver customResolvers; private final Map<String,Object> localBeans = new HashMap<String,Object>(); public StandardELContext(ExpressionFactory factory) { wrappedContext = null; variableMapper = new StandardVariableMapper(); functionMapper = new StandardFunctionMapper(factory.getInitFunctionMap()); standardResolver = new CompositeELResolver(); customResolvers = new CompositeELResolver(); ELResolver streamResolver = factory.getStreamELResolver(); // Add resolvers in order standardResolver.add(new BeanNameELResolver( new StandardBeanNameResolver(localBeans))); standardResolver.add(customResolvers); if (streamResolver != null) { standardResolver.add(streamResolver); } standardResolver.add(new StaticFieldELResolver()); standardResolver.add(new MapELResolver()); standardResolver.add(new ResourceBundleELResolver()); standardResolver.add(new ListELResolver()); standardResolver.add(new ArrayELResolver()); standardResolver.add(new BeanELResolver()); } public StandardELContext(ELContext context) { wrappedContext = context; variableMapper = context.getVariableMapper(); functionMapper = context.getFunctionMapper(); standardResolver = new CompositeELResolver(); customResolvers = new CompositeELResolver(); // Add resolvers in order standardResolver.add(new BeanNameELResolver( new StandardBeanNameResolver(localBeans))); standardResolver.add(customResolvers); // Use resolvers from context from this point on standardResolver.add(context.getELResolver()); } // Can't use Class<?> because API needs to match specification public void putContext(@SuppressWarnings("rawtypes") Class key, Object contextObject) { if (wrappedContext == null) { super.putContext(key, contextObject); } else { wrappedContext.putContext(key, contextObject); } } public Object getContext(@SuppressWarnings("rawtypes") Class key) { if (wrappedContext == null) { return super.getContext(key); } else { return wrappedContext.getContext(key); } } public ELResolver getELResolver() { return standardResolver; } public void addELResolver(ELResolver resolver) { customResolvers.add(resolver); } public FunctionMapper getFunctionMapper() { return functionMapper; } public VariableMapper getVariableMapper() { return variableMapper; } Map<String,Object> getLocalBeans() { return localBeans; } private static class StandardVariableMapper extends VariableMapper { private Map<String, ValueExpression> vars; public ValueExpression resolveVariable(String variable) { if (vars == null) { return null; } return vars.get(variable); } public ValueExpression setVariable(String variable, ValueExpression expression) { if (vars == null) vars = new HashMap<String, ValueExpression>(); if (expression == null) { return vars.remove(variable); } else { return vars.put(variable, expression); } } } private static class StandardBeanNameResolver extends BeanNameResolver { private final Map<String,Object> beans; public StandardBeanNameResolver(Map<String,Object> beans) { this.beans = beans; } public boolean isNameResolved(String beanName) { return beans.containsKey(beanName); } public Object getBean(String beanName) { return beans.get(beanName); } public void setBeanValue(String beanName, Object value) throws PropertyNotWritableException { beans.put(beanName, value); } public boolean isReadOnly(String beanName) { return false; } public boolean canCreateBean(String beanName) { return true; } } private static class StandardFunctionMapper extends FunctionMapper { private final Map<String,Method> methods = new HashMap<String,Method>(); public StandardFunctionMapper(Map<String,Method> initFunctionMap) { if (initFunctionMap != null) { methods.putAll(initFunctionMap); } } public Method resolveFunction(String prefix, String localName) { String key = prefix + ':' + localName; return methods.get(key); } public void mapFunction(String prefix, String localName, Method method) { String key = prefix + ':' + localName; if (method == null) { methods.remove(key); } else { methods.put(key, method); } } } }