001/*
002 * Copyright (c) 2015-2020, Oracle and/or its affiliates. All rights reserved.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.tribuo.provenance;
018
019import com.oracle.labs.mlrg.olcut.provenance.ObjectProvenance;
020import com.oracle.labs.mlrg.olcut.provenance.Provenance;
021import com.oracle.labs.mlrg.olcut.provenance.primitives.DateTimeProvenance;
022import com.oracle.labs.mlrg.olcut.provenance.primitives.StringProvenance;
023import com.oracle.labs.mlrg.olcut.util.Pair;
024import org.tribuo.DataSource;
025import org.tribuo.Output;
026import org.tribuo.OutputFactory;
027
028import java.time.OffsetDateTime;
029import java.util.ArrayList;
030import java.util.Iterator;
031import java.util.Map;
032import java.util.Objects;
033
034/**
035 * This class stores a String describing the data source, along with a
036 * timestamp. It should not be used except for simple demos, or machine
037 * created data. It is vastly preferable to create a {@link DataSource}
038 * implementation with a specific provenance, rather than using this
039 * to construct an empty {@link org.tribuo.MutableDataset}.
040 */
041public class SimpleDataSourceProvenance implements DataSourceProvenance {
042    private static final long serialVersionUID = 1L;
043
044    public static final String DESCRIPTION = "description";
045
046    private final String className = DataSource.class.getName();
047
048    private final StringProvenance description;
049    private final DateTimeProvenance creationTime;
050    private final OutputFactoryProvenance outputFactoryProvenance;
051
052    /**
053     * This constructor initialises the provenance using the current time in the system timezone.
054     * @param description The description of the data.
055     * @param outputFactory The output factory used to process it.
056     * @param <T> The type of the output.
057     */
058    public <T extends Output<T>> SimpleDataSourceProvenance(String description, OutputFactory<T> outputFactory) {
059        this(description,OffsetDateTime.now(),outputFactory);
060    }
061
062    /**
063     * This constructor initialises the provenance using the supplied description, time and output factory.
064     * @param description The description of the data.
065     * @param creationTime The time the data was created or processed.
066     * @param outputFactory The output factory used to process it.
067     * @param <T> The type of the output.
068     */
069    public <T extends Output<T>> SimpleDataSourceProvenance(String description, OffsetDateTime creationTime, OutputFactory<T> outputFactory) {
070        this.description = new StringProvenance(DESCRIPTION,description);
071        this.creationTime = new DateTimeProvenance(DATASOURCE_CREATION_TIME,creationTime);
072        this.outputFactoryProvenance = outputFactory.getProvenance();
073    }
074
075    /**
076     * Used for provenance deserialization.
077     * @param map The provenance elements.
078     */
079    public SimpleDataSourceProvenance(Map<String,Provenance> map) {
080        this.description = ObjectProvenance.checkAndExtractProvenance(map,DESCRIPTION,StringProvenance.class,SimpleDataSourceProvenance.class.getSimpleName());
081        this.creationTime = ObjectProvenance.checkAndExtractProvenance(map,DATASOURCE_CREATION_TIME,DateTimeProvenance.class,SimpleDataSourceProvenance.class.getSimpleName());
082        this.outputFactoryProvenance = ObjectProvenance.checkAndExtractProvenance(map,OUTPUT_FACTORY,OutputFactoryProvenance.class,SimpleDataSourceProvenance.class.getSimpleName());
083    }
084
085    @Override
086    public boolean equals(Object o) {
087        if (this == o) return true;
088        if (!(o instanceof SimpleDataSourceProvenance)) return false;
089        SimpleDataSourceProvenance pairs = (SimpleDataSourceProvenance) o;
090        return className.equals(pairs.className) &&
091                description.equals(pairs.description) &&
092                creationTime.equals(pairs.creationTime) &&
093                outputFactoryProvenance.equals(pairs.outputFactoryProvenance);
094    }
095
096    @Override
097    public int hashCode() {
098        return Objects.hash(className, description, creationTime, outputFactoryProvenance);
099    }
100
101    @Override
102    public String getClassName() {
103        return className;
104    }
105
106    @Override
107    public Iterator<Pair<String, Provenance>> iterator() {
108        ArrayList<Pair<String,Provenance>> list = new ArrayList<>();
109
110        list.add(new Pair<>(DESCRIPTION,description));
111        list.add(new Pair<>(OUTPUT_FACTORY,outputFactoryProvenance));
112        list.add(new Pair<>(DATASOURCE_CREATION_TIME,creationTime));
113
114        return list.iterator();
115    }
116
117    @Override
118    public String toString() {
119        return generateString("DataSource");
120    }
121}