Changes in / [7499:7505] in josm


Ignore:
Location:
/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • /trunk/data/tagging-preset.xsd

    r7499 r7505  
    8686        </complexType>
    8787
    88     <complexType name="chunk">
    89         <sequence>
    90             <choice minOccurs="1" maxOccurs="unbounded">
    91                 <group ref="tns:optional_elements" />
    92                 <element name="key" type="tns:key" />
    93                 <element name="optional" type="tns:optional" minOccurs="0" />
    94             </choice>
    95         </sequence>
    96         <attribute name="id" type="ID" use="required" />
    97     </complexType>
    98 
    99     <complexType name="reference">
    100         <attribute name="ref" type="IDREF" use="required" />
    101     </complexType>
    102 
    103     <group name="optional_elements">
     88        <complexType name="chunk">
     89                <choice minOccurs="1" maxOccurs="1">
     90                        <sequence>
     91                                <choice minOccurs="1" maxOccurs="unbounded">
     92                                        <group ref="tns:optional_elements" />
     93                                        <element name="key" type="tns:key" />
     94                                        <element name="optional" type="tns:optional" minOccurs="0" />
     95                                </choice>
     96                        </sequence>
     97                        <sequence>
     98                                <!-- Cannot use tns:list_elements here because reference is present both in optional_elements and list_elements
     99                                so it violates cos-nonambig: Unique Particle Attribution :
     100                                <group ref="tns:list_elements" minOccurs="1" maxOccurs="unbounded" />-->
     101                                <element name="list_entry" type="tns:list_entry" minOccurs="1" maxOccurs="unbounded" />
     102                        </sequence>
     103                </choice>
     104                <attribute name="id" type="ID" use="required" />
     105        </complexType>
     106
     107        <complexType name="reference">
     108                <attribute name="ref" type="IDREF" use="required" />
     109        </complexType>
     110
     111        <group name="optional_elements">
    104112                <choice>
    105113                        <element name="label" type="tns:label" />
     
    117125        </group>
    118126
     127        <group name="list_elements">
     128                <choice>
     129                        <element name="list_entry" type="tns:list_entry" />
     130                        <element name="reference" type="tns:reference" />
     131                </choice>
     132        </group>
     133
    119134        <complexType name="key">
    120135                <attribute name="key" type="string" use="required" />
     
    122137                <attribute name="match" type="string" />
    123138        </complexType>
    124 
    125139
    126140        <complexType name="link">
     
    179193                <!-- use either list_entry's or a combination of values/display_values -->
    180194                <sequence>
    181                         <element name="list_entry" type="tns:list_entry" minOccurs="0" maxOccurs="unbounded" />
     195                        <group ref="tns:list_elements" minOccurs="0" maxOccurs="unbounded" />
    182196                </sequence>
    183197                <attribute name="key" type="string" use="required" />
     
    207221                <!-- use either list_entry's or a combination of values/display_values -->
    208222                <sequence>
    209                         <element name="list_entry" type="tns:list_entry" minOccurs="0" maxOccurs="unbounded" />
     223                        <group ref="tns:list_elements" minOccurs="0" maxOccurs="unbounded" />
    210224                </sequence>
    211225                <attribute name="key" type="string" use="required" />
     
    216230                <attribute name="values_context" type="string" />
    217231                <attribute name="display_values" type="string" />
    218         <attribute name="values_searchable" type="boolean" />
     232                <attribute name="values_searchable" type="boolean" />
    219233                <attribute name="default" type="string" />
    220234                <attribute name="use_last_as_default" type="tns:last_default" />
     
    247261                <attribute name="value_on" type="string" />
    248262                <attribute name="value_off" type="string" />
    249         <attribute name="disable_off" type="boolean" />
     263                <attribute name="disable_off" type="boolean" />
    250264                <attribute name="match" type="tns:match" />
    251265
  • /trunk/src/org/openstreetmap/josm/data/osm/DataSet.java

    r7499 r7505  
    102102    private static final int MAX_EVENTS = 1000;
    103103
    104     private Storage<OsmPrimitive> allPrimitives = new Storage<>(new Storage.PrimitiveIdHash(), true);
    105     private Map<PrimitiveId, OsmPrimitive> primitivesMap = allPrimitives.foreignKey(new Storage.PrimitiveIdHash());
    106     private CopyOnWriteArrayList<DataSetListener> listeners = new CopyOnWriteArrayList<>();
     104    private final Storage<OsmPrimitive> allPrimitives = new Storage<>(new Storage.PrimitiveIdHash(), true);
     105    private final Map<PrimitiveId, OsmPrimitive> primitivesMap = allPrimitives.foreignKey(new Storage.PrimitiveIdHash());
     106    private final CopyOnWriteArrayList<DataSetListener> listeners = new CopyOnWriteArrayList<>();
    107107
    108108    // provide means to highlight map elements that are not osm primitives
     
    257257     * conversion of the whole DataSet by iterating over this data structure.
    258258     */
    259     private QuadBuckets<Node> nodes = new QuadBuckets<>();
     259    private final QuadBuckets<Node> nodes = new QuadBuckets<>();
    260260
    261261    private <T extends OsmPrimitive> Collection<T> getPrimitives(Predicate<OsmPrimitive> predicate) {
     
    287287
    288288    /**
     289     * Determines if the given node can be retrieved in the data set through its bounding box. Useful for dataset consistency test.
     290     * For efficiency reasons this method does not lock the dataset, you have to lock it manually.
     291     *
     292     * @param n The node to search
     293     * @return {@code true} if {@code n} ban be retrieved in this data set, {@code false} otherwise
     294     * @since 7501
     295     */
     296    public boolean containsNode(Node n) {
     297        return nodes.contains(n);
     298    }
     299
     300    /**
    289301     * All ways (Streets etc.) in the DataSet.
    290302     *
    291303     * The way nodes are stored only in the way list.
    292304     */
    293     private QuadBuckets<Way> ways = new QuadBuckets<>();
     305    private final QuadBuckets<Way> ways = new QuadBuckets<>();
    294306
    295307    /**
     
    317329
    318330    /**
     331     * Determines if the given way can be retrieved in the data set through its bounding box. Useful for dataset consistency test.
     332     * For efficiency reasons this method does not lock the dataset, you have to lock it manually.
     333     *
     334     * @param w The way to search
     335     * @return {@code true} if {@code w} ban be retrieved in this data set, {@code false} otherwise
     336     * @since 7501
     337     */
     338    public boolean containsWay(Way w) {
     339        return ways.contains(w);
     340    }
     341
     342    /**
    319343     * All relations/relationships
    320344     */
    321     private Collection<Relation> relations = new ArrayList<>();
     345    private final Collection<Relation> relations = new ArrayList<>();
    322346
    323347    /**
     
    349373            lock.readLock().unlock();
    350374        }
     375    }
     376
     377    /**
     378     * Determines if the given relation can be retrieved in the data set through its bounding box. Useful for dataset consistency test.
     379     * For efficiency reasons this method does not lock the dataset, you have to lock it manually.
     380     *
     381     * @param r The relation to search
     382     * @return {@code true} if {@code r} ban be retrieved in this data set, {@code false} otherwise
     383     * @since 7501
     384     */
     385    public boolean containsRelation(Relation r) {
     386        return relations.contains(r);
    351387    }
    352388
  • /trunk/src/org/openstreetmap/josm/data/osm/DatasetConsistencyTest.java

    r7499 r7505  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.data.osm;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
    35
    46import java.io.PrintWriter;
     
    68import java.io.Writer;
    79
    8 import org.openstreetmap.josm.data.coor.LatLon;
     10import org.openstreetmap.josm.Main;
     11import org.openstreetmap.josm.tools.Utils;
    912
    1013/**
    11  * This class can be used to run consistency tests on dataset. Any errors found will be written to provided PrintWriter
     14 * This class can be used to run consistency tests on dataset. Any errors found will be written to provided PrintWriter.
    1215 * <br>
    13  * Texts here should not be translated because they're not intended for users but for josm developers
    14  *
     16 * Texts here should not be translated because they're not intended for users but for josm developers.
     17 * @since 2500
    1518 */
    1619public class DatasetConsistencyTest {
     
    2124    private int errorCount;
    2225
     26    /**
     27     * Constructs a new {@code DatasetConsistencyTest}.
     28     * @param dataSet The dataset to test
     29     * @param writer The writer used to write results
     30     */
    2331    public DatasetConsistencyTest(DataSet dataSet, Writer writer) {
    2432        this.dataSet = dataSet;
     
    3341    }
    3442
     43    /**
     44     * Checks that parent primitive is referred from its child members
     45     */
    3546    public void checkReferrers() {
     47        long startTime = System.currentTimeMillis();
    3648        // It's also error when referred primitive's dataset is null but it's already covered by referredPrimitiveNotInDataset check
    37         for (Way way:dataSet.getWays()) {
     49        for (Way way : dataSet.getWays()) {
    3850            if (!way.isDeleted()) {
    39                 for (Node n:way.getNodes()) {
     51                for (Node n : way.getNodes()) {
    4052                    if (n.getDataSet() != null && !n.getReferrers().contains(way)) {
    4153                        printError("WAY NOT IN REFERRERS", "%s is part of %s but is not in referrers", n, way);
     
    4557        }
    4658
    47         for (Relation relation:dataSet.getRelations()) {
     59        for (Relation relation : dataSet.getRelations()) {
    4860            if (!relation.isDeleted()) {
    49                 for (RelationMember m:relation.getMembers()) {
     61                for (RelationMember m : relation.getMembers()) {
    5062                    if (m.getMember().getDataSet() != null && !m.getMember().getReferrers().contains(relation)) {
    5163                        printError("RELATION NOT IN REFERRERS", "%s is part of %s but is not in referrers", m.getMember(), relation);
     
    5466            }
    5567        }
    56     }
    57 
     68        printElapsedTime(startTime);
     69    }
     70
     71    /**
     72     * Checks for womplete ways with incomplete nodes.
     73     */
    5874    public void checkCompleteWaysWithIncompleteNodes() {
    59         for (Way way:dataSet.getWays()) {
     75        long startTime = System.currentTimeMillis();
     76        for (Way way : dataSet.getWays()) {
    6077            if (way.isUsable()) {
    61                 for (Node node:way.getNodes()) {
     78                for (Node node : way.getNodes()) {
    6279                    if (node.isIncomplete()) {
    6380                        printError("USABLE HAS INCOMPLETE", "%s is usable but contains incomplete node '%s'", way, node);
     
    6683            }
    6784        }
    68     }
    69 
     85        printElapsedTime(startTime);
     86    }
     87
     88    /**
     89     * Checks for complete nodes without coordinates.
     90     */
    7091    public void checkCompleteNodesWithoutCoordinates() {
    71         for (Node node:dataSet.getNodes()) {
     92        long startTime = System.currentTimeMillis();
     93        for (Node node : dataSet.getNodes()) {
    7294            if (!node.isIncomplete() && node.isVisible() && (node.getCoor() == null || node.getEastNorth() == null)) {
    7395                printError("COMPLETE WITHOUT COORDINATES", "%s is not incomplete but has null coordinates", node);
    7496            }
    7597        }
    76     }
    77 
     98        printElapsedTime(startTime);
     99    }
     100
     101    /**
     102     * Checks that nodes can be retrieved through their coordinates.
     103     */
    78104    public void searchNodes() {
    79         for (Node n:dataSet.getNodes()) {
    80             if (!n.isIncomplete() && !n.isDeleted()) {
    81                 LatLon c = n.getCoor();
    82                 if (c != null) {
    83                     BBox box = c.toBBox(0.0001);
    84                     if (!dataSet.searchNodes(box).contains(n)) {
    85                         printError("SEARCH NODES", "%s not found using Dataset.searchNodes()", n);
    86                     }
    87                 }
    88             }
    89         }
    90     }
    91 
     105        long startTime = System.currentTimeMillis();
     106        dataSet.getReadLock().lock();
     107        try {
     108            for (Node n : dataSet.getNodes()) {
     109                // Call isDrawable() as an efficient replacement to previous checks (!deleted, !incomplete, getCoor() != null)
     110                if (n.isDrawable() && !dataSet.containsNode(n)) {
     111                    printError("SEARCH NODES", "%s not found using Dataset.containsNode()", n);
     112                }
     113            }
     114        } finally {
     115            dataSet.getReadLock().unlock();
     116        }
     117        printElapsedTime(startTime);
     118    }
     119
     120    /**
     121     * Checks that ways can be retrieved through their bounding box.
     122     */
    92123    public void searchWays() {
    93         for (Way w:dataSet.getWays()) {
    94             if (!w.isIncomplete() && !w.isDeleted() && w.getNodesCount() >= 2 && !dataSet.searchWays(w.getBBox()).contains(w)) {
    95                 printError("SEARCH WAYS", "%s not found using Dataset.searchWays()", w);
    96             }
    97         }
     124        long startTime = System.currentTimeMillis();
     125        dataSet.getReadLock().lock();
     126        try {
     127            for (Way w : dataSet.getWays()) {
     128                if (!w.isIncomplete() && !w.isDeleted() && w.getNodesCount() >= 2 && !dataSet.containsWay(w)) {
     129                    printError("SEARCH WAYS", "%s not found using Dataset.containsWay()", w);
     130                }
     131            }
     132        } finally {
     133            dataSet.getReadLock().unlock();
     134        }
     135        printElapsedTime(startTime);
    98136    }
    99137
     
    112150    }
    113151
     152    /**
     153     * Checks that referred primitives are present in dataset.
     154     */
    114155    public void referredPrimitiveNotInDataset() {
    115         for (Way way:dataSet.getWays()) {
    116             for (Node node:way.getNodes()) {
     156        long startTime = System.currentTimeMillis();
     157        for (Way way : dataSet.getWays()) {
     158            for (Node node : way.getNodes()) {
    117159                checkReferredPrimitive(node, way);
    118160            }
    119161        }
    120162
    121         for (Relation relation:dataSet.getRelations()) {
    122             for (RelationMember member:relation.getMembers()) {
     163        for (Relation relation : dataSet.getRelations()) {
     164            for (RelationMember member : relation.getMembers()) {
    123165                checkReferredPrimitive(member.getMember(), relation);
    124166            }
    125167        }
    126     }
    127 
    128 
     168        printElapsedTime(startTime);
     169    }
     170
     171    /**
     172     * Checks for zero and one-node ways.
     173     */
    129174    public void checkZeroNodesWays() {
    130         for (Way way:dataSet.getWays()) {
     175        long startTime = System.currentTimeMillis();
     176        for (Way way : dataSet.getWays()) {
    131177            if (way.isUsable() && way.getNodesCount() == 0) {
    132178                printError("WARN - ZERO NODES", "Way %s has zero nodes", way);
     
    135181            }
    136182        }
    137     }
    138 
     183        printElapsedTime(startTime);
     184    }
     185
     186    private void printElapsedTime(long startTime) {
     187        if (Main.isDebugEnabled()) {
     188            StackTraceElement item = Thread.currentThread().getStackTrace()[2];
     189            String operation = getClass().getSimpleName() + "." + item.getMethodName();
     190            long elapsedTime = System.currentTimeMillis() - startTime;
     191            Main.debug(tr("Test ''{0}'' completed in {1}",
     192                    operation, Utils.getDurationString(elapsedTime)));
     193        }
     194    }
     195
     196    /**
     197     * Runs test.
     198     */
    139199    public void runTest() {
    140200        try {
     201            long startTime = System.currentTimeMillis();
    141202            referredPrimitiveNotInDataset();
    142203            checkReferrers();
     
    146207            searchWays();
    147208            checkZeroNodesWays();
     209            printElapsedTime(startTime);
    148210            if (errorCount > MAX_ERRORS) {
    149211                writer.println((errorCount - MAX_ERRORS) + " more...");
    150212            }
     213
    151214        } catch (Exception e) {
    152215            writer.println("Exception during dataset integrity test:");
     
    155218    }
    156219
     220    /**
     221     * Runs test on the given dataset.
     222     * @param dataSet the dataset to test
     223     * @return the errors as string
     224     */
    157225    public static String runTests(DataSet dataSet) {
    158226        StringWriter writer = new StringWriter();
     
    160228        return writer.toString();
    161229    }
    162 
    163230}
  • /trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPresetItems.java

    r7499 r7505  
    592592        private JComponent value;
    593593
    594         @Override public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel, boolean presetInitiallyMatches) {
     594        @Override
     595        public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel, boolean presetInitiallyMatches) {
    595596
    596597            // find out if our key is already used in the selection.
     
    602603                initAutoCompletionField(textField, key);
    603604            }
     605            textField.setHint(key);
    604606            if (length != null && !length.isEmpty()) {
    605607                textField.setMaxChars(Integer.valueOf(length));
     
    12191221            AutoCompletingTextField tf = new AutoCompletingTextField();
    12201222            initAutoCompletionField(tf, key);
     1223            tf.setHint(key);
    12211224            if (length != null && !length.isEmpty()) {
    12221225                tf.setMaxChars(Integer.valueOf(length));
  • /trunk/src/org/openstreetmap/josm/gui/widgets/JosmTextField.java

    r7499 r7505  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.widgets;
     3
     4import java.awt.Color;
     5import java.awt.FontMetrics;
     6import java.awt.Graphics;
     7import java.awt.Graphics2D;
     8import java.awt.Insets;
     9import java.awt.RenderingHints;
     10import java.awt.event.FocusEvent;
     11import java.awt.event.FocusListener;
    312
    413import javax.swing.JTextField;
     
    615
    716/**
    8  * Subclass of {@link JTextField} that adds a "native" context menu (cut/copy/paste/select all).
     17 * Subclass of {@link JTextField} that adds a "native" context menu (cut/copy/paste/select all)
     18 * and an optional "hint" displayed when no text has been entered.
    919 * @since 5886
    1020 */
    11 public class JosmTextField extends JTextField {
     21public class JosmTextField extends JTextField implements FocusListener {
     22
     23    private String hint;
    1224
    1325    /**
     
    3446            setMinimumSize(getPreferredSize());
    3547        }
     48        addFocusListener(this);
    3649    }
    3750
     
    8497        this(null, null, 0);
    8598    }
     99
     100    /**
     101     * Replies the hint displayed when no text has been entered.
     102     * @return the hint
     103     * @since 7505
     104     */
     105    public final String getHint() {
     106        return hint;
     107    }
     108
     109    /**
     110     * Sets the hint to display when no text has been entered.
     111     * @param hint the hint to set
     112     * @since 7505
     113     */
     114    public final void setHint(String hint) {
     115        this.hint = hint;
     116    }
     117
     118    @Override
     119    public void paint(Graphics g) {
     120        super.paint(g);
     121        if (hint != null && !hint.isEmpty() && getText().isEmpty() && !isFocusOwner()) {
     122            // Taken from http://stackoverflow.com/a/24571681/2257172
     123            int h = getHeight();
     124            ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
     125            Insets ins = getInsets();
     126            FontMetrics fm = g.getFontMetrics();
     127            int c0 = getBackground().getRGB();
     128            int c1 = getForeground().getRGB();
     129            int m = 0xfefefefe;
     130            int c2 = ((c0 & m) >>> 1) + ((c1 & m) >>> 1);
     131            g.setColor(new Color(c2, true));
     132            g.drawString(hint, ins.left, h / 2 + fm.getAscent() / 2 - 2);
     133        }
     134    }
     135
     136    @Override
     137    public void focusGained(FocusEvent e) {
     138        repaint();
     139    }
     140
     141    @Override
     142    public void focusLost(FocusEvent e) {
     143        repaint();
     144    }
    86145}
Note: See TracChangeset for help on using the changeset viewer.