CommonTextFormatValidator.java
/**
* VStar: a statistical analysis tool for variable star data.
* Copyright (C) 2009 AAVSO (http://www.aavso.org/)
*
* 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 org.aavso.tools.vstar.data.validation;
import java.io.IOException;
import java.util.Map;
import org.aavso.tools.vstar.data.DateInfo;
import org.aavso.tools.vstar.data.Magnitude;
import org.aavso.tools.vstar.data.SeriesType;
import org.aavso.tools.vstar.data.ValidObservation;
import org.aavso.tools.vstar.exception.ObservationValidationError;
import org.aavso.tools.vstar.exception.ObservationValidationWarning;
import org.aavso.tools.vstar.input.text.ObservationFieldSplitter;
import com.csvreader.CsvReader;
/**
* This class accepts a line of text for tokenising, validation, and
* ValidObservation instance creation that is common to all text format sources.
* Currently, simple and AAVSO download file formats have an intersecting set of
* mandatory and optional fields. The field indices differ across formats but the
* fieldIndexMap constructor argument caters for the differences.
*/
public class CommonTextFormatValidator {
protected final static String COMMON_VALFLAG_PATTERN = "G|D|T|P|U|V|Z";
protected final ObservationFieldSplitter fieldSplitter;
protected CsvReader lineReader;
protected final JulianDayValidator julianDayValidator;
protected final MagnitudeFieldValidator magnitudeFieldValidator;
protected final UncertaintyValueValidator uncertaintyValueValidator;
protected final ObserverCodeValidator observerCodeValidator;
protected final ValflagValidator valflagValidator;
protected final Map<String, Integer> fieldIndexMap;
protected String[] fields;
/**
* Constructor.
*
* @param desc
* A description of the kind of line we are validating.
* @param lineReader
* The CsvReader that will be used to return fields, created with
* the appropriate delimiter and data source.
* @param minFields
* The minimum number of fields permitted in an observation line.
* @param maxFields
* The maximum number of fields permitted in an observation line.
* @param valflagPatternStr
* A regex pattern representing the alternations of permitted
* valflags for this validator instance, e.g. COMMON_VALFLAG_PATTERN
* @param fieldInfoSource
* A mapping from field name to field index that makes sense for
* the source.
*/
public CommonTextFormatValidator(String desc, CsvReader lineReader,
int minFields, int maxFields, String valflagPatternStr,
IFieldInfoSource fieldInfoSource) throws IOException {
this.lineReader = lineReader;
this.fieldSplitter = new ObservationFieldSplitter(lineReader,
minFields, maxFields);
this.fieldIndexMap = fieldInfoSource.getFieldIndexMap();
this.julianDayValidator = new JulianDayValidator();
this.magnitudeFieldValidator = new MagnitudeFieldValidator();
this.uncertaintyValueValidator = new UncertaintyValueValidator(
new InclusiveRangePredicate(0, 1));
this.observerCodeValidator = new ObserverCodeValidator();
this.valflagValidator = new ValflagValidator(valflagPatternStr);
this.fields = null;
}
/**
* Attempt to read the next record, returning whether it was.
*
* @return Whether the next record was read.
* @throws IOException
* If a read error occurred.
*/
public boolean next() throws IOException {
return lineReader.readRecord();
}
/**
* Return the current raw record.
*
* @return The current raw record.
*/
public String getRawRecord() {
return lineReader.getRawRecord();
}
/**
* Validate an observation line and either return a ValidObservation
* instance, or throw an exception indicating the error.
*
* Uncertainty, observer code, and valflag fields are optional. The
* uncertainty field may be present however, whether or not the magnitude
* field has a ":" (meaning 'uncertain') suffix.
*
* @param line
* The line of text to be tokenised and validated.
* @return The validated ValidObservation object or null if one could not be
* created from the current record's fields.
*/
public ValidObservation validate() throws IOException,
ObservationValidationError, ObservationValidationWarning {
ValidObservation observation = null;
// Get an array of fields split on the expected delimiter.
fields = fieldSplitter.getFields();
if (fields.length != 0) {
// Create a new valid observation, making the assumption
// that validation will pass.
observation = new ValidObservation();
// Validate the fields.
DateInfo dateInfo = julianDayValidator
.validate(fields[fieldIndexMap.get("JD_FIELD")]);
observation.setDateInfo(dateInfo);
Magnitude magnitude = magnitudeFieldValidator
.validate(fields[fieldIndexMap.get("MAGNITUDE_FIELD")]);
Double uncertaintyMag = uncertaintyValueValidator
.validate(fields[fieldIndexMap.get("UNCERTAINTY_FIELD")]);
if (uncertaintyMag != null) {
magnitude.setUncertainty(uncertaintyMag);
}
if (magnitude.isBrighterThan()) {
throw new ObservationValidationError(
"Was '>' intended (brighter than) or '<'?");
}
observation.setMagnitude(magnitude);
if (observation.getBand() == null) {
observation.setBand(SeriesType.Unspecified);
}
observation
.setObsCode(observerCodeValidator
.validate(fields[fieldIndexMap
.get("OBSERVER_CODE_FIELD")]));
String valflag = fields[fieldIndexMap.get("VALFLAG_FIELD")];
observation.setValidationType(valflagValidator.validate(valflag));
}
return observation;
}
}