/* * Copyright 2016 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.serialization; import com.google.android.libraries.remixer.DataType; import com.google.android.libraries.remixer.ItemListVariable; import com.google.android.libraries.remixer.RangeVariable; import com.google.android.libraries.remixer.Remixer; import com.google.android.libraries.remixer.Variable; import java.util.List; /** * This is an intermediate format that conforms to the agreed upon cross-platform storage and sync * protocol. * * <p>This is never used for anything other than storage and syncing and is meant to be converted to * a regular {@link com.google.android.libraries.remixer.Variable} as soon as it's completely * parsed. */ public class StoredVariable<T> { /** * The serializable string to represent the constraintType on values for variables of the * {@link Variable} class. */ public final static String VARIABLE_CONSTRAINT = "__ConstraintTypeNone__"; /** * The serializable string to represent the constraintType on values for variables of the * {@link ItemListVariable} class. */ public final static String ITEM_LIST_VARIABLE_CONSTRAINT = "__ConstraintTypeList__"; /** * The serializable string to represent the constraintType on values for variables of the * {@link RangeVariable} class. */ public final static String RANGE_VARIABLE_CONSTRAINT = "__ConstraintTypeRange__"; // Json dictionary keys to serialize this object public static final String KEY = "key"; public static final String TITLE = "title"; public static final String CONSTRAINT_TYPE = "constraintType"; public static final String DATA_TYPE = "dataType"; public static final String SELECTED_VALUE = "selectedValue"; public static final String LIMITED_TO_VALUES = "limitedToValues"; public static final String MIN_VALUE = "minValue"; public static final String MAX_VALUE = "maxValue"; public static final String INCREMENT = "increment"; /** * The RemixerItem's key. */ String key; /** * The RemixerItem's title. It's optional. */ String title; /** * The data type this variable represents, it's the string representation of one of the {@link * DataType}. */ String dataType; /** * The constraintType on this variable. * * <p>If this is a regular {@link Variable} it's "none", if it's an {@link ItemListVariable} it's * "list", and if it is a {@link RangeVariable} it's "range". */ String constraintType; /** * The currently selected value for the variable. */ T selectedValue; /** * The list of possible values, if this is not null then this StoredVariable represents a {@link * com.google.android.libraries.remixer.ItemListVariable}. */ List<T> limitedToValues; // These are only used in case it T is a number and it is a range variable, otherwise they are // ignored. /** * The minimum value for the {@link com.google.android.libraries.remixer.RangeVariable} */ T minValue; /** * The maximum value for the {@link com.google.android.libraries.remixer.RangeVariable} */ T maxValue; /** * The increment value for the {@link com.google.android.libraries.remixer.RangeVariable} */ T increment; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getConstraintType() { return constraintType; } public void setConstraintType(String constraintType) { this.constraintType = constraintType; } public String getDataType() { return dataType; } public void setDataType(String dataType) { this.dataType = dataType; } public T getSelectedValue() { return selectedValue; } public void setSelectedValue(T selectedValue) { this.selectedValue = selectedValue; } public List<T> getLimitedToValues() { return limitedToValues; } public void setLimitedToValues(List<T> limitedToValues) { this.limitedToValues = limitedToValues; } public T getMinValue() { return minValue; } public void setMinValue(T minValue) { this.minValue = minValue; } public T getMaxValue() { return maxValue; } public void setMaxValue(T maxValue) { this.maxValue = maxValue; } public T getIncrement() { return increment; } public void setIncrement(T increment) { this.increment = increment; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null || getClass() != obj.getClass()) { return false; } StoredVariable<?> variable = (StoredVariable<?>) obj; if (!isCompatibleWith(variable)) { return false; } if (title != null ? !title.equals(variable.title) : variable.title != null) { return false; } return selectedValue != null ? selectedValue.equals(variable.selectedValue) : variable.selectedValue == null; } /** * Checks whether the configuration of this stored variable matches the configuration of the * argument. The configuration explicitly excludes the value for comparison, the value may be * synced later if the configurations are compatible */ @SuppressWarnings("PMD.CollapsibleIfStatements") public boolean isCompatibleWith(StoredVariable<?> variable) { if (!key.equals(variable.key)) { return false; } if (!dataType.equals(variable.dataType)) { return false; } if (limitedToValues != null ? !limitedToValues.equals(variable.limitedToValues) : variable.limitedToValues != null) { return false; } if (minValue != null ? !minValue.equals(variable.minValue) : variable.minValue != null) { return false; } if (maxValue != null ? !maxValue.equals(variable.maxValue) : variable.maxValue != null) { return false; } return increment != null ? increment.equals(variable.increment) : variable.increment == null; } @Override public int hashCode() { int result = key.hashCode(); result = 31 * result + (title != null ? title.hashCode() : 0); result = 31 * result + dataType.hashCode(); result = 31 * result + (selectedValue != null ? selectedValue.hashCode() : 0); result = 31 * result + (limitedToValues != null ? limitedToValues.hashCode() : 0); result = 31 * result + (minValue != null ? minValue.hashCode() : 0); result = 31 * result + (maxValue != null ? maxValue.hashCode() : 0); result = 31 * result + (increment != null ? increment.hashCode() : 0); return result; } /** * Creates a Stored variable from a existing RemixerItem. */ public static StoredVariable fromVariable(Variable item) { StoredVariable storedVariable = null; for (DataType type : Remixer.getRegisteredDataTypes()) { try { storedVariable = type.getConverter().fromVariable(item); break; } catch (IllegalArgumentException ex) { // Don't do anything, this just wasn't the right data type. storedVariable = null; } } if (storedVariable == null) { throw new UnsupportedOperationException( "Cannot convert remixer item, maybe you forgot to add support for a new type?"); } storedVariable.key = item.getKey(); storedVariable.title = item.getTitle(); storedVariable.constraintType = item.getSerializableConstraints(); return storedVariable; } }