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

camundafeel.de.odysseus.el.tree.Bindings Maven / Gradle / Ivy

There is a newer version: 7.22.0-alpha5
Show newest version
/*
 * Copyright 2006-2009 Odysseus Software GmbH
 *
 * 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 de.odysseus.el.tree;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Arrays;

import javax.el.ELException;
import javax.el.ValueExpression;

import de.odysseus.el.misc.TypeConverter;

/**
 * Bindings, usually created by a {@link de.odysseus.el.tree.Tree}.
 *
 * @author Christoph Beck
 */
public class Bindings implements TypeConverter {
	private static final long serialVersionUID = 1L;

	private static final Method[] NO_FUNCTIONS = new Method[0];
	private static final ValueExpression[] NO_VARIABLES = new ValueExpression[0];

	/**
	 * Wrap a {@link Method} for serialization.
	 */
	private static class MethodWrapper implements Serializable {
		private static final long serialVersionUID = 1L;

		private transient Method method;
		private MethodWrapper(Method method) {
			this.method = method;
		}
		private void writeObject(ObjectOutputStream out) throws IOException, ClassNotFoundException {
			out.defaultWriteObject();
			out.writeObject(method.getDeclaringClass());
			out.writeObject(method.getName());
			out.writeObject(method.getParameterTypes());
		}
		private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
			in.defaultReadObject();
			Class type = (Class)in.readObject();
			String name = (String)in.readObject();
			Class[] args = (Class[])in.readObject();
			try {
				method = type.getDeclaredMethod(name, args);
			} catch (NoSuchMethodException e) {
				throw new IOException(e.getMessage());
			}
		}	
	}

	private transient Method[] functions;
	private final ValueExpression[] variables;
	private final TypeConverter converter;

	/**
	 * Constructor.
	 */
	public Bindings(Method[] functions, ValueExpression[] variables) {
		this(functions, variables, TypeConverter.DEFAULT);
	}

	/**
	 * Constructor.
	 */
	public Bindings(Method[] functions, ValueExpression[] variables, TypeConverter converter) {
		super();

		this.functions = functions == null || functions.length == 0 ? NO_FUNCTIONS : functions;
		this.variables = variables == null || variables.length == 0 ? NO_VARIABLES : variables;
		this.converter = converter == null ? TypeConverter.DEFAULT : converter;
	}
	
	/**
	 * Get function by index.
	 * @param index function index
	 * @return method
	 */
	public Method getFunction(int index) {
		return functions[index];
	}
	
	/**
	 * Test if given index is bound to a function.
	 * This method performs an index check.
	 * @param index identifier index
	 * @return true if the given index is bound to a function
	 */
	public boolean isFunctionBound(int index) {
		return index >= 0 && index < functions.length;
	}
	
	/**
	 * Get variable by index.
	 * @param index identifier index
	 * @return value expression
	 */
	public ValueExpression getVariable(int index) {
		return variables[index];
	}

	/**
	 * Test if given index is bound to a variable.
	 * This method performs an index check.
	 * @param index identifier index
	 * @return true if the given index is bound to a variable
	 */
	public boolean isVariableBound(int index) {
		return index >= 0 && index < variables.length && variables[index] != null;
	}
	
	/**
	 * Apply type conversion.
	 * @param value value to convert
	 * @param type target type
	 * @return converted value
	 * @throws ELException
	 */
	public  T convert(Object value, Class type) {
		return converter.convert(value, type);
	}
	
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Bindings) {
			Bindings other = (Bindings)obj;
			return Arrays.equals(functions, other.functions)
				&& Arrays.equals(variables, other.variables)
				&& converter.equals(other.converter);
		}
		return false;
	}

	@Override
	public int hashCode() {
		return Arrays.hashCode(functions) ^ Arrays.hashCode(variables) ^ converter.hashCode();
	}

	private void writeObject(ObjectOutputStream out) throws IOException, ClassNotFoundException {
		out.defaultWriteObject();
		MethodWrapper[] wrappers = new MethodWrapper[functions.length];
		for (int i = 0; i < wrappers.length; i++) {
			wrappers[i] = new MethodWrapper(functions[i]);
		}
		out.writeObject(wrappers);
	}

	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
		in.defaultReadObject();
		MethodWrapper[] wrappers = (MethodWrapper[])in.readObject();
		if (wrappers.length == 0) {
			functions = NO_FUNCTIONS;
		} else {
			functions = new Method[wrappers.length];
			for (int i = 0; i < functions.length; i++) {
				functions[i] = wrappers[i].method;
			}
		}
	}	
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy