001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.osm;
003
004import java.io.Serializable;
005import java.util.ArrayList;
006import java.util.List;
007import java.util.regex.Matcher;
008import java.util.regex.Pattern;
009
010public class SimplePrimitiveId implements PrimitiveId, Serializable {
011    private final long id;
012    private final OsmPrimitiveType type;
013
014    public static final Pattern ID_PATTERN = Pattern.compile("((n(ode)?|w(ay)?|r(el(ation)?)?)/?)(\\d+)");
015
016    public SimplePrimitiveId(long id, OsmPrimitiveType type) {
017        this.id = id;
018        this.type = type;
019    }
020
021    @Override
022    public OsmPrimitiveType getType() {
023        return type;
024    }
025
026    @Override
027    public long getUniqueId() {
028        return id;
029    }
030
031    @Override
032    public boolean isNew() {
033        return id <= 0;
034    }
035
036    @Override
037    public int hashCode() {
038        final int prime = 31;
039        int result = 1;
040        result = prime * result + (int) (id ^ (id >>> 32));
041        result = prime * result + ((type == null) ? 0 : type.hashCode());
042        return result;
043    }
044
045    @Override
046    public boolean equals(Object obj) {
047        if (this == obj)
048            return true;
049        if (obj == null)
050            return false;
051        if (getClass() != obj.getClass())
052            return false;
053        SimplePrimitiveId other = (SimplePrimitiveId) obj;
054        if (id != other.id)
055            return false;
056        if (type == null) {
057            if (other.type != null)
058                return false;
059        } else if (!type.equals(other.type))
060            return false;
061        return true;
062    }
063
064    @Override
065    public String toString() {
066        return type + " " + id;
067    }
068
069    /**
070     * Parses a {@code SimplePrimitiveId} from the string {@code s}.
071     * @param s the string to be parsed, e.g., {@code n1}, {@code node1},
072     * {@code w1}, {@code way1}, {@code r1}, {@code rel1}, {@code relation1}.
073     * @return the parsed {@code SimplePrimitiveId}
074     * @throws IllegalArgumentException if the string does not match the pattern
075     */
076    public static SimplePrimitiveId fromString(String s) {
077        final Matcher m = ID_PATTERN.matcher(s);
078        if (m.matches()) {
079            return new SimplePrimitiveId(Long.parseLong(m.group(m.groupCount())),
080                    s.charAt(0) == 'n'
081                            ? OsmPrimitiveType.NODE
082                            : s.charAt(0) == 'w'
083                            ? OsmPrimitiveType.WAY
084                            : OsmPrimitiveType.RELATION);
085        } else {
086            throw new IllegalArgumentException("The string " + s + " does not match the pattern " + ID_PATTERN);
087        }
088    }
089
090    /**
091     * Attempts to parse extract any primitive id from the string {@code s}.
092     * @param s the string to be parsed, e.g., {@code n1, w1}, {@code node1 and rel2}.
093     * @return the parsed list of {@code OsmPrimitiveType}s.
094     */
095    public static List<SimplePrimitiveId> fuzzyParse(String s) {
096        final ArrayList<SimplePrimitiveId> ids = new ArrayList<>();
097        final Matcher m = ID_PATTERN.matcher(s);
098        while (m.find()) {
099            final char firstChar = s.charAt(m.start());
100            ids.add(new SimplePrimitiveId(Long.parseLong(m.group(m.groupCount())),
101                    firstChar == 'n'
102                            ? OsmPrimitiveType.NODE
103                            : firstChar == 'w'
104                            ? OsmPrimitiveType.WAY
105                            : OsmPrimitiveType.RELATION));
106        }
107        return ids;
108    }
109}