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    public String getAPIName() {
042        return apiTypeName;
043    }
044
045    public Class<? extends OsmPrimitive> getOsmClass() {
046        return osmClass;
047    }
048
049    public Class<? extends PrimitiveData> getDataClass() {
050        return dataClass;
051    }
052
053    public static OsmPrimitiveType fromApiTypeName(String typeName) {
054        for (OsmPrimitiveType type : OsmPrimitiveType.values()) {
055            if (type.getAPIName().equals(typeName)) return type;
056        }
057        throw new IllegalArgumentException(MessageFormat.format(
058                "Parameter ''{0}'' is not a valid type name. Got ''{1}''.", "typeName", typeName));
059    }
060
061    /**
062     * Determines the OSM primitive type of the given object.
063     * @param obj the OSM object to inspect
064     * @return the OSM primitive type of {@code obj}
065     * @throws IllegalArgumentException if {@code obj} is null or of unknown type
066     */
067    public static OsmPrimitiveType from(IPrimitive obj) {
068        if (obj instanceof INode) return NODE;
069        if (obj instanceof IWay) return WAY;
070        if (obj instanceof IRelation) return RELATION;
071        throw new IllegalArgumentException("Unknown type: "+obj);
072    }
073
074    public static OsmPrimitiveType from(String value) {
075        if (value == null) return null;
076        for (OsmPrimitiveType type: values()) {
077            if (type.getAPIName().equalsIgnoreCase(value))
078                return type;
079        }
080        return null;
081    }
082
083    public static Collection<OsmPrimitiveType> dataValues() {
084        return DATA_VALUES;
085    }
086
087    public OsmPrimitive newInstance(long uniqueId, boolean allowNegative) {
088        switch (this) {
089        case NODE:
090            return new Node(uniqueId, allowNegative);
091        case WAY:
092            return new Way(uniqueId, allowNegative);
093        case RELATION:
094            return new Relation(uniqueId, allowNegative);
095        default:
096            throw new AssertionError();
097        }
098    }
099
100    @Override
101    public String toString() {
102        return tr(getAPIName());
103    }
104}