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),
019    /** Way type */
020    WAY(marktr(/* ICON(data/) */"way"), Way.class, WayData.class),
021    /** Relation type */
022    RELATION(marktr(/* ICON(data/) */"relation"), Relation.class, RelationData.class),
023
024    /** Closed way: only for display, no real type */
025    CLOSEDWAY(marktr(/* ICON(data/) */"closedway"), null, WayData.class),
026    /** Multipolygon: only for display, no real type */
027    MULTIPOLYGON(marktr(/* ICON(data/) */"multipolygon"), null, RelationData.class);
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
035    OsmPrimitiveType(String apiTypeName, Class<? extends OsmPrimitive> osmClass, Class<? extends PrimitiveData> dataClass) {
036        this.apiTypeName = apiTypeName;
037        this.osmClass = osmClass;
038        this.dataClass = dataClass;
039    }
040
041    /**
042     * Returns the API type name / JOSM display name.
043     * @return the API type name / JOSM display name
044     */
045    public String getAPIName() {
046        return apiTypeName;
047    }
048
049    /**
050     * Returns the OSM class for data values, or null.
051     * @return the OSM class for data values, or null
052     */
053    public Class<? extends OsmPrimitive> getOsmClass() {
054        return osmClass;
055    }
056
057    /**
058     * Returns the data class.
059     * @return the data class
060     */
061    public Class<? extends PrimitiveData> getDataClass() {
062        return dataClass;
063    }
064
065    /**
066     * Returns enum value from API type name / JOSM display name, case sensitive.
067     * @param typeName API type name / JOSM display name, case sensitive
068     * @return matching enum value
069     * @throws IllegalArgumentException if the type name does not match any valid type
070     * @see #from(String)
071     */
072    public static OsmPrimitiveType fromApiTypeName(String typeName) {
073        for (OsmPrimitiveType type : OsmPrimitiveType.values()) {
074            if (type.getAPIName().equals(typeName)) return type;
075        }
076        throw new IllegalArgumentException(MessageFormat.format(
077                "Parameter ''{0}'' is not a valid type name. Got ''{1}''.", "typeName", typeName));
078    }
079
080    /**
081     * Determines the OSM primitive type of the given object.
082     * @param obj the OSM object to inspect
083     * @return the OSM primitive type of {@code obj}
084     * @throws IllegalArgumentException if {@code obj} is null or of unknown type
085     */
086    public static OsmPrimitiveType from(IPrimitive obj) {
087        if (obj instanceof INode) return NODE;
088        if (obj instanceof IWay) return WAY;
089        if (obj instanceof IRelation) return RELATION;
090        throw new IllegalArgumentException("Unknown type: "+obj);
091    }
092
093    /**
094     * Returns enum value from API type name / JOSM display name, case insensitive.
095     * @param value API type name / JOSM display name, case insensitive
096     * @return matching enum value or null
097     * @see #fromApiTypeName
098     */
099    public static OsmPrimitiveType from(String value) {
100        for (OsmPrimitiveType type: values()) {
101            if (type.getAPIName().equalsIgnoreCase(value))
102                return type;
103        }
104        return null;
105    }
106
107    /**
108     * Returns the values matching real OSM API data types (node, way, relation).
109     * @return the values matching real OSM API data types (node, way, relation)
110     */
111    public static Collection<OsmPrimitiveType> dataValues() {
112        return DATA_VALUES;
113    }
114
115    /**
116     * Constructs a new primitive instance (node, way or relation) without version.
117     * @param uniqueId the unique id
118     * @param allowNegative {@code true} to allow negative id
119     * @return a new primitive instance (node, way or relation)
120     * @throws IllegalArgumentException if uniqueId &lt; 0 and allowNegative is false
121     */
122    public OsmPrimitive newInstance(long uniqueId, boolean allowNegative) {
123        switch (this) {
124        case NODE:
125            return new Node(uniqueId, allowNegative);
126        case WAY:
127            return new Way(uniqueId, allowNegative);
128        case RELATION:
129            return new Relation(uniqueId, allowNegative);
130        default:
131            throw new AssertionError();
132        }
133    }
134
135    /**
136     * Constructs a new primitive instance (node, way or relation) with given version.
137     * @param id The id. Must be &gt;= 0
138     * @param version The version
139     * @return a new primitive instance (node, way or relation) with given version
140     * @throws IllegalArgumentException if id &lt; 0
141     * @since 12018
142     */
143    public OsmPrimitive newVersionedInstance(long id, int version) {
144        switch (this) {
145        case NODE:
146            return new Node(id, version);
147        case WAY:
148            return new Way(id, version);
149        case RELATION:
150            return new Relation(id, version);
151        default:
152            throw new AssertionError();
153        }
154    }
155
156    @Override
157    public String toString() {
158        return tr(getAPIName());
159    }
160}