package org.magenta; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Arrays; import org.magenta.core.EmptyDataSet; import org.magenta.core.ForwardingDataSet; import org.magenta.core.GenericDataSet; import org.magenta.random.FluentRandom; import com.google.common.base.Function; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; /** * A DataKey is used to reference a {@link DataSet}, {@link Generator} or a * {@link GenerationStrategy}. There are two types of key : default and * qualified. A default key is one created with just a class name, so it will be * considered as the "default" key for this class. A qualified key add a * qualifier to the key type so two keys referring to the same type can be * distinguished. * * @author ngagnon * * @param <D> * the data type of the referenced dataset, generator or generation * strategy. */ public class DataKey<D> { public static final String DEFAULT_QUALIFIER = "default"; private final String qualifier; private final Class<D> type; DataKey(String qualifier, Class<D> type) { this.qualifier = checkNotNull(qualifier); this.type = checkNotNull(type); } /** * Make a new key for the given qualifier and the class. * * @param qualifier * a string that disambiguate this key from another that is of the * same type. * @param type * the type of data * @param <D> * the type of data * @return a new key */ public static <D> DataKey<D> makeQualified(String qualifier, Class<D> type) { DataKey<D> ref = new DataKey<D>(qualifier, type); return ref; } /** * Make a new key for the given class using the default qualifier key. * * @param type * the type of data * @param <D> * the type of data * @return a new key */ public static <D> DataKey<D> makeDefault(Class<D> type) { DataKey<D> ref = new DataKey<D>(DEFAULT_QUALIFIER, type); return ref; } /** * Return true if this key is the default for this key type. * * @return true if it is a default key. */ public boolean isDefault() { return DEFAULT_QUALIFIER.equals(qualifier); } /** * @return the category */ public String getQualifier() { return this.qualifier; } /** * @return the type */ public Class<D> getType() { return this.type; } /** * Get the {@link DataSet} in the <code>domain</code> identified by this key. * * * @param domain the domain * @return the matching data set */ public DataSet<D> getDataSetFrom(Fixture<?> domain) { return domain.dataset(this); } /** * Return a {@link Qualified} dataset. * * @param randomizer * the randomizer to use * @param data * the data composing the qualified data set. * @return a new QualifiedDataSet */ @SuppressWarnings("unchecked") public QualifiedDataSet<D> datasetOf(FluentRandom randomizer, D... data) { return new QualifiedDataSetImpl<D>(this, new GenericDataSet<D>(Suppliers.ofInstance(Arrays.asList(data)), this.type, randomizer)); } /** * Return a {@link Qualified} dataset. * * @param randomizer * the randomizer to use * @param data * the data composing the qualified data set. * @return a new QualifiedDataSet */ @SuppressWarnings("unchecked") public QualifiedDataSet<D> datasetOf(D... data) { return new QualifiedDataSetImpl<D>(this, new GenericDataSet<D>(Suppliers.ofInstance(Arrays.asList(data)), this.type, FluentRandom.singleton())); } /** * Return a {@link Qualified} dataset. * * @param dataset * the dataset to qualify. * @return a new QualifiedDataSet */ @SuppressWarnings("unchecked") public QualifiedDataSet<D> qualify(DataSet<D> dataset) { return new QualifiedDataSetImpl<D>(this, dataset); } /** * Return a {@link Qualified} dataset. * * @param dataset * the dataset to qualify. * @return a new QualifiedDataSet */ @SuppressWarnings("unchecked") public QualifiedDataSet<D> qualify(Supplier<DataSet<D>> dataset) { return new QualifiedDataSetImpl<D>(this, dataset); } /** * * @return an empty data set for this key */ public EmptyDataSet<D> asEmptyDataSet() { return EmptyDataSet.ofType(getType()); } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (type.hashCode()); result = prime * result + (qualifier.hashCode()); return result; } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (!(obj instanceof DataKey)) { return false; } DataKey<?> other = (DataKey<?>) obj; if (!type.equals(other.getType())) { return false; } if (!qualifier.equals(other.getQualifier())) { return false; } return true; } /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append(getType().getName()).append(':').append(getQualifier()); return builder.toString(); } static class QualifiedDataSetImpl<D2> extends ForwardingDataSet<D2> implements QualifiedDataSet<D2> { private final DataKey<D2> key; private QualifiedDataSetImpl(DataKey<D2> qualifier, DataSet<D2> delegate) { super(Suppliers.ofInstance(delegate)); this.key = qualifier; } public QualifiedDataSetImpl(DataKey<D2> key, Supplier<DataSet<D2>> delegate) { super(delegate); this.key = key; } @Override public DataKey<D2> getKey() { return key; } } /** * Utility function that creates a default {@link DataKey} for a given class. * * @return the function */ @SuppressWarnings("rawtypes") public static Function<Class, DataKey> classToKey() { return new Function<Class, DataKey>() { @SuppressWarnings("unchecked") @Override public DataKey apply(Class input) { return DataKey.makeDefault(input); } }; } }