/**
* Copyright (C) 2001-2017 by RapidMiner and the contributors
*
* Complete list of developers available at our web site:
*
* http://rapidminer.com
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program.
* If not, see http://www.gnu.org/licenses/.
*/
package com.rapidminer.example.utils;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import com.rapidminer.RapidMiner;
import com.rapidminer.example.Attribute;
import com.rapidminer.example.Attributes;
import com.rapidminer.example.ExampleSet;
import com.rapidminer.example.SimpleAttributes;
import com.rapidminer.example.set.SimpleExampleSet;
import com.rapidminer.example.table.BinominalAttribute;
import com.rapidminer.example.table.DateAttribute;
import com.rapidminer.example.table.ExampleTable;
import com.rapidminer.example.table.GrowingExampleTable;
import com.rapidminer.example.table.MemoryExampleTable;
import com.rapidminer.example.table.NumericalAttribute;
import com.rapidminer.example.table.PolynominalAttribute;
import com.rapidminer.example.table.internal.ColumnarExampleTable;
import com.rapidminer.example.utils.ExampleSetBuilder.DataManagement;
import com.rapidminer.operator.preprocessing.MaterializeDataInMemory;
import com.rapidminer.tools.ParameterService;
/**
* This class consists exclusively of static methods that help to build new {@link ExampleSet}s.
*
* @author Gisa Schaefer
* @since 7.3
*/
public final class ExampleSets {
/** Set of primitive attribute types that are known to be thread safe for read accesses. */
private static final Set<Class<? extends Attribute>> SAFE_ATTRIBUTES = new HashSet<>(5);
static {
SAFE_ATTRIBUTES.add(DateAttribute.class);
SAFE_ATTRIBUTES.add(BinominalAttribute.class);
SAFE_ATTRIBUTES.add(PolynominalAttribute.class);
SAFE_ATTRIBUTES.add(DateAttribute.class);
SAFE_ATTRIBUTES.add(NumericalAttribute.class);
}
private ExampleSets() {}
/**
* Creates a builder for an {@link ExampleSet} starting from the given attributes. If the given
* attributes are {@code null}, the example will have no attributes.
*
* @param attributes
* the attributes for the new {@link ExampleSet}, can be {@code null}
* @return the {@link ExampleSetBuilder} to build the example set
*/
public static ExampleSetBuilder from(List<Attribute> attributes) {
if (Boolean.valueOf(ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_SYSTEM_LEGACY_DATA_MGMT))) {
return new MemoryExampleSetBuilder(attributes);
} else {
return new ColumnarExampleSetBuilder(attributes);
}
}
/**
* Creates a builder for an {@link ExampleSet} starting from the given attributes.
*
* @param attributes
* the attributes for the new {@link ExampleSet}
* @return the {@link ExampleSetBuilder} to build the example set
*/
public static ExampleSetBuilder from(Attribute... attributes) {
if (Boolean.valueOf(ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_SYSTEM_LEGACY_DATA_MGMT))) {
return new MemoryExampleSetBuilder(attributes);
} else {
return new ColumnarExampleSetBuilder(attributes);
}
}
/**
* Creates an {@link ExampleTable} to which rows can be added. Only use this if it is not
* possible to use an {@link ExampleSetBuilder}.
*
* @param attributes
* the attributes for the new {@link ExampleTable}
* @return a table that can grow
*/
@SuppressWarnings("deprecation")
public static GrowingExampleTable createTableFrom(List<Attribute> attributes) {
if (Boolean.valueOf(ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_SYSTEM_LEGACY_DATA_MGMT))) {
return new MemoryExampleTable(attributes);
} else {
return new ColumnarExampleTable(attributes);
}
}
/**
* Creates an {@link ExampleTable} to which rows can be added. Only use this if it is not
* possible to use an {@link ExampleSetBuilder}.
*
* @param attributes
* the attributes for the new {@link ExampleTable}
* @param management
* the {@link DataManagement} to use for the table if supported
* @return a table that can grow
*/
@SuppressWarnings("deprecation")
public static GrowingExampleTable createTableFrom(List<Attribute> attributes, DataManagement management) {
if (Boolean.valueOf(ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_SYSTEM_LEGACY_DATA_MGMT))) {
return new MemoryExampleTable(attributes);
} else {
return new ColumnarExampleTable(attributes, management, false);
}
}
/**
* Creates a copy of the input that guarantees thread-safety for read access and attribute set manipulations.
* If the input already provides these guarantees, a shallow copy is return, otherwise a deep copy is created.
*
* @param set the input example set
* @return the thread safe copy of the given set
* @throws IllegalArgumentException if the input example set is {@code null}
*/
public static ExampleSet createThreadSafeCopy(ExampleSet set) {
if (set == null) {
throw new IllegalArgumentException("Example set must not be null");
}
boolean foundUnsafeComponent = false;
// check example set implementation
foundUnsafeComponent |= set.getClass() != SimpleExampleSet.class;
// check example table implementation
if (!foundUnsafeComponent) {
ExampleTable table = set.getExampleTable();
foundUnsafeComponent |= table.getClass() != ColumnarExampleTable.class;
}
// check attribute implementation
if (!foundUnsafeComponent) {
Attributes attributes = set.getAttributes();
foundUnsafeComponent |= attributes.getClass() != SimpleAttributes.class;
}
// check individual attributes and attribute transformations
if (!foundUnsafeComponent) {
Iterator<Attribute> attributes = set.getAttributes().allAttributes();
while (!foundUnsafeComponent && attributes.hasNext()) {
Attribute attribute = attributes.next();
if (!SAFE_ATTRIBUTES.contains(attribute.getClass()) || attribute.getLastTransformation() != null) {
foundUnsafeComponent = true;
}
}
}
if (foundUnsafeComponent) {
return MaterializeDataInMemory.materializeExampleSet(set);
} else {
return (ExampleSet) set.clone();
}
}
}