blob: 31a829043b2bceeaeaf4a67ef7f5a447b6dae2e2 [file] [log] [blame]
/*
* 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());
}
}
}