/** * 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.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.aim.api.measurement.AbstractRecord; /** * Builder for wrapped records. * * @author Alexander Wert * */ public class DatasetRowBuilder { private List<AbstractRecord> records; private TreeSet<Parameter> parameters; private Class<? extends AbstractRecord> recordType; private List<String> recordNonMetricParameterNames; private int recordStructureHash; /** * Construcotr. * * @param recordType * type of the records for which the wrapped record should be * built. */ public DatasetRowBuilder(Class<? extends AbstractRecord> recordType) { this.recordType = recordType; records = new ArrayList<>(); parameters = new TreeSet<>(); updateStructureHash(); } /** * Adds a new input parameter to the wrapped record. * * @param name * parameter name * @param value * parameter value */ public void addInputParameter(String name, Object value) { addInputParameter(new Parameter(name, value)); } /** * Adds a new input parameter to the wrapped record. * * @param parameter * parameter to add */ public void addInputParameter(Parameter parameter) { if (!validParameter(parameter.getName(), parameter.getValue())) { throw new IllegalArgumentException("Invalid input parameter!"); } parameters.add(parameter); updateStructureHash(); } /** * For internal use only. Adds an input parameter without checking its * validity. * * @param parameter * parameter to add */ protected void addInputParameterWithoutChecks(Parameter parameter) { parameters.add(parameter); updateStructureHash(); } private void updateStructureHash() { Set<String> names = new HashSet<>(); for (Parameter p : parameters) { names.add(p.getName()); } setRecordStructureHash(names.hashCode() + recordType.hashCode()); } /** * Adds a record to this wrapped record. Note: this method assumes that all * non metric parameter values match the one of this wrapped record. If this * is not the case the behaviour of this wrapped record is not predictible. * Use the method checkParameters(...) to check whethr your record is * conform to this wrapped record. * * @param record * the record to add to the wrapper */ public void addRecord(final AbstractRecord record) { if (record == null) { throw new IllegalArgumentException("Passed record is null!"); } else if (!recordType.equals(record.getClass())) { throw new IllegalArgumentException("Passed Record type " + record.getClass().getName() + " is not compatibel with the wrapper record type " + recordType.getName()); } if (records.isEmpty()) { List<String> parNames = record.getNonMetricParameterNames(); List<Object> parValues = record.getNonMetricValues(); for (int i = 0; i < parNames.size(); i++) { addInputParameter(parNames.get(i), parValues.get(i)); } } records.add(record); } /** * FOr internal use only! Adds a record without checking its validity for * this dataset row. * * @param record * record to add */ protected void addRecordWithoutChecks(final AbstractRecord record) { records.add(record); } /** * checks whether this record is valid for the wrapped record. * * @param record * record to check * @return true if valid */ public boolean isValidRecord(final AbstractRecord record) { if (records.isEmpty() && recordType.equals(record.getClass())) { return true; } if (recordNonMetricParameterNames == null) { recordNonMetricParameterNames = record.getNonMetricParameterNames(); } List<Object> parValues = record.getNonMetricValues(); for (int i = 0; i < recordNonMetricParameterNames.size(); i++) { if (!validExistingParameter(recordNonMetricParameterNames.get(i), parValues.get(i))) { return false; } } return true; } /** * checks parameters. * * @param parameterNames * names * @param parameterValues * values * @return true if parameters are valid for this wrapped record */ public boolean areValidParameters(String[] parameterNames, Object[] parameterValues) { if (parameterNames.length != parameterValues.length) { throw new IllegalArgumentException("Number of parameter names must match number of parameter values!"); } for (int i = 0; i < parameterNames.length; i++) { if (!validExistingParameter(parameterNames[i], parameterValues[i])) { return false; } } return true; } /** * checks parameters. * * @param parameters * parameters * @return true if parameters are valid for this wrapped record */ public boolean areValidParameters(Set<Parameter> parameters) { for (Parameter par : parameters) { if (!validExistingParameter(par.getName(), par.getValue())) { return false; } } return true; } /** * Adds records to the wrapped record. * * @param records * records to add */ public void addRecords(final Collection<AbstractRecord> records) { for (AbstractRecord rec : records) { addRecord(rec); } } /** * * @return a new {@link DatasetRow} or null if no records are available to * build a row */ public DatasetRow build() { if (records.isEmpty()) { return null; } else { return new DatasetRow(recordType, parameters, records); } } /** * * @param parameter * parameter to check * @return true, if parameter with that name does not exist yet in the * wrapped record to build or if the parameter with the same value * already eists. */ private boolean validParameter(final String name, final Object value) { for (Parameter p : parameters) { if (p.getName().equals(name) && !p.getValue().equals(value)) { return false; } } return true; } /** * * @param parameter * parameter to check * @return true, if parameter with that name already exists and has the same * value */ private boolean validExistingParameter(final String name, final Object value) { for (Parameter p : parameters) { if (p.getName().equals(name)) { return p.getValue().equals(value); } } return false; } /** * @return the recordStructureHash */ protected int getRecordStructureHash() { return recordStructureHash; } /** * @param recordStructureHash * the recordStructureHash to set */ protected void setRecordStructureHash(int recordStructureHash) { this.recordStructureHash = recordStructureHash; } }