001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import java.io.IOException;
005import java.io.ObjectInputStream;
006import java.io.ObjectOutputStream;
007import java.io.Serializable;
008import java.util.ArrayList;
009import java.util.Arrays;
010import java.util.Collection;
011import java.util.List;
012import java.util.Map;
013
014/**
015 * This class can be used to save properties of OsmPrimitive.
016 *
017 * The main difference between PrimitiveData
018 * and OsmPrimitive is that PrimitiveData is not part of the dataset and changes in PrimitiveData are not
019 * reported by events
020 */
021public abstract class PrimitiveData extends AbstractPrimitive implements Serializable {
022
023    private static final long serialVersionUID = -1044837092478109138L;
024
025    /**
026     * Constructs a new {@code PrimitiveData}.
027     */
028    public PrimitiveData() {
029        this(OsmPrimitive.generateUniqueId());
030    }
031
032    /**
033     * Constructs a new {@code PrimitiveData} with given id.
034     * @param id id
035     * @since 12017
036     */
037    public PrimitiveData(long id) {
038        this.id = id;
039    }
040
041    /**
042     * Constructs a new {@code PrimitiveData} from an existing one.
043     * @param data the data to copy
044     */
045    public PrimitiveData(PrimitiveData data) {
046        cloneFrom(data);
047    }
048
049    /**
050     * Sets the primitive identifier.
051     * @param id primitive identifier
052     */
053    public void setId(long id) {
054        this.id = id;
055    }
056
057    /**
058     * Sets the primitive version.
059     * @param version primitive version
060     */
061    public void setVersion(int version) {
062        this.version = version;
063    }
064
065    /**
066     * override to make it public
067     */
068    @Override
069    public void setIncomplete(boolean incomplete) {
070        super.setIncomplete(incomplete);
071    }
072
073    /**
074     * Returns a copy of this primitive data.
075     * @return a copy of this primitive data
076     */
077    public abstract PrimitiveData makeCopy();
078
079    @Override
080    public String toString() {
081        StringBuilder builder = new StringBuilder();
082        builder.append(id).append(' ').append(Arrays.toString(keys)).append(' ').append(getFlagsAsString());
083        return builder.toString();
084    }
085
086    /**
087     * Returns a filtered list for a given primitive type.
088     * @param <T> primitive type
089     * @param list list to filter
090     * @param type primitive type
091     * @return a filtered list for given primitive type
092     */
093    @SuppressWarnings("unchecked")
094    public static <T extends PrimitiveData> List<T> getFilteredList(Collection<T> list, OsmPrimitiveType type) {
095        List<T> ret = new ArrayList<>();
096        for (PrimitiveData p: list) {
097            if (type.getDataClass().isInstance(p)) {
098                ret.add((T) p);
099            }
100        }
101        return ret;
102    }
103
104    @Override
105    protected final void keysChangedImpl(Map<String, String> originalKeys) {
106    }
107
108    private void writeObject(ObjectOutputStream oos) throws IOException {
109        // since super class is not Serializable
110        oos.writeLong(id);
111        oos.writeLong(user == null ? -1 : user.getId());
112        oos.writeInt(version);
113        oos.writeInt(changesetId);
114        oos.writeInt(timestamp);
115        oos.writeObject(keys);
116        oos.writeShort(flags);
117        oos.defaultWriteObject();
118    }
119
120    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
121        // since super class is not Serializable
122        id = ois.readLong();
123        final long userId = ois.readLong();
124        user = userId == -1 ? null : User.getById(userId);
125        version = ois.readInt();
126        changesetId = ois.readInt();
127        timestamp = ois.readInt();
128        keys = (String[]) ois.readObject();
129        flags = ois.readShort();
130        ois.defaultReadObject();
131    }
132}