001 // License: GPL. For details, see LICENSE file.
002 package org.openstreetmap.josm.gui.widgets;
003
004 import static org.openstreetmap.josm.tools.I18n.tr;
005
006 import java.util.ArrayList;
007 import java.util.List;
008 import java.util.StringTokenizer;
009
010 import javax.swing.JTextField;
011 import javax.swing.text.JTextComponent;
012
013 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
014 import org.openstreetmap.josm.data.osm.PrimitiveId;
015 import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
016
017 /**
018 * @author Matthias Julius
019 */
020 public class OsmIdTextField extends JTextField {
021
022 private OsmIdValidator validator;
023
024 public OsmIdTextField() {
025 validator = OsmIdValidator.decorate(this);
026 }
027
028 public void setType(OsmPrimitiveType type) {
029 validator.type = type;
030 }
031
032 /**
033 * Get entered ID list - supports "1,2,3" "1 2 ,3" or even "1 2 3 v2 6 v8"
034 * @return list of id's
035 */
036 public List<PrimitiveId> getIds() {
037 return validator.ids;
038 }
039
040 public boolean readOsmIds() {
041 return validator.readOsmIds();
042 }
043
044 public void performValidation() {
045 validator.validate();
046 }
047
048 public void clearTextIfInvalid() {
049 if (!validator.isValid())
050 setText("");
051 validator.validate();
052 }
053
054 /**
055 * Validator for a changeset ID entered in a {@link JTextComponent}.
056 *
057 */
058 static private class OsmIdValidator extends AbstractTextComponentValidator {
059
060 static public OsmIdValidator decorate(JTextComponent tc) {
061 return new OsmIdValidator(tc);
062 }
063
064 private List<PrimitiveId> ids = new ArrayList<PrimitiveId>();
065 private OsmPrimitiveType type;
066
067 public OsmIdValidator(JTextComponent tc) {
068 super(tc, false);
069 }
070
071 @Override
072 public boolean isValid() {
073 return readOsmIds();
074 }
075
076 @Override
077 public void validate() {
078 if (!isValid()) {
079 feedbackInvalid(tr("The current value is not a valid OSM ID. Please enter an integer value > 0"));
080 } else {
081 feedbackValid(tr("Please enter an integer value > 0"));
082 }
083 }
084
085 public boolean readOsmIds() {
086 String value = getComponent().getText();
087 char c;
088 if (value == null || value.trim().length() == 0) {
089 return false;
090 }
091 ids.clear();
092 StringTokenizer st = new StringTokenizer(value, ",.+/ \t\n");
093 String s;
094 while (st.hasMoreTokens()) {
095 s = st.nextToken();
096 // convert tokens to int skipping v-words (version v2 etc)
097 c = s.charAt(0);
098 if (c == 'v') {
099 continue;
100 } else {
101 try {
102 ids.add(SimplePrimitiveId.fromString(s));
103 } catch (IllegalArgumentException ex) {
104 try {
105 long id = Long.parseLong(s);
106 if (id <= 0) {
107 return false;
108 } else if (type == OsmPrimitiveType.NODE) {
109 ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.NODE));
110 } else if (type == OsmPrimitiveType.WAY) {
111 ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.WAY));
112 } else if (type == OsmPrimitiveType.RELATION) {
113 ids.add(new SimplePrimitiveId(id, OsmPrimitiveType.RELATION));
114 } else {
115 return false;
116 }
117 } catch (IllegalArgumentException ex2) {
118 return false;
119 }
120 }
121 }
122 }
123 return true;
124 }
125 }
126 }