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

de.hpi.isg.profiledb.ProfileDB Maven / Gradle / Ivy

package de.hpi.isg.profiledb;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import de.hpi.isg.profiledb.store.json.MeasurementDeserializer;
import de.hpi.isg.profiledb.store.json.MeasurementSerializer;
import de.hpi.isg.profiledb.store.model.Experiment;
import de.hpi.isg.profiledb.store.model.Measurement;
import de.hpi.isg.profiledb.store.model.TimeMeasurement;

import java.io.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;

/**
 * This class provides facilities to save and load {@link Experiment}s.
 */
public class ProfileDB {

    /**
     * Maintains a list of {@link Class}es for {@link Measurement}s. Required for deserialization.
     */
    private List> measurementClasses = new LinkedList<>();

    /**
     * Maintains actions to preparate {@link Gson}.
     */
    private List> gsonPreparationSteps = new LinkedList<>();

    /**
     * Maintains a {@link Gson} object for efficiency. It will be dropped on changes, though.
     */
    private Gson gson;

    /**
     * Register a {@link Measurement} type. This is required before being able to load that type.
     *
     * @param measurementClass the {@link Measurement} {@link Class}
     * @return this instance
     */
    public ProfileDB registerMeasurementClass(Class measurementClass) {
        this.measurementClasses.add(measurementClass);
        this.gson = null;
        return this;
    }

    /**
     * Apply any changes necessary to {@link Gson} so that it can be used for de/serialization of custom objects.
     *
     * @param preparation a preparatory step performed on a {@link GsonBuilder}
     * @return this instance
     */
    public ProfileDB withGsonPreparation(Consumer preparation) {
        this.gsonPreparationSteps.add(preparation);
        this.gson = null;
        return this;
    }

    /**
     * Provide a {@link Gson} object.
     *
     * @return the {@link Gson} object
     */
    private Gson getGson() {
        if (this.gson == null) {
            MeasurementSerializer measurementSerializer = new MeasurementSerializer();
            MeasurementDeserializer measurementDeserializer = new MeasurementDeserializer();
            this.measurementClasses.forEach(measurementDeserializer::register);
            final GsonBuilder gsonBuilder = new GsonBuilder()
                    .registerTypeAdapter(Measurement.class, measurementDeserializer)
                    .registerTypeAdapter(Measurement.class, measurementSerializer);
            this.gsonPreparationSteps.forEach(step -> step.accept(gsonBuilder));
            this.gson = gsonBuilder.create();
        }
        return this.gson;
    }

    /**
     * Creates a new instance.
     */
    public ProfileDB() {
        this.measurementClasses.add(TimeMeasurement.class);
    }

    /**
     * Load {@link Experiment}s from a {@link File}.
     *
     * @param file the {@link File}
     * @return the {@link Experiment}s
     */
    public Collection load(File file) throws IOException {
        return load(new FileInputStream(file));
    }

    /**
     * Load {@link Experiment}s from an {@link InputStream}.
     *
     * @param inputStream the {@link InputStream}
     * @return the {@link Experiment}s
     */
    public Collection load(InputStream inputStream) throws IOException {
        try {
            return load(new BufferedReader(new InputStreamReader(inputStream, "UTF-8")));
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Unexpectedly, UTF-8 is not supported.");
        }
    }

    /**
     * Load {@link Experiment}s from an {@link Reader}.
     *
     * @param reader the {@link Reader}
     * @return the {@link Experiment}s
     */
    public Collection load(BufferedReader reader) throws IOException {
        Collection experiments = new LinkedList<>();
        Gson gson = this.getGson();
        String line;
        while ((line = reader.readLine()) != null) {
            Experiment experiment = gson.fromJson(line, Experiment.class);
            experiments.add(experiment);
        }
        return experiments;
    }

    /**
     * Write {@link Experiment}s to a {@link File}. Existing file contents will be overwritten.
     *
     * @param file        the {@link File}
     * @param experiments the {@link Experiment}s
     * @throws IOException if the writing fails
     */
    public void save(File file, Collection experiments) throws IOException {
        file.getAbsoluteFile().getParentFile().mkdirs();
        try (FileOutputStream fos = new FileOutputStream(file, false)) {
            this.save(experiments, fos);
        }
    }

    /**
     * Write {@link Experiment}s to a {@link File}. Existing file contents will be overwritten.
     *
     * @param file        the {@link File}
     * @param experiments the {@link Experiment}s
     * @throws IOException if the writing fails
     */
    public void save(File file, Experiment... experiments) throws IOException {
        this.save(file, Arrays.asList(experiments));
    }

    /**
     * Append {@link Experiment}s to a {@link File}. Existing file contents will be preserved.
     *
     * @param file        the {@link File}
     * @param experiments the {@link Experiment}s
     * @throws IOException if the writing fails
     */
    public void append(File file, Collection experiments) throws IOException {
        file.getAbsoluteFile().getParentFile().mkdirs();
        try (FileOutputStream fos = new FileOutputStream(file, true)) {
            this.save(experiments, fos);
        }
    }

    /**
     * Append {@link Experiment}s to a {@link File}. Existing file contents will be preserved.
     *
     * @param file        the {@link File}
     * @param experiments the {@link Experiment}s
     * @throws IOException if the writing fails
     */
    public void append(File file, Experiment... experiments) throws IOException {
        this.append(file, Arrays.asList(experiments));
    }

    /**
     * Write {@link Experiment}s to an {@link OutputStream}.
     *
     * @param outputStream the {@link OutputStream}
     */
    public void save(Collection experiments, OutputStream outputStream) throws IOException {
        try {
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
            this.save(experiments, writer);
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Unexpectedly, UTF-8 is not supported.");
        }
    }

    /**
     * Write {@link Experiment}s to a {@link Writer}.
     *
     * @param writer the {@link Writer}
     */
    public void save(Collection experiments, Writer writer) throws IOException {
        try {
            Gson gson = this.getGson();
            for (Experiment experiment : experiments) {
                gson.toJson(experiment, writer);
                writer.append('\n');
            }
            writer.flush();
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("Unexpectedly, UTF-8 is not supported.");
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy