001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import static org.openstreetmap.josm.tools.I18n.marktr;
005import static org.openstreetmap.josm.tools.I18n.tr;
006
007import java.text.MessageFormat;
008import java.util.Arrays;
009import java.util.Collection;
010
011/**
012 * OSM primitive type.
013 * @since 1670
014 */
015public enum OsmPrimitiveType {
016
017    /** Node type */
018    NODE(marktr(/* ICON(data/) */"node"), Node.class, NodeData.class, Node.idGenerator),
019    /** Way type */
020    WAY(marktr(/* ICON(data/) */"way"), Way.class, WayData.class, Way.idGenerator),
021    /** Relation type */
022    RELATION(marktr(/* ICON(data/) */"relation"), Relation.class, RelationData.class, Relation.idGenerator),
023
024    /** Closed way: only for display, no real type */
025    CLOSEDWAY(marktr(/* ICON(data/) */"closedway"), null, WayData.class, Way.idGenerator),
026    /** Multipolygon: only for display, no real type */
027    MULTIPOLYGON(marktr(/* ICON(data/) */"multipolygon"), null, RelationData.class, Relation.idGenerator);
028
029    private static final Collection<OsmPrimitiveType> DATA_VALUES = Arrays.asList(NODE, WAY, RELATION);
030
031    private final String apiTypeName;
032    private final Class<? extends OsmPrimitive> osmClass;
033    private final Class<? extends PrimitiveData> dataClass;
034    @SuppressWarnings("ImmutableEnumChecker")
035    private final UniqueIdGenerator idGenerator;
036
037    OsmPrimitiveType(String apiTypeName, Class<? extends OsmPrimitive> osmClass, Class<? extends PrimitiveData> dataClass,
038            UniqueIdGenerator idGenerator) {
039        this.apiTypeName = apiTypeName;
040        this.osmClass = osmClass;
041        this.dataClass = dataClass;
042        this.idGenerator = idGenerator;
043    }
044
045    /**
046     * Returns the API type name / JOSM display name.
047     * @return the API type name / JOSM display name
048     */
049    public String getAPIName() {
050        return apiTypeName;
051    }
052
053    /**
054     * Returns the OSM class for data values, or null.
055     * @return the OSM class for data values, or null
056     */
057    public Class<? extends OsmPrimitive> getOsmClass() {
058        return osmClass;
059    }
060
061    /**
062     * Returns the data class.
063     * @return the data class
064     */
065    public Class<? extends PrimitiveData> getDataClass() {
066        return dataClass;
067    }
068
069    /**
070     * Returns enum value from API type name / JOSM display name, case sensitive.
071     * @param typeName API type name / JOSM display name, case sensitive
072     * @return matching enum value
073     * @throws IllegalArgumentException if the type name does not match any valid type
074     * @see #from(String)
075     */
076    public static OsmPrimitiveType fromApiTypeName(String typeName) {
077        for (OsmPrimitiveType type : OsmPrimitiveType.values()) {
078            if (type.getAPIName().equals(typeName)) return type;
079        }
080        throw new IllegalArgumentException(MessageFormat.format(
081                "Parameter ''{0}'' is not a valid type name. Got ''{1}''.", "typeName", typeName));
082    }
083
084    /**
085     * Determines the OSM primitive type of the given object.
086     * @param obj the OSM object to inspect
087     * @return the OSM primitive type of {@code obj}
088     * @throws IllegalArgumentException if {@code obj} is null or of unknown type
089     */
090    public static OsmPrimitiveType from(IPrimitive obj) {
091        if (obj instanceof INode) return NODE;
092        if (obj instanceof IWay) return WAY;
093        if (obj instanceof IRelation) return RELATION;
094        throw new IllegalArgumentException("Unknown type: "+obj);
095    }
096
097    /**
098     * Returns enum value from API type name / JOSM display name, case insensitive.
099     * @param value API type name / JOSM display name, case insensitive
100     * @return matching enum value or null
101     * @see #fromApiTypeName
102     */
103    public static OsmPrimitiveType from(String value) {
104        return Arrays.stream(values())
105                .filter(type -> type.getAPIName().equalsIgnoreCase(value))
106                .findFirst().orElse(null);
107    }
108
109    /**
110     * Returns the values matching real OSM API data types (node, way, relation).
111     * @return the values matching real OSM API data types (node, way, relation)
112     */
113    public static Collection<OsmPrimitiveType> dataValues() {
114        return DATA_VALUES;
115    }
116
117    /**
118     * Constructs a new primitive instance (node, way or relation) without version.
119     * @param uniqueId the unique id
120     * @param allowNegative {@code true} to allow negative id
121     * @return a new primitive instance (node, way or relation)
122     * @throws IllegalArgumentException if uniqueId &lt; 0 and allowNegative is false
123     */
124    public OsmPrimitive newInstance(long uniqueId, boolean allowNegative) {
125        switch (this) {
126        case NODE:
127            return new Node(uniqueId, allowNegative);
128        case WAY:
129            return new Way(uniqueId, allowNegative);
130        case RELATION:
131            return new Relation(uniqueId, allowNegative);
132        default:
133            throw new AssertionError();
134        }
135    }
136
137    /**
138     * Constructs a new primitive instance (node, way or relation) with given version.
139     * @param id The id. Must be &gt;= 0
140     * @param version The version
141     * @return a new primitive instance (node, way or relation) with given version
142     * @throws IllegalArgumentException if id &lt; 0
143     * @since 12018
144     */
145    public OsmPrimitive newVersionedInstance(long id, int version) {
146        switch (this) {
147        case NODE:
148            return new Node(id, version);
149        case WAY:
150            return new Way(id, version);
151        case RELATION:
152            return new Relation(id, version);
153        default:
154            throw new AssertionError();
155        }
156    }
157
158    /**
159     * Returns the unique identifier generator.
160     * @return the unique identifier generator
161     * @since 15820
162     */
163    public final UniqueIdGenerator getIdGenerator() {
164        return idGenerator;
165    }
166
167    @Override
168    public String toString() {
169        return tr(getAPIName());
170    }
171}