Changeset 30766 in osm


Ignore:
Timestamp:
2014-10-27T23:30:49+01:00 (10 years ago)
Author:
donvip
Message:

[josm-merge_overlap] fix #josm10668 - ClassCastException while merging ways

Location:
applications/editors/josm/plugins/merge-overlap
Files:
2 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/merge-overlap/build.xml

    r30714 r30766  
    44    <property name="commit.message" value="MergeOverlap: help shortcut parser, rebuild"/>
    55    <!-- enter the *lowest* JOSM version this plugin is currently compatible with -->
    6     <property name="plugin.main.version" value="7610"/>
     6    <property name="plugin.main.version" value="7661"/>
    77   
    88    <!-- Configure these properties (replace "..." accordingly).
  • applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/MergeOverlapAction.java

    r30713 r30766  
    602602                if (askForMergeTag(ways) || duplicateParentRelations(ways)) {
    603603                        dialog.setVisible(true);
    604                         if (dialog.isCancelled())
     604                        if (dialog.isCanceled())
    605605                                throw new UserCancelException();
    606606                }
  • applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/hack/MyCombinePrimitiveResolverDialog.java

    r30714 r30766  
    4343import org.openstreetmap.josm.gui.conflict.tags.RelationMemberConflictDecision;
    4444import org.openstreetmap.josm.gui.conflict.tags.RelationMemberConflictDecisionType;
     45import org.openstreetmap.josm.gui.conflict.tags.RelationMemberConflictResolver;
    4546import org.openstreetmap.josm.gui.conflict.tags.TagConflictResolver;
    4647import org.openstreetmap.josm.gui.conflict.tags.TagConflictResolverModel;
    4748import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
    4849import org.openstreetmap.josm.gui.help.HelpUtil;
     50import org.openstreetmap.josm.gui.util.GuiHelper;
    4951import org.openstreetmap.josm.tools.ImageProvider;
    5052import org.openstreetmap.josm.tools.WindowGeometry;
     
    5557 *
    5658 * There is a singleton instance of this dialog which can be retrieved using
    57  * {@see #getInstance()}.
     59 * {@link #getInstance()}.
    5860 *
    5961 * The dialog uses two models: one  for resolving tag conflicts, the other
    6062 * for resolving conflicts in relation memberships. For both models there are accessors,
    61  * i.e {@see #getTagConflictResolverModel()} and {@see #getRelationMemberConflictResolverModel()}.
     63 * i.e {@link #getTagConflictResolverModel()} and {@link #getRelationMemberConflictResolverModel()}.
    6264 *
    6365 * Models have to be <strong>populated</strong> before the dialog is launched. Example:
     
    7072 *
    7173 * You should also set the target primitive which other primitives (ways or nodes) are
    72  * merged to, see {@see #setTargetPrimitive(OsmPrimitive)}.
     74 * merged to, see {@link #setTargetPrimitive(OsmPrimitive)}.
    7375 *
    74  * After the dialog is closed use {@see #isCancelled()} to check whether the user canceled
    75  * the dialog. If it wasn't canceled you may build a collection of {@see Command} objects
     76 * After the dialog is closed use {@link #isCanceled()} to check whether the user canceled
     77 * the dialog. If it wasn't canceled you may build a collection of {@link Command} objects
    7678 * which reflect the conflict resolution decisions the user made in the dialog:
    77  * see {@see #buildResolutionCommands()}
    78  *
    79  *
     79 * see {@link #buildResolutionCommands()}
    8080 */
    8181public class MyCombinePrimitiveResolverDialog extends JDialog {
    8282
    8383    /** the unique instance of the dialog */
    84     static private MyCombinePrimitiveResolverDialog instance;
     84    private static MyCombinePrimitiveResolverDialog instance;
    8585
    8686    /**
     
    9191    public static MyCombinePrimitiveResolverDialog getInstance() {
    9292        if (instance == null) {
    93             instance = new MyCombinePrimitiveResolverDialog(Main.parent);
     93            GuiHelper.runInEDTAndWait(new Runnable() {
     94                @Override public void run() {
     95                    instance = new MyCombinePrimitiveResolverDialog(Main.parent);
     96                }
     97            });
    9498        }
    9599        return instance;
     
    98102    private AutoAdjustingSplitPane spTagConflictTypes;
    99103    private TagConflictResolver pnlTagConflictResolver;
    100     private MyRelationMemberConflictResolver pnlRelationMemberConflictResolver;
    101     private boolean cancelled;
     104    private RelationMemberConflictResolver pnlRelationMemberConflictResolver;
     105    private boolean canceled;
    102106    private JPanel pnlButtons;
    103107    private OsmPrimitive targetPrimitive;
     
    119123
    120124    /**
    121      * Sets the primitive the collection of primitives is merged or combined
    122      * to.
     125     * Sets the primitive the collection of primitives is merged or combined to.
    123126     *
    124127     * @param primitive the target primitive
    125128     */
    126     public void setTargetPrimitive(OsmPrimitive primitive) {
     129    public void setTargetPrimitive(final OsmPrimitive primitive) {
    127130        this.targetPrimitive = primitive;
    128         updateTitle();
    129         if (primitive instanceof Way) {
    130             pnlRelationMemberConflictResolver.initForWayCombining();
    131         } else if (primitive instanceof Node) {
    132             pnlRelationMemberConflictResolver.initForNodeMerging();
    133         }
     131        GuiHelper.runInEDTAndWait(new Runnable() {
     132            @Override public void run() {
     133                updateTitle();
     134                if (primitive instanceof Way) {
     135                    pnlRelationMemberConflictResolver.initForWayCombining();
     136                } else if (primitive instanceof Node) {
     137                    pnlRelationMemberConflictResolver.initForNodeMerging();
     138                }
     139            }
     140        });
    134141    }
    135142
     
    152159    }
    153160
    154     protected void build() {
     161    protected final void build() {
    155162        getContentPane().setLayout(new BorderLayout());
    156163        updateTitle();
     
    169176
    170177    protected JPanel buildRelationMemberConflictResolverPanel() {
    171         pnlRelationMemberConflictResolver = new MyRelationMemberConflictResolver();
     178        pnlRelationMemberConflictResolver = new RelationMemberConflictResolver(new MyRelationMemberConflictResolverModel());
    172179        return pnlRelationMemberConflictResolver;
    173180    }
    174181
    175182    protected JPanel buildButtonPanel() {
    176         JPanel pnl = new JPanel();
    177         pnl.setLayout(new FlowLayout(FlowLayout.CENTER));
     183        JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER));
    178184
    179185        // -- apply button
     
    196202    }
    197203
    198     public MyCombinePrimitiveResolverDialog(Component owner) {
    199         super(JOptionPane.getFrameForComponent(owner), ModalityType.DOCUMENT_MODAL);
     204    /**
     205     * Constructs a new {@code MyCombinePrimitiveResolverDialog}.
     206     * @param parent The parent component in which this dialog will be displayed.
     207     */
     208    public MyCombinePrimitiveResolverDialog(Component parent) {
     209        super(JOptionPane.getFrameForComponent(parent), ModalityType.DOCUMENT_MODAL);
    200210        build();
    201211    }
    202212
     213    /**
     214     * Replies the tag conflict resolver model.
     215     * @return The tag conflict resolver model.
     216     */
    203217    public TagConflictResolverModel getTagConflictResolverModel() {
    204218        return pnlTagConflictResolver.getModel();
    205219    }
    206220
     221    /**
     222     * Replies the relation membership conflict resolver model.
     223     * @return The relation membership conflict resolver model.
     224     */
    207225    public MyRelationMemberConflictResolverModel getRelationMemberConflictResolverModel() {
    208         return pnlRelationMemberConflictResolver.getModel();
     226        return (MyRelationMemberConflictResolverModel) pnlRelationMemberConflictResolver.getModel();
    209227    }
    210228
     
    230248
    231249        TagCollection allResolutions = getTagConflictResolverModel().getAllResolutions();
    232         if (allResolutions.size() > 0) {
     250        if (!allResolutions.isEmpty()) {
    233251            cmds.addAll(buildTagChangeCommand(targetPrimitive, allResolutions));
    234252        }
     
    279297    }
    280298
     299    /**
     300     * Prepares the default decisions for populated tag and relation membership conflicts.
     301     */
    281302    public void prepareDefaultDecisions() {
    282303        prepareDefaultTagDecisions();
     
    285306
    286307    protected JPanel buildEmptyConflictsPanel() {
    287         JPanel pnl = new JPanel();
    288         pnl.setLayout(new BorderLayout());
     308        JPanel pnl = new JPanel(new BorderLayout());
    289309        pnl.add(new JLabel(tr("No conflicts to resolve")));
    290310        return pnl;
     
    297317
    298318        if (relModel.getNumDecisions() > 0 && tagModel.getNumDecisions() > 0) {
    299             // display both, the dialog for resolving relation conflicts and for resolving
    300             // tag conflicts
     319            // display both, the dialog for resolving relation conflicts and for resolving tag conflicts
    301320            spTagConflictTypes.setTopComponent(pnlTagConflictResolver);
    302321            spTagConflictTypes.setBottomComponent(pnlRelationMemberConflictResolver);
     
    304323        } else if (relModel.getNumDecisions() > 0) {
    305324            // relation conflicts only
    306             //
    307325            getContentPane().add(pnlRelationMemberConflictResolver, BorderLayout.CENTER);
    308326        } else if (tagModel.getNumDecisions() > 0) {
    309327            // tag conflicts only
    310             //
    311328            getContentPane().add(pnlTagConflictResolver, BorderLayout.CENTER);
    312329        } else {
     
    324341    }
    325342
    326     protected void setCancelled(boolean cancelled) {
    327         this.cancelled = cancelled;
    328     }
    329 
    330     public boolean isCancelled() {
    331         return cancelled;
     343    protected void setCanceled(boolean canceled) {
     344        this.canceled = canceled;
     345    }
     346
     347    /**
     348     * Determines if this dialog has been cancelled.
     349     * @return true if this dialog has been cancelled, false otherwise.
     350     */
     351    public boolean isCanceled() {
     352        return canceled;
    332353    }
    333354
     
    338359            new WindowGeometry(getClass().getName() + ".geometry", WindowGeometry.centerInWindow(Main.parent,
    339360                    new Dimension(600, 400))).applySafe(this);
    340             setCancelled(false);
     361            setCanceled(false);
    341362            btnApply.requestFocusInWindow();
    342363        } else if (isShowing()) { // Avoid IllegalComponentStateException like in #8775
     
    357378        @Override
    358379        public void actionPerformed(ActionEvent arg0) {
    359             setCancelled(true);
     380            setCanceled(true);
    360381            setVisible(false);
    361382        }
     
    377398        }
    378399
    379         protected void updateEnabledState() {
     400        protected final void updateEnabledState() {
    380401            setEnabled(pnlTagConflictResolver.getModel().getNumConflicts() == 0
    381402                    && pnlRelationMemberConflictResolver.getModel().getNumConflicts() == 0);
  • applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/hack/MyRelationMemberConflictResolverModel.java

    r30714 r30766  
    22package mergeoverlap.hack;
    33
    4 import java.beans.PropertyChangeListener;
    5 import java.beans.PropertyChangeSupport;
    6 import java.util.ArrayList;
    74import java.util.Collection;
    8 import java.util.HashSet;
    95import java.util.LinkedList;
    106import java.util.List;
    117import java.util.Map;
    12 import java.util.Set;
    13 
    14 import javax.swing.table.DefaultTableModel;
    158
    169import mergeoverlap.MergeOverlapAction;
    1710
     11import org.openstreetmap.josm.command.Command;
    1812import org.openstreetmap.josm.data.osm.OsmPrimitive;
    1913import org.openstreetmap.josm.data.osm.Relation;
    2014import org.openstreetmap.josm.data.osm.RelationMember;
    21 import org.openstreetmap.josm.data.osm.RelationToChildReference;
    2215import org.openstreetmap.josm.data.osm.Way;
    2316import org.openstreetmap.josm.gui.conflict.tags.RelationMemberConflictDecision;
    24 import org.openstreetmap.josm.gui.conflict.tags.RelationMemberConflictDecisionType;
    25 import org.openstreetmap.josm.gui.util.GuiHelper;
     17import org.openstreetmap.josm.gui.conflict.tags.RelationMemberConflictResolverModel;
    2618
    2719/**
     
    3022 * It can be used as {@link javax.swing.table.TableModel}.
    3123 */
    32 public class MyRelationMemberConflictResolverModel extends DefaultTableModel {
     24public class MyRelationMemberConflictResolverModel extends RelationMemberConflictResolverModel {
    3325    /** the property name for the number conflicts managed by this model */
    3426    public static final String NUM_CONFLICTS_PROP = MyRelationMemberConflictResolverModel.class.getName() + ".numConflicts";
    3527
    36     /** the list of conflict decisions */
    37     private List<RelationMemberConflictDecision> decisions;
    38     /** the collection of relations for which we manage conflicts */
    39     private Collection<Relation> relations;
    40     /** the number of conflicts */
    41     private int numConflicts;
    42     private PropertyChangeSupport support;
    43 
    44     /**
    45      * Replies true if each {@link MultiValueResolutionDecision} is decided.
    46      *
    47      * @return true if each {@link MultiValueResolutionDecision} is decided; false
    48      * otherwise
    49      */
    50     public boolean isResolvedCompletely() {
    51         return numConflicts == 0;
     28    @Override
     29    protected String getProperty() {
     30        return NUM_CONFLICTS_PROP;
    5231    }
    53 
    54     /**
    55      * Replies the current number of conflicts
    56      *
    57      * @return the current number of conflicts
    58      */
    59     public int getNumConflicts() {
    60         return numConflicts;
    61     }
    62 
    63     /**
    64      * Updates the current number of conflicts from list of decisions and emits
    65      * a property change event if necessary.
    66      *
    67      */
    68     protected void updateNumConflicts() {
    69         int count = 0;
    70         for (RelationMemberConflictDecision decision: decisions) {
    71             if (!decision.isDecided()) {
    72                 count++;
    73             }
    74         }
    75         int oldValue = numConflicts;
    76         numConflicts = count;
    77         if (numConflicts != oldValue) {
    78             support.firePropertyChange(NUM_CONFLICTS_PROP, oldValue, numConflicts);
    79         }
    80     }
    81 
    82     public void addPropertyChangeListener(PropertyChangeListener l) {
    83         support.addPropertyChangeListener(l);
    84     }
    85 
    86     public void removePropertyChangeListener(PropertyChangeListener l) {
    87         support.removePropertyChangeListener(l);
    88     }
    89 
    90     public MyRelationMemberConflictResolverModel() {
    91         decisions = new ArrayList<>();
    92         support = new PropertyChangeSupport(this);
    93     }
    94 
     32   
    9533    @Override
    96     public int getRowCount() {
    97         return getNumDecisions();
    98     }
    99 
    100     @Override
    101     public Object getValueAt(int row, int column) {
    102         if (decisions == null) return null;
    103 
    104         RelationMemberConflictDecision d = decisions.get(row);
    105         switch(column) {
    106         case 0: /* relation */ return d.getRelation();
    107         case 1: /* pos */ return Integer.toString(d.getPos() + 1); // position in "user space" starting at 1
    108         case 2: /* role */ return d.getRole();
    109         case 3: /* original */ return d.getOriginalPrimitive();
    110         case 4: /* decision */ return d.getDecision();
    111         }
    112         return null;
    113     }
    114 
    115     @Override
    116     public void setValueAt(Object value, int row, int column) {
    117         RelationMemberConflictDecision d = decisions.get(row);
    118         switch(column) {
    119         case 2: /* role */
    120             d.setRole((String)value);
    121             break;
    122         case 4: /* decision */
    123             d.decide((RelationMemberConflictDecisionType)value);
    124             refresh();
    125             break;
    126         }
    127         fireTableDataChanged();
     34    protected void populate(Relation relation, OsmPrimitive primitive) {
     35        throw new UnsupportedOperationException("Use populate(Relation, OsmPrimitive, Map<Way, Way>) instead");
    12836    }
    12937
     
    14149            }
    14250        }
     51    }
     52
     53    @Override
     54    public void populate(Collection<Relation> relations, Collection<? extends OsmPrimitive> memberPrimitives) {
     55        throw new UnsupportedOperationException("Use populate(Collection<Relation>, Collection<? extends OsmPrimitive>, Map<Way, Way>) instead");
    14356    }
    14457
     
    16376    }
    16477
    165     /**
    166      * Populates the model with the relation members represented as a collection of
    167      * {@link RelationToChildReference}s.
    168      *
    169      * @param references the references. Empty list assumed if null.
    170      */
    171     public void populate(Collection<RelationToChildReference> references) {
    172         references = references == null ? new LinkedList<RelationToChildReference>() : references;
    173         decisions.clear();
    174         this.relations = new HashSet<>(references.size());
    175         for (RelationToChildReference reference: references) {
    176             decisions.add(new RelationMemberConflictDecision(reference.getParent(), reference.getPosition()));
    177             relations.add(reference.getParent());
    178         }
    179         refresh();
    180     }
    181 
    182     /**
    183      * Replies the decision at position <code>row</code>
    184      *
    185      * @param row
    186      * @return the decision at position <code>row</code>
    187      */
    188     public RelationMemberConflictDecision getDecision(int row) {
    189         return decisions.get(row);
    190     }
    191 
    192     /**
    193      * Replies the number of decisions managed by this model
    194      *
    195      * @return the number of decisions managed by this model
    196      */
    197     public int getNumDecisions() {
    198         return decisions == null ? 0 : decisions.size();
    199     }
    200 
    201     /**
    202      * Refreshes the model state. Invoke this method to trigger necessary change
    203      * events after an update of the model data.
    204      *
    205      */
    206     public void refresh() {
    207         updateNumConflicts();
    208         GuiHelper.runInEDTAndWait(new Runnable() {
    209             @Override public void run() {
    210                 fireTableDataChanged();
    211             }
    212         });
    213     }
    214 
    215     /**
    216      * Apply a role to all member managed by this model.
    217      *
    218      * @param role the role. Empty string assumed if null.
    219      */
    220     public void applyRole(String role) {
    221         role = role == null ? "" : role;
    222         for (RelationMemberConflictDecision decision : decisions) {
    223             decision.setRole(role);
    224         }
    225         refresh();
    226     }
    227 
    228     protected RelationMemberConflictDecision getDecision(Relation relation, int pos) {
    229         for(RelationMemberConflictDecision decision: decisions) {
    230             if (decision.matches(relation, pos)) return decision;
    231         }
    232         return null;
     78    @Override
     79    protected Command buildResolveCommand(Relation relation, OsmPrimitive newPrimitive) {
     80        throw new UnsupportedOperationException("Use buildResolveCorrespondance(Relation, OsmPrimitive, Map<Relation, Relation>, Map<Way, Way>) instead");
    23381    }
    23482
     
    23886        Relation modifiedRelation = MergeOverlapAction.getNew(relation, newRelations);
    23987        modifiedRelation.setMembers(null);
    240 //      boolean isChanged = false;
    24188        for (int i=0; i < relationsMembers.size(); i++) {
    24289                RelationMember rm = relationsMembers.get(i);
    243 //          RelationMember rm = relation.getMember(i);
    244 //          RelationMember rmNew;
    24590            RelationMemberConflictDecision decision = getDecision(relation, i);
    24691            if (decision == null) {
    24792                modifiedRelation.addMember(rm);
    24893            } else {
    249                 System.out.println(modifiedRelation);
    250                 System.out.println(111);
    25194                switch(decision.getDecision()) {
    25295                case KEEP:
    253 //                  modifiedRelation.removeMembersFor(newPrimitive);
    254                         System.out.println(222);
    25596                        if (newPrimitive instanceof Way) {
    25697                        modifiedRelation.addMember(new RelationMember(decision.getRole(), MergeOverlapAction.getOld((Way)newPrimitive, oldWays)));
     
    259100                                modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));
    260101                        }
    261 //                  modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));
    262102                    break;
    263103                case REMOVE:
    264                         System.out.println(333);
    265 //                  modifiedRelation.removeMembersFor(rm.getMember());
    266 //                  isChanged = true;
    267104                    // do nothing
    268105                    break;
     
    275112    }
    276113
     114    @Override
     115    public List<Command> buildResolutionCommands(OsmPrimitive newPrimitive) {
     116        throw new UnsupportedOperationException("Use buildRelationCorrespondance(OsmPrimitive, Map<Relation, Relation>, Map<Way, Way>) instead");
     117    }
     118
    277119    /**
    278120     * Builds a collection of commands executing the decisions made in this model.
     
    280122     * @param newPrimitive the primitive which members shall refer to if the
    281123     * decision is {@see RelationMemberConflictDecisionType#REPLACE}
    282      * @return a list of commands
    283124     */
    284125    public void buildRelationCorrespondance(OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
     
    287128        }
    288129    }
    289 
    290     protected boolean isChanged(Relation relation, OsmPrimitive newPrimitive) {
    291         for (int i=0; i < relation.getMembersCount(); i++) {
    292             RelationMemberConflictDecision decision = getDecision(relation, i);
    293             if (decision == null) {
    294                 continue;
    295             }
    296             switch(decision.getDecision()) {
    297             case REMOVE: return true;
    298             case KEEP:
    299                 if (!relation.getMember(i).getRole().equals(decision.getRole()))
    300                     return true;
    301                 if (relation.getMember(i).getMember() != newPrimitive)
    302                     return true;
    303             case UNDECIDED:
    304                 // FIXME: handle error
    305             }
    306         }
    307         return false;
    308     }
    309 
    310     /**
    311      * Replies the set of relations which have to be modified according
    312      * to the decisions managed by this model.
    313      *
    314      * @param newPrimitive the primitive which members shall refer to if the
    315      * decision is {@see RelationMemberConflictDecisionType#REPLACE}
    316      *
    317      * @return the set of relations which have to be modified according
    318      * to the decisions managed by this model
    319      */
    320     public Set<Relation> getModifiedRelations(OsmPrimitive newPrimitive) {
    321         HashSet<Relation> ret = new HashSet<>();
    322         for (Relation relation: relations) {
    323             if (isChanged(relation, newPrimitive)) {
    324                 ret.add(relation);
    325             }
    326         }
    327         return ret;
    328     }
    329130}
Note: See TracChangeset for help on using the changeset viewer.