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

com.netflix.astyanax.mapping.Mapping Maven / Gradle / Ivy

There is a newer version: 3.10.2
Show newest version
/*******************************************************************************
 * Copyright 2011 Netflix
 * 
 * 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 com.netflix.astyanax.mapping;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.netflix.astyanax.ColumnListMutation;
import com.netflix.astyanax.model.ColumnList;
import com.netflix.astyanax.model.Row;
import com.netflix.astyanax.model.Rows;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 

* Utility for doing object/relational mapping between bean-like instances and * Cassandra *

*

*

* The mapper stores values in Cassandra and maps in/out to native types. Column * names must be strings. Annotate your bean with {@link Id} and {@link Column}. * Or, provide an {@link AnnotationSet} that defines IDs and Columns in your * bean. * * @deprecated please use DefaultEntityManager instead */ @Deprecated @SuppressWarnings({ "SuspiciousMethodCalls" }) public class Mapping { private final ImmutableMap fields; private final String idFieldName; private final Class clazz; /** * If the ID column does not have a Column annotation, this column name is * used */ public static final String DEFAULT_ID_COLUMN_NAME = "ID"; /** * Convenience for allocation a mapping object * * @param clazz * clazz type to map * @return mapper */ public static Mapping make(Class clazz, boolean includeParentFields) { return new Mapping(clazz, new DefaultAnnotationSet(), includeParentFields); } public static Mapping make(Class clazz) { return new Mapping(clazz, new DefaultAnnotationSet(), false); } /** * Convenience for allocation a mapping object * * @param clazz * clazz type to map * @param annotationSet * annotations to use when analyzing a bean * @return mapper */ public static Mapping make(Class clazz, AnnotationSet annotationSet, boolean includeParentFields) { return new Mapping(clazz, annotationSet, includeParentFields); } public static Mapping make(Class clazz, AnnotationSet annotationSet) { return new Mapping(clazz, annotationSet, false); } /** * @param clazz * clazz type to map */ public Mapping(Class clazz, boolean includeParentFields) { this(clazz, new DefaultAnnotationSet(), includeParentFields); } public Mapping(Class clazz) { this(clazz, new DefaultAnnotationSet(), false); } /** * @param clazz * clazz type to map * @param annotationSet * annotations to use when analyzing a bean */ public Mapping(Class clazz, AnnotationSet annotationSet, boolean includeParentFields) { this.clazz = clazz; String localKeyFieldName = null; ImmutableMap.Builder builder = ImmutableMap.builder(); AtomicBoolean isKey = new AtomicBoolean(); Set usedNames = Sets.newHashSet(); List allFields = getFields(clazz, includeParentFields); for (Field field : allFields) { String name = mapField(field, annotationSet, builder, usedNames, isKey); if (isKey.get()) { Preconditions.checkArgument(localKeyFieldName == null); localKeyFieldName = name; } } Preconditions.checkNotNull(localKeyFieldName); fields = builder.build(); idFieldName = localKeyFieldName; } public Mapping(Class clazz, AnnotationSet annotationSet) { this(clazz, annotationSet, false); } private List getFields(Class clazz, boolean recursuvely) { List allFields = new ArrayList(); if (clazz.getDeclaredFields() != null && clazz.getDeclaredFields().length > 0) { for (Field field : clazz.getDeclaredFields()) { allFields.add(field); } if (recursuvely && clazz.getSuperclass() != null) { allFields.addAll(getFields(clazz.getSuperclass(), true)); } } return allFields; } /** * Return the value for the ID/Key column from the given instance * * @param instance * the instance * @param valueClass * type of the value (must match the actual native type in the * instance's class) * @return value */ public V getIdValue(T instance, Class valueClass) { return getColumnValue(instance, idFieldName, valueClass); } /** * Return the value for the given column from the given instance * * @param instance * the instance * @param columnName * name of the column (must match a corresponding annotated field * in the instance's class) * @param valueClass * type of the value (must match the actual native type in the * instance's class) * @return value */ public V getColumnValue(T instance, String columnName, Class valueClass) { Field field = fields.get(columnName); if (field == null) { throw new IllegalArgumentException("Column not found: " + columnName); } try { return valueClass.cast(field.get(instance)); } catch (IllegalAccessException e) { throw new RuntimeException(e); // should never get here } } /** * Set the value for the ID/Key column for the given instance * * @param instance * the instance * @param value * The value (must match the actual native type in the instance's * class) */ public void setIdValue(T instance, V value) { setColumnValue(instance, idFieldName, value); } /** * Set the value for the given column for the given instance * * @param instance * the instance * @param columnName * name of the column (must match a corresponding annotated field * in the instance's class) * @param value * The value (must match the actual native type in the instance's * class) */ public void setColumnValue(T instance, String columnName, V value) { Field field = fields.get(columnName); if (field == null) { throw new IllegalArgumentException("Column not found: " + columnName); } try { field.set(instance, value); } catch (IllegalAccessException e) { throw new RuntimeException(e); // should never get here } } /** * Map a bean to a column mutation. i.e. set the columns in the mutation to * the corresponding values from the instance * * @param instance * instance * @param mutation * mutation */ public void fillMutation(T instance, ColumnListMutation mutation) { for (String fieldName : getNames()) { Coercions.setColumnMutationFromField(instance, fields.get(fieldName), fieldName, mutation); } } /** * Allocate a new instance and populate it with the values from the given * column list * * @param columns * column list * @return the allocated instance * @throws IllegalAccessException * if a new instance could not be instantiated * @throws InstantiationException * if a new instance could not be instantiated */ public T newInstance(ColumnList columns) throws IllegalAccessException, InstantiationException { return initInstance(clazz.newInstance(), columns); } /** * Populate the given instance with the values from the given column list * * @param instance * instance * @param columns * column this * @return instance (as a convenience for chaining) */ public T initInstance(T instance, ColumnList columns) { for (com.netflix.astyanax.model.Column column : columns) { Field field = fields.get(column.getName()); if (field != null) { // otherwise it may be a column that was // removed, etc. Coercions.setFieldFromColumn(instance, field, column); } } return instance; } /** * Load a set of rows into new instances populated with values from the * column lists * * @param rows * the rows * @return list of new instances * @throws IllegalAccessException * if a new instance could not be instantiated * @throws InstantiationException * if a new instance could not be instantiated */ public List getAll(Rows rows) throws InstantiationException, IllegalAccessException { List list = Lists.newArrayList(); for (Row row : rows) { if (!row.getColumns().isEmpty()) { list.add(newInstance(row.getColumns())); } } return list; } /** * Return the set of column names discovered from the bean class * * @return column names */ public Collection getNames() { return fields.keySet(); } Class getIdFieldClass() { return fields.get(idFieldName).getType(); } private String mapField( Field field, AnnotationSet annotationSet, ImmutableMap.Builder builder, Set usedNames, AtomicBoolean isKey) { String mappingName = null; ID idAnnotation = field.getAnnotation(annotationSet.getIdAnnotation()); COLUMN columnAnnotation = field.getAnnotation(annotationSet .getColumnAnnotation()); if ((idAnnotation != null) && (columnAnnotation != null)) { throw new IllegalStateException( "A field cannot be marked as both an ID and a Column: " + field.getName()); } if (idAnnotation != null) { mappingName = annotationSet.getIdName(field, idAnnotation); isKey.set(true); } else { isKey.set(false); } if ((columnAnnotation != null)) { mappingName = annotationSet.getColumnName(field, columnAnnotation); } if (mappingName != null) { Preconditions.checkArgument( !usedNames.contains(mappingName.toLowerCase()), mappingName + " has already been used for this column family"); usedNames.add(mappingName.toLowerCase()); field.setAccessible(true); builder.put(mappingName, field); } return mappingName; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy