/*
* Copyright (c) 2014 Carman Consulting, Inc.
*
* 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.carmanconsulting.cassidy.util;
import com.carmanconsulting.cassidy.exception.CassidyException;
import com.carmanconsulting.cassidy.serializer.SerializerRegistry;
import me.prettyprint.cassandra.serializers.BytesArraySerializer;
import me.prettyprint.hector.api.Cluster;
import me.prettyprint.hector.api.Keyspace;
import me.prettyprint.hector.api.Serializer;
import me.prettyprint.hector.api.beans.DynamicComposite;
import me.prettyprint.hector.api.ddl.KeyspaceDefinition;
import me.prettyprint.hector.api.factory.HFactory;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.reflect.ConstructorUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
public final class CassidyUtils {
//----------------------------------------------------------------------------------------------------------------------
// Fields
//----------------------------------------------------------------------------------------------------------------------
private static final Logger LOGGER = LoggerFactory.getLogger(CassidyUtils.class);
private static final BytesArraySerializer NULL_SERIALIZER = BytesArraySerializer.get();
private static final byte[] NULL_VALUE = new byte[0];
private static final Map<Class<?>, Object> DEFAULT_VALUES = new HashMap<>();
//----------------------------------------------------------------------------------------------------------------------
// Static Methods
//----------------------------------------------------------------------------------------------------------------------
static {
DEFAULT_VALUES.put(Byte.class, (byte) 0);
DEFAULT_VALUES.put(Byte.TYPE, (byte) 0);
DEFAULT_VALUES.put(Short.class, (short) 0);
DEFAULT_VALUES.put(Short.TYPE, (short) 0);
DEFAULT_VALUES.put(Integer.class, 0);
DEFAULT_VALUES.put(Integer.TYPE, 0);
DEFAULT_VALUES.put(Long.class, 0L);
DEFAULT_VALUES.put(Long.TYPE, 0L);
DEFAULT_VALUES.put(Float.class, 0.0f);
DEFAULT_VALUES.put(Float.TYPE, 0.0f);
DEFAULT_VALUES.put(Double.class, 0.0);
DEFAULT_VALUES.put(Double.TYPE, 0.0);
DEFAULT_VALUES.put(Boolean.class, false);
DEFAULT_VALUES.put(Boolean.TYPE, false);
DEFAULT_VALUES.put(Character.class, (char) 0);
DEFAULT_VALUES.put(Character.TYPE, (char) 0);
}
public static Keyspace createKeyspace(Cluster cluster, KeyspaceDefinition definition) {
return createKeyspace(cluster, definition, true);
}
public static Keyspace createKeyspace(Cluster cluster, KeyspaceDefinition definition, boolean waitForSchemaAgreement) {
LOGGER.info("Attempting to create keyspace {}...", definition.getName());
final KeyspaceDefinition existing = cluster.describeKeyspace(definition.getName());
if (existing == null) {
cluster.addKeyspace(definition, waitForSchemaAgreement);
LOGGER.info("Keyspace {} created successfully.", definition.getName());
} else {
LOGGER.info("Keyspace {} already exists.", definition.getName());
}
return HFactory.createKeyspace(definition.getName(), cluster);
}
private static String getClassName(Object target) {
return target == null ? "null" : target.getClass().getCanonicalName();
}
public static Object getDefaultValue(Class<?> type) {
return DEFAULT_VALUES.get(type);
}
public static Object getFieldValue(Object target, String fieldName) {
try {
LOGGER.debug("Getting field {} value from object {} (type={})...", fieldName, target, getClassName(target));
return FieldUtils.readField(target, fieldName, true);
}
catch (IllegalAccessException e) {
throw new CassidyException(String.format("Unable to read field %s value from object of type %s.", fieldName, getClassName(target)), e);
}
}
public static <T> T instantiate(Class<T> type) {
try {
LOGGER.debug("Instantiating object of type {}...", type.getCanonicalName());
return Validate.notNull(type.newInstance());
}
catch (InstantiationException e) {
throw new CassidyException(String.format("Unable to instantiate object of type %s.", type.getName()), e);
}
catch (IllegalAccessException e) {
throw new CassidyException(String.format("Type %s has no accessible default constructor.", type.getName()), e);
}
}
public static boolean isDefaultValue(Class<?> type, Object value) {
return ObjectUtils.equals(value, DEFAULT_VALUES.get(type));
}
public static boolean isInstantiable(Class<?> type) {
return ConstructorUtils.getAccessibleConstructor(type) != null;
}
public static void setFieldValue(Object target, String fieldName, Object value) {
try {
LOGGER.debug("Setting field {} to value {} on object {} (type={})...", fieldName, value, target, getClassName(target));
FieldUtils.writeField(target, fieldName, value, true);
}
catch (IllegalAccessException e) {
throw new CassidyException(String.format("Unable to write field %s value on object of type %s.", fieldName, getClassName(target)), e);
}
}
@SuppressWarnings("unchecked")
public static DynamicComposite toComposite(SerializerRegistry registry, Iterable<?> values) {
DynamicComposite composite = new DynamicComposite();
for (Object value : values) {
if (value == null) {
composite.addComponent(NULL_VALUE, NULL_SERIALIZER);
} else {
composite.addComponent(value, (Serializer<Object>) registry.getSerializer(value.getClass()));
}
}
return composite;
}
//----------------------------------------------------------------------------------------------------------------------
// Constructors
//----------------------------------------------------------------------------------------------------------------------
private CassidyUtils() {
}
}