/**
* Copyright 2014 SAP AG
*
* 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 org.aim.api.measurement.dataset;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import org.aim.api.measurement.AbstractRecord;
/**
* A parameter configuration selection.
*
* @author Alexander Wert
*
*/
public class ParameterSelection {
/**
*
* @return new instance of parameter selection
*/
public static ParameterSelection newSelection() {
return new ParameterSelection();
}
private final Set<Parameter> selection;
private final Set<Parameter> unEqualSelection;
private final Set<Parameter> largerSelection;
private final Set<Parameter> smallerSelection;
/**
* Constructor.
*/
public ParameterSelection() {
selection = new TreeSet<>();
unEqualSelection = new TreeSet<>();
largerSelection = new TreeSet<>();
smallerSelection = new TreeSet<>();
}
/**
* Tells the selection to select all records which have a smaller value for
* the given parameter name then specified by the given parameter.
*
* @param parameter
* parameter for which the value should be smaller
* @return the modified parameter selection
*/
public ParameterSelection smallerOrEquals(Parameter parameter) {
removeExistingParameterwithSameName(parameter.getName(), smallerSelection);
smallerSelection.add(parameter);
return this;
}
/**
* Tells the selection to select all records which have a smaller value for
* the given parameter name then specified by the given parameter.
*
* @param parName
* name of the parameter for which the value should be smaller
* @param value
* upper limit for that parameter
* @return the modified parameter selection
*/
public ParameterSelection smallerOrEquals(String parName, Object value) {
smallerOrEquals(new Parameter(parName, value));
return this;
}
/**
* Tells the selection to select all records which have a larger value for
* the given parameter name then specified by the given parameter.
*
* @param parameter
* parameter for which the value should be larger
* @return the modified parameter selection
*/
public ParameterSelection largerOrEquals(Parameter parameter) {
removeExistingParameterwithSameName(parameter.getName(), largerSelection);
largerSelection.add(parameter);
return this;
}
/**
* Tells the selection to select all records which have a larger value for
* the given parameter name then specified by the given parameter.
*
* @param parName
* name of the parameter for which the value should be larger
* @param value
* lower limit for that parameter
* @return the modified parameter selection
*/
public ParameterSelection largerOrEquals(String parName, Object value) {
largerOrEquals(new Parameter(parName, value));
return this;
}
/**
* Tells the selection to select all records which have a value between
* lower and upper limitfor the given parameter name.
*
* @param parName
* name of the parameter for which the value should be larger
* @param lowerLimit
* lower limit for that parameter
* @param upperLimit
* upper limit for that parameter
* @return the modified parameter selection
*/
public ParameterSelection between(String parName, Object lowerLimit, Object upperLimit) {
if (!lowerLimit.getClass().equals(upperLimit.getClass())) {
throw new IllegalArgumentException("Lower and upper limit must have the same type!");
}
largerOrEquals(new Parameter(parName, lowerLimit));
smallerOrEquals(new Parameter(parName, upperLimit));
return this;
}
/**
* Selects the given parameter. If a parameter with same name within this
* selection exists the old value will be overwritten.
*
* @param parameter
* parameter for which the value should be fixed
* @return the modified parameter selection
*/
public ParameterSelection select(Parameter parameter) {
removeExistingParameterwithSameName(parameter.getName(), selection);
selection.add(parameter);
return this;
}
/**
* Selects the given parameter. If a parameter with same name within this
* selection exists the old value will be overwritten.
*
* @param parameter
* parameter for which the value should be excluded
* @return the modified parameter selection
*/
public ParameterSelection unequal(Parameter parameter) {
unEqualSelection.add(parameter);
return this;
}
/**
* Excludes the given parameter from selection.
* @param parName parameter name
* @param value parameter value
* @return selection instance
*/
public ParameterSelection unequal(String parName, Object value) {
unequal(new Parameter(parName, value));
return this;
}
/**
* Selects the given parameters.If a parameter with same name within this
* selection exists the old value will be overwritten.
*
* @param parameters
* parameters for which the value should be fixed
* @return the modified parameter selection
*/
public ParameterSelection select(Collection<Parameter> parameters) {
for (Parameter p : parameters) {
select(p);
}
return this;
}
/**
* Selects the given parameter. If a parameter with same name within this
* selection exists the old value will be overwritten.
*
* @param parName
* of parameter
* @param value
* for the parameter to fix
* @return the modified parameter selection
*/
public ParameterSelection select(String parName, Object value) {
return select(new Parameter(parName, value));
}
private void removeExistingParameterwithSameName(String parName, Set<Parameter> parameters) {
Parameter parToRemove = null;
for (Parameter p : parameters) {
if (p.getName().equalsIgnoreCase(parName)) {
parToRemove = p;
}
}
if (parToRemove != null) {
parameters.remove(parToRemove);
}
}
/**
* applies selection to given dataset row.
*
* @param dsRow
* dataset row to select from
* @return selected dataset row or null if no records could be selected
*/
public DatasetRow applyTo(DatasetRow dsRow) {
return applyToWithSubSelection(dsRow, selection, unEqualSelection, smallerSelection, largerSelection);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private DatasetRow applyToWithSubSelection(DatasetRow dsRow, Set<Parameter> subSelection,
Set<Parameter> unEqualSelection, Set<Parameter> subSmaller, Set<Parameter> subLarger) {
DatasetRowBuilder dsRowBuilder = new DatasetRowBuilder(dsRow.getRecordType());
recordLoop: for (AbstractRecord record : dsRow.getRecords()) {
if (unEqualSelection != null) {
for (Parameter parameter : unEqualSelection) {
if (parameter.getValue().equals(record.getValue(parameter.getName()))) {
continue recordLoop;
}
}
}
if (subSelection != null) {
for (Parameter parameter : subSelection) {
if (!parameter.getValue().equals(record.getValue(parameter.getName()))) {
continue recordLoop;
}
}
}
if (subSmaller != null) {
for (Parameter parameter : subSmaller) {
Comparable upperLimit = (Comparable) parameter.getValue();
Comparable value = (Comparable) record.getValue(parameter.getName());
if (value.compareTo(upperLimit) > 0) {
continue recordLoop;
}
}
}
if (subLarger != null) {
for (Parameter parameter : subLarger) {
Comparable lowerLimit = (Comparable) parameter.getValue();
Comparable value = (Comparable) record.getValue(parameter.getName());
if (value.compareTo(lowerLimit) < 0) {
continue recordLoop;
}
}
}
dsRowBuilder.addRecordWithoutChecks(record);
}
for (Parameter parameter : dsRow.getParameters()) {
dsRowBuilder.addInputParameterWithoutChecks(parameter);
}
return dsRowBuilder.build();
}
/**
* applies selection to given dataset.
*
* @param dataset
* dataset to select from
* @return selected dataset
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public Dataset applyTo(Dataset dataset) {
Set<Parameter> selectionInputParameters = null;
Set<Parameter> selectionObservationParameters = null;
Set<Parameter> unEqualInputParameters = null;
Set<Parameter> unEqualnObservationParameters = null;
Set<Parameter> smallerInputParameters = null;
Set<Parameter> smallerObservationParameters = null;
Set<Parameter> largerInputParameters = null;
Set<Parameter> largerObservationParameters = null;
if (!selection.isEmpty()) {
selectionInputParameters = new HashSet<>();
selectionObservationParameters = new HashSet<>();
splitParametersIntoInputAndOutput(dataset, selectionInputParameters, selectionObservationParameters,
selection);
}
if (!unEqualSelection.isEmpty()) {
unEqualInputParameters = new HashSet<>();
unEqualnObservationParameters = new HashSet<>();
splitParametersIntoInputAndOutput(dataset, unEqualInputParameters, unEqualnObservationParameters,
unEqualSelection);
}
if (!smallerSelection.isEmpty()) {
smallerInputParameters = new HashSet<>();
smallerObservationParameters = new HashSet<>();
splitParametersIntoInputAndOutput(dataset, smallerInputParameters, smallerObservationParameters,
smallerSelection);
}
if (!largerSelection.isEmpty()) {
largerInputParameters = new HashSet<>();
largerObservationParameters = new HashSet<>();
splitParametersIntoInputAndOutput(dataset, largerInputParameters, largerObservationParameters,
largerSelection);
}
DatasetBuilder dsBuilder = new DatasetBuilder(dataset.getRecordType());
rowLoop: for (DatasetRow row : dataset.getRows()) {
if (selectionInputParameters != null && !row.getParameters().containsAll(selectionInputParameters)) {
continue rowLoop;
}
if (unEqualInputParameters != null) {
for (Parameter par : unEqualInputParameters) {
if (row.getParameters().contains(par)) {
continue rowLoop;
}
}
}
if (smallerInputParameters != null) {
for (Parameter par : smallerInputParameters) {
Comparable upperLimit = (Comparable) par.getValue();
Comparable value = (Comparable) row.getValues(par.getName()).get(0);
if (value.compareTo(upperLimit) > 0) {
continue rowLoop;
}
}
}
if (largerInputParameters != null) {
for (Parameter par : largerInputParameters) {
Comparable lowerLimit = (Comparable) par.getValue();
Comparable value = (Comparable) row.getValues(par.getName()).get(0);
if (value.compareTo(lowerLimit) < 0) {
continue rowLoop;
}
}
}
if ((selectionObservationParameters == null || selectionObservationParameters.isEmpty())
&& (unEqualInputParameters == null || unEqualnObservationParameters.isEmpty())
&& (smallerObservationParameters == null || smallerObservationParameters.isEmpty())
&& (largerObservationParameters == null || largerObservationParameters.isEmpty())) {
dsBuilder.addRowWithoutChecks(row);
} else {
dsBuilder.addRowWithoutChecks(applyToWithSubSelection(row, selectionObservationParameters,
unEqualnObservationParameters, smallerObservationParameters, largerObservationParameters));
}
}
return dsBuilder.build();
}
private void splitParametersIntoInputAndOutput(Dataset dataset, Set<Parameter> selectionInputParameters,
Set<Parameter> selectionObservationParameters, Set<Parameter> selectionSet) {
Set<String> dsInputParameters = dataset.getInputParameterNames();
for (Parameter parameter : selectionSet) {
if (dsInputParameters.contains(parameter.getName())) {
selectionInputParameters.add(parameter);
} else {
selectionObservationParameters.add(parameter);
}
}
}
/**
* applies selection to given data.
*
* @param data
* data to select from
* @return selected data
*/
public DatasetCollection applyTo(DatasetCollection data) {
DatasetCollectionBuilder dscBuilder = new DatasetCollectionBuilder();
for (Dataset dataset : data.getDataSets()) {
Dataset selectedDS = applyTo(dataset);
if (selectedDS != null) {
dscBuilder.addDataSet(selectedDS);
}
}
return dscBuilder.build();
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((largerSelection == null) ? 0 : largerSelection.hashCode());
result = prime * result + ((selection == null) ? 0 : selection.hashCode());
result = prime * result + ((smallerSelection == null) ? 0 : smallerSelection.hashCode());
result = prime * result + ((unEqualSelection == null) ? 0 : unEqualSelection.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 (getClass() != obj.getClass()) {
return false;
}
ParameterSelection other = (ParameterSelection) obj;
if (largerSelection == null) {
if (other.largerSelection != null) {
return false;
}
} else if (!largerSelection.equals(other.largerSelection)) {
return false;
}
if (selection == null) {
if (other.selection != null) {
return false;
}
} else if (!selection.equals(other.selection)) {
return false;
}
if (smallerSelection == null) {
if (other.smallerSelection != null) {
return false;
}
} else if (!smallerSelection.equals(other.smallerSelection)) {
return false;
}
if (unEqualSelection == null) {
if (other.unEqualSelection != null) {
return false;
}
} else if (!unEqualSelection.equals(other.unEqualSelection)) {
return false;
}
return true;
}
}