/* * 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.apache.openjpa.persistence; import java.lang.reflect.Method; import java.util.List; import javax.persistence.Tuple; import javax.persistence.TupleElement; import org.apache.openjpa.kernel.Filters; import org.apache.openjpa.lib.util.Localizer; /** * Tuple holds a set of values corresponding to a set of {@link TupleElement}. * This implementation prefers index-based access. * A Tuple instance is constructed by a TupleFactory. * The TupleElemets are shared across all the tuple instances. * * @author Pinaki Poddar * */ public class TupleImpl implements Tuple { private static final Localizer _loc = Localizer.forPackage(TupleImpl.class); private final TupleFactory factory; private final Object[] values; public static Method PUT; static { try { PUT = TupleImpl.class.getMethod("put", new Class[]{Integer.class, Object.class}); } catch (Exception e) { } } /** * Supply the factory that creates prototypes and holds the elements. */ TupleImpl(TupleFactory factory) { this.factory = factory; values = new Object[factory.getElements().size()]; } public <X> X get(TupleElement<X> tupleElement) { int i = factory.getIndex(tupleElement); return assertAndConvertType(""+i, values[i], tupleElement.getJavaType()); } public <X> X get(String alias, Class<X> type) { Object val = values[factory.getIndex(alias)]; return assertAndConvertType(alias, val, type); } public Object get(String alias) { return get(alias, null); } public <X> X get(int i, Class<X> type) { if (i >= values.length || i < 0) { throw new IllegalArgumentException(_loc.get("tuple-exceeded-size", i, values.length).getMessage()); } Object val = values[i]; return assertAndConvertType(""+i, val, type); } public Object get(int i) { return get(i, null); } public Object[] toArray() { return values; } public List<TupleElement<?>> getElements() { return factory.getElements(); } /** * Put the value at the given key index. * This is invoked by the kernel to populate a Tuple. */ public void put(Integer key, Object value) { values[key] = value; } /** * Assert that the given value is convertible to the given type and convert. * null type implies no conversion and a pure cast. */ <X> X assertAndConvertType(String id, Object value, Class<X> type) { try { if (type == null || value == null) { return (X) value; } else { return (X) Filters.convert(value, type); } } catch (Exception e) { throw new IllegalArgumentException(_loc.get("tuple-element-wrong-type", new Object[]{id, value, value.getClass().getName(), type.getName()}).getMessage()); } } }