All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.wselwood.mpcreader.MinorPlanetReaderBuilder Maven / Gradle / Ivy

There is a newer version: 0.1.1
Show newest version
package com.wselwood.mpcreader;

import com.wselwood.mpcreader.columns.*;
import com.wselwood.mpcreader.modifiers.ArcLengthModifier;
import com.wselwood.mpcreader.modifiers.Modifier;
import com.wselwood.mpcreader.modifiers.RadianModifier;
import com.wselwood.mpcreader.modifiers.YearOfObservationModifier;

import java.io.*;
import java.util.*;
import java.util.zip.GZIPInputStream;

/**
 * Simple builder pattern to create a minor planet reader.
 *
 * Mainly done this way so we can add more options in later with out having to make breaking changes to the api.
 *
 * Created by wselwood on 27/04/14.
 */
public class MinorPlanetReaderBuilder {


    private File target = null;

    private Boolean compressed = null;

    private boolean convertToRaidians = false;

    private final List columns = new ArrayList<>();
    private final List modifiers = new ArrayList<>();
    private final Map values = new HashMap<>();


    /**
     * Create a new builder. Builders are one shot and should not be reused.
     */
    public MinorPlanetReaderBuilder() {

    }

    /**
     * select the file for the reader to open.
     * @param f the file to open.
     */
    public MinorPlanetReaderBuilder open(File f) {
        target = f;
        return this;
    }

    public MinorPlanetReaderBuilder compressed() {
        compressed = true;
        return this;
    }

    public MinorPlanetReaderBuilder unCompressed() {
        compressed = false;
        return this;
    }

    /**
     * Should angles in the file be converted to radians.
     */
    public MinorPlanetReaderBuilder convertAngles() {
        convertToRaidians = true;
        return this;
    }

    /**
     * Construct the final MinorPlanetReader.
     *
     * Once this has been called this class should not be reused.
     *
     * @return the reader.
     * @throws IOException if there is any problem opening the file.
     */
    public MinorPlanetReader build() throws IOException {

        if(compressed == null) {
            detectCompression();
        }

        buildColumns();
        buildModifiers();
        return new MinorPlanetReader(target, compressed, columns, modifiers, values);
    }

    /**
     * look for the gzip magic number at the start of the file
     * @throws IOException
     */
    private void detectCompression() throws IOException {
        try(FileInputStream bufferedReader = new FileInputStream(target)) {
            byte[] buffer = new byte[3];
            int bytesRead = bufferedReader.read(buffer);
            if(bytesRead != 3) {
                throw new IOException("File appears to be empty");
            }
            // is there a gzip flag on the front.
            compressed = buffer[0] == 31 && buffer[1] == -117;
        }
    }


    // see http://www.minorplanetcenter.net/iau/info/MPOrbitFormat.html
    // column list indexes from 1. need to index from zero for java buffer access.
    // fortran F77 definitions
    // a7 ascii seven characters.
    // f5.2 floating point number five digits long (including the point) two decimal places.
    // f9.5 floating point number nine digits long, five decimal places.
    // i4 integer four digits long.
    private void buildColumns() {

        Container container = new Container<>();
        values.put(ColumnNames.MPC_NUMBER, container);
        columns.add(new PackedIdentifierColumn(0, 6, container));

        addDouble(ColumnNames.MPC_MAGNITUDE,                8, 13);
        addDouble(ColumnNames.MPC_SLOPE,                    14, 19);
        addPackedDate(ColumnNames.MPC_EPOCH,                20, 25);
        addDouble(ColumnNames.MPC_MEAN_ANOMALY_EPOCH,       26, 35);
        addDouble(ColumnNames.MPC_ARGUMENT_OF_PERIHELION,   37, 46);
        addDouble(ColumnNames.MPC_LONGITUDE,                48, 57);
        addDouble(ColumnNames.MPC_INCLINATION,              59, 68);
        addDouble(ColumnNames.MPC_ECCENTRICITY,             70, 79);
        addDouble(ColumnNames.MPC_MOTION,                   80, 91);
        addDouble(ColumnNames.MPC_SEMIMAJOR_AXIS,           92, 103);
        addString(ColumnNames.MPC_UNCERTAINTY,              105, 106);
        addString(ColumnNames.MPC_REFERENCE,                107, 116);
        addInt   (ColumnNames.MPC_NUM_OBS,                  117, 122, false);
        addInt   (ColumnNames.MPC_NUM_OPPS,                 123, 126, false);
        addString(ColumnNames.MPC_OPPOSITION,               127, 136);  // process this later it depends on the parameter above.
        addDouble(ColumnNames.MPC_RESIDUAL,                 137, 141);
        addString(ColumnNames.MPC_COARSE_PERTURBERS,        142, 145);
        addString(ColumnNames.MPC_PRECISE_PERTURBERS,       146, 149);
        addString(ColumnNames.MPC_COMPUTER_NAME,            150, 160);
        addInt   (ColumnNames.MPC_FLAGS,                    161, 165, true);
        addString(ColumnNames.MPC_DESIGNATION,              166, 194);
        addDate  (ColumnNames.MPC_LAST_OBS,                 194, 202, "yyyyMMdd");

    }

    private void buildModifiers() {
        // add the two modifiers needed to take care of the opposition information.
        Container firstYear = new Container<>();
        Container lastYear = new Container<>();
        Modifier year = new YearOfObservationModifier(
                values.get(ColumnNames.MPC_NUM_OPPS),
                values.get(ColumnNames.MPC_OPPOSITION),
                firstYear,
                lastYear
                );

        values.put(ColumnNames.MPC_FIRST_YEAR, firstYear);
        values.put(ColumnNames.MPC_LAST_YEAR, lastYear);
        modifiers.add(year);

        Container arcLength = new Container<>();
        Modifier arcLengthMod = new ArcLengthModifier(
                values.get(ColumnNames.MPC_NUM_OPPS),
                values.get(ColumnNames.MPC_OPPOSITION),
                arcLength
        );
        values.put(ColumnNames.MPC_ARC_LENGTH, arcLength);
        modifiers.add(arcLengthMod);

        // now if they are needed add the modifiers for converting to radians
        if(convertToRaidians) {
            modifiers.add(new RadianModifier(values.get(ColumnNames.MPC_MEAN_ANOMALY_EPOCH)));
            modifiers.add(new RadianModifier(values.get(ColumnNames.MPC_ARGUMENT_OF_PERIHELION)));
            modifiers.add(new RadianModifier(values.get(ColumnNames.MPC_LONGITUDE)));
            modifiers.add(new RadianModifier(values.get(ColumnNames.MPC_INCLINATION)));
            modifiers.add(new RadianModifier(values.get(ColumnNames.MPC_MOTION)));
        }
    }

    private void addString(String name, int start, int end) {
        Container container = new Container<>();
        values.put(name, container);
        columns.add(new TextColumn(start, end, container));
    }

    private void addDouble(String name, int start, int end) {
        Container container = new Container<>();
        values.put(name, container);
        columns.add(new FloatColumn(start, end, container));
    }

    private void addInt(String name, int start, int end, boolean hex) {
        Container container = new Container<>();
        values.put(name, container);
        if(hex) {
            columns.add(new HexColumn(start, end, container));
        }
        else {
            columns.add(new IntColumn(start, end, container));
        }
    }

    private void addDate(String name, int start, int end, String format) {
        Container container = new Container<>();
        values.put(name, container);
        columns.add(new DateColumn(start, end, format, container));
    }

    private void addPackedDate(String name, int start, int end) {
        Container container = new Container<>();
        values.put(name, container);
        columns.add(new PackedDateColumn(start, end, container));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy