/*
* Copyright 2017 Google 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.google.android.libraries.remixer;
import com.google.android.libraries.remixer.serialization.SerializedColor;
import com.google.android.libraries.remixer.serialization.ValueConverter;
import com.google.android.libraries.remixer.serialization.converters.BooleanValueConverter;
import com.google.android.libraries.remixer.serialization.converters.ColorValueConverter;
import com.google.android.libraries.remixer.serialization.converters.FloatValueConverter;
import com.google.android.libraries.remixer.serialization.converters.StringValueConverter;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* The data type for each RemixerItem. The data type is used to determine default layoutIDs and to
* help serialization.
*
* @param <RuntimeT> The type to use during runtime to represent variables of this DataType
* @param <SerializableT> The type to use to serialize variables of this type.
*/
public class DataType<RuntimeT, SerializableT> {
/**
* The serializable, unique name for this data type.
*/
private final String name;
/**
* The runtime class of the values contained by this variable.
*/
private final Class<RuntimeT> runtimeType;
/**
* The serializable class of the values contained by this variable.
*/
private final Class<SerializableT> serializableType;
/**
* The value converter that aids in the serialization process.
*/
private final ValueConverter<RuntimeT, SerializableT> converter;
/**
* Map of default layout ids for this datatype when used with a specific RemixerItem class.
*
* <p>The key for this map is the specific RemixerItem subclass, and the value is the default
* layout to use when a RemixerItem of the specific subclass has this data type.
*/
private final Map<Class<? extends Variable>, Integer> layoutIdForVariableType =
new HashMap<>();
/**
* Constructs a datatype with the given {@code name}, that takes values of type
* {@code runtimeType} and uses {@code converter} to serialize.
*
* <p>Note {@code converter} has a {@link ValueConverter#dataType} field that must be initialized
* to the same as {@code name}.
*/
public DataType(
String name,
Class<RuntimeT> runtimeType,
Class<SerializableT> serializableType,
ValueConverter<RuntimeT, SerializableT> converter) {
this.name = name;
this.runtimeType = runtimeType;
this.serializableType = serializableType;
this.converter = converter;
if (!name.equals(converter.getDataType())) {
throw new AssertionError(String.format(
Locale.getDefault(),
"The data type %s has a converter whose data type doesn't match, %s",
name, converter.getDataType()));
}
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
DataType dataType = (DataType) obj;
if (!name.equals(dataType.name)) {
return false;
}
return runtimeType.equals(dataType.runtimeType);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + runtimeType.hashCode();
return result;
}
public void setLayoutIdForVariableType(Class<? extends Variable> clazz, int layoutId) {
layoutIdForVariableType.put(clazz, layoutId);
}
public int getLayoutIdForVariableType(Class<? extends Variable> clazz) {
return layoutIdForVariableType.get(clazz);
}
public String getName() {
return name;
}
public Class<RuntimeT> getRuntimeType() {
return runtimeType;
}
public Class<SerializableT> getSerializableType() {
return serializableType;
}
public ValueConverter<RuntimeT, SerializableT> getConverter() {
return converter;
}
// ======= Default data types defined here.
private static final String KEY_BOOLEAN = "__DataTypeBoolean__";
private static final String KEY_COLOR = "__DataTypeColor__";
private static final String KEY_NUMBER = "__DataTypeNumber__";
private static final String KEY_STRING = "__DataTypeString__";
public static final DataType<Boolean, Boolean> BOOLEAN = new DataType<>(
KEY_BOOLEAN, Boolean.class, Boolean.class, new BooleanValueConverter(KEY_BOOLEAN));
public static final DataType<Integer, SerializedColor> COLOR = new DataType<>(
KEY_COLOR, Integer.class, SerializedColor.class, new ColorValueConverter(KEY_COLOR));
public static final DataType<Float, Float> NUMBER = new DataType<>(
KEY_NUMBER, Float.class, Float.class, new FloatValueConverter(KEY_NUMBER));
public static final DataType<String, String> STRING = new DataType<>(
KEY_STRING, String.class, String.class, new StringValueConverter(KEY_STRING));
}