Ignore:
Timestamp:
2014-10-12T12:37:13+02:00 (11 years ago)
Author:
donvip
Message:

[josm_merge_overlap] fix #josm10626 - fix ClassCastException

File:
1 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/hack/MyRelationMemberConflictResolverModel.java

    r30713 r30714  
    2323import org.openstreetmap.josm.gui.conflict.tags.RelationMemberConflictDecision;
    2424import org.openstreetmap.josm.gui.conflict.tags.RelationMemberConflictDecisionType;
     25import org.openstreetmap.josm.gui.util.GuiHelper;
    2526
    2627/**
    27      * This model manages a list of conflicting relation members.
    28      *
    29      * It can be used as {@see TableModel}.
    30      *
    31      *
    32      */
    33     public class MyRelationMemberConflictResolverModel extends DefaultTableModel {
    34         /** the property name for the number conflicts managed by this model */
    35         static public final String NUM_CONFLICTS_PROP = MyRelationMemberConflictResolverModel.class.getName() + ".numConflicts";
    36 
    37         /** the list of conflict decisions */
    38         private List<RelationMemberConflictDecision> decisions;
    39         /** the collection of relations for which we manage conflicts */
    40         private Collection<Relation> relations;
    41         /** the number of conflicts */
    42         private int numConflicts;
    43         private PropertyChangeSupport support;
    44 
    45         /**
    46          * Replies the current number of conflicts
    47          *
    48          * @return the current number of conflicts
    49          */
    50         public int getNumConflicts() {
    51             return numConflicts;
    52         }
    53 
    54         /**
    55          * Updates the current number of conflicts from list of decisions and emits
    56          * a property change event if necessary.
    57          *
    58          */
    59         protected void updateNumConflicts() {
    60             int count = 0;
    61             for (RelationMemberConflictDecision decision: decisions) {
    62                 if (!decision.isDecided()) {
    63                     count++;
     28 * This model manages a list of conflicting relation members.
     29 *
     30 * It can be used as {@link javax.swing.table.TableModel}.
     31 */
     32public class MyRelationMemberConflictResolverModel extends DefaultTableModel {
     33    /** the property name for the number conflicts managed by this model */
     34    public static final String NUM_CONFLICTS_PROP = MyRelationMemberConflictResolverModel.class.getName() + ".numConflicts";
     35
     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;
     52    }
     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
     95    @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();
     128    }
     129
     130    /**
     131     * Populates the model with the members of the relation <code>relation</code>
     132     * referring to <code>primitive</code>.
     133     *
     134     * @param relation the parent relation
     135     * @param primitive the child primitive
     136     */
     137    protected void populate(Relation relation, OsmPrimitive primitive, Map<Way, Way> oldWays) {
     138        for (int i =0; i<relation.getMembersCount();i++) {
     139            if (MergeOverlapAction.getOld(relation.getMember(i).getWay(), oldWays) == MergeOverlapAction.getOld((Way)primitive, oldWays)) {
     140                decisions.add(new RelationMemberConflictDecision(relation, i));
     141            }
     142        }
     143    }
     144
     145    /**
     146     * Populates the model with the relation members belonging to one of the relations in <code>relations</code>
     147     * and referring to one of the primitives in <code>memberPrimitives</code>.
     148     *
     149     * @param relations  the parent relations. Empty list assumed if null.
     150     * @param memberPrimitives the child primitives. Empty list assumed if null.
     151     */
     152    public void populate(Collection<Relation> relations, Collection<? extends OsmPrimitive> memberPrimitives, Map<Way, Way> oldWays) {
     153        decisions.clear();
     154        relations = relations == null ? new LinkedList<Relation>() : relations;
     155        memberPrimitives = memberPrimitives == null ? new LinkedList<OsmPrimitive>() : memberPrimitives;
     156        for (Relation r : relations) {
     157            for (OsmPrimitive p: memberPrimitives) {
     158                populate(r, p, oldWays);
     159            }
     160        }
     161        this.relations = relations;
     162        refresh();
     163    }
     164
     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;
     233    }
     234
     235    protected void buildResolveCorrespondance(Relation relation, OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
     236
     237        List<RelationMember> relationsMembers = relation.getMembers();
     238        Relation modifiedRelation = MergeOverlapAction.getNew(relation, newRelations);
     239        modifiedRelation.setMembers(null);
     240//      boolean isChanged = false;
     241        for (int i=0; i < relationsMembers.size(); i++) {
     242                RelationMember rm = relationsMembers.get(i);
     243//          RelationMember rm = relation.getMember(i);
     244//          RelationMember rmNew;
     245            RelationMemberConflictDecision decision = getDecision(relation, i);
     246            if (decision == null) {
     247                modifiedRelation.addMember(rm);
     248            } else {
     249                System.out.println(modifiedRelation);
     250                System.out.println(111);
     251                switch(decision.getDecision()) {
     252                case KEEP:
     253//                  modifiedRelation.removeMembersFor(newPrimitive);
     254                        System.out.println(222);
     255                        if (newPrimitive instanceof Way) {
     256                        modifiedRelation.addMember(new RelationMember(decision.getRole(), MergeOverlapAction.getOld((Way)newPrimitive, oldWays)));
     257                        }
     258                        else {
     259                                modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));
     260                        }
     261//                  modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));
     262                    break;
     263                case REMOVE:
     264                        System.out.println(333);
     265//                  modifiedRelation.removeMembersFor(rm.getMember());
     266//                  isChanged = true;
     267                    // do nothing
     268                    break;
     269                case UNDECIDED:
     270                    // FIXME: this is an error
     271                    break;
    64272                }
    65273            }
    66             int oldValue = numConflicts;
    67             numConflicts = count;
    68             if (numConflicts != oldValue) {
    69                 support.firePropertyChange(NUM_CONFLICTS_PROP, oldValue, numConflicts);
    70             }
    71         }
    72 
    73         public void addPropertyChangeListener(PropertyChangeListener l) {
    74             support.addPropertyChangeListener(l);
    75         }
    76 
    77         public void removePropertyChangeListener(PropertyChangeListener l) {
    78             support.removePropertyChangeListener(l);
    79         }
    80 
    81         public MyRelationMemberConflictResolverModel() {
    82             decisions = new ArrayList<>();
    83             support = new PropertyChangeSupport(this);
    84         }
    85 
    86         @Override
    87         public int getRowCount() {
    88             if (decisions == null) return 0;
    89             return decisions.size();
    90         }
    91 
    92         @Override
    93         public Object getValueAt(int row, int column) {
    94             if (decisions == null) return null;
    95 
    96             RelationMemberConflictDecision d = decisions.get(row);
    97             switch(column) {
    98             case 0: /* relation */ return d.getRelation();
    99             case 1: /* pos */ return Integer.toString(d.getPos() + 1); // position in "user space" starting at 1
    100             case 2: /* role */ return d.getRole();
    101             case 3: /* original */ return d.getOriginalPrimitive();
    102             case 4: /* decision */ return d.getDecision();
    103             }
    104             return null;
    105         }
    106 
    107         @Override
    108         public void setValueAt(Object value, int row, int column) {
    109             RelationMemberConflictDecision d = decisions.get(row);
    110             switch(column) {
    111             case 2: /* role */
    112                 d.setRole((String)value);
    113                 break;
    114             case 4: /* decision */
    115                 d.decide((RelationMemberConflictDecisionType)value);
    116                 refresh();
    117                 break;
    118             }
    119             fireTableDataChanged();
    120         }
    121 
    122         /**
    123          * Populates the model with the members of the relation <code>relation</code>
    124          * referring to <code>primitive</code>.
    125          *
    126          * @param relation the parent relation
    127          * @param primitive the child primitive
    128          */
    129         protected void populate(Relation relation, OsmPrimitive primitive, Map<Way, Way> oldWays) {
    130             for (int i = 0; i<relation.getMembersCount(); i++) {
    131                 if (MergeOverlapAction.getOld(relation.getMember(i).getWay(), oldWays) == MergeOverlapAction.getOld((Way)primitive, oldWays)) {
    132                     decisions.add(new RelationMemberConflictDecision(relation, i));
    133                 }
    134             }
    135         }
    136 
    137         /**
    138          * Populates the model with the relation members belonging to one of the relations in <code>relations</code>
    139          * and referring to one of the primitives in <code>memberPrimitives</code>.
    140          *
    141          * @param relations  the parent relations. Empty list assumed if null.
    142          * @param memberPrimitives the child primitives. Empty list assumed if null.
    143          */
    144         public void populate(Collection<Relation> relations, Collection<? extends OsmPrimitive> memberPrimitives, Map<Way, Way> oldWays) {
    145             decisions.clear();
    146                
    147             relations = relations == null ? new LinkedList<Relation>() : relations;
    148             memberPrimitives = memberPrimitives == null ? new LinkedList<OsmPrimitive>() : memberPrimitives;
    149             for (Relation r : relations) {
    150                 for (OsmPrimitive p: memberPrimitives) {
    151                     populate(r, p, oldWays);
    152                 }
    153             }
    154             this.relations = relations;
    155             refresh();
    156         }
    157 
    158         /**
    159          * Populates the model with the relation members represented as a collection of
    160          * {@see RelationToChildReference}s.
    161          *
    162          * @param references the references. Empty list assumed if null.
    163          */
    164         public void populate(Collection<RelationToChildReference> references) {
    165             references = references == null ? new LinkedList<RelationToChildReference>() : references;
    166             decisions.clear();
    167             this.relations = new HashSet<>(references.size());
    168             for (RelationToChildReference reference: references) {
    169                 decisions.add(new RelationMemberConflictDecision(reference.getParent(), reference.getPosition()));
    170                 relations.add(reference.getParent());
    171             }
    172             refresh();
    173         }
    174 
    175         /**
    176          * Replies the decision at position <code>row</code>
    177          *
    178          * @param row
    179          * @return the decision at position <code>row</code>
    180          */
    181         public RelationMemberConflictDecision getDecision(int row) {
    182             return decisions.get(row);
    183         }
    184 
    185         /**
    186          * Replies the number of decisions managed by this model
    187          *
    188          * @return the number of decisions managed by this model
    189          */
    190         public int getNumDecisions() {
    191             return  getRowCount();
    192         }
    193 
    194         /**
    195          * Refreshes the model state. Invoke this method to trigger necessary change
    196          * events after an update of the model data.
    197          *
    198          */
    199         public void refresh() {
    200             updateNumConflicts();
    201             fireTableDataChanged();
    202         }
    203 
    204         /**
    205          * Apply a role to all member managed by this model.
    206          *
    207          * @param role the role. Empty string assumed if null.
    208          */
    209         public void applyRole(String role) {
    210             role = role == null ? "" : role;
    211             for (RelationMemberConflictDecision decision : decisions) {
    212                 decision.setRole(role);
    213             }
    214             refresh();
    215         }
    216 
    217         protected RelationMemberConflictDecision getDecision(Relation relation, int pos) {
    218             for(RelationMemberConflictDecision decision: decisions) {
    219                 if (decision.matches(relation, pos)) return decision;
    220             }
    221             return null;
    222         }
    223 
    224         protected void buildResolveCorrespondance(Relation relation, OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
    225 
    226                 List<RelationMember> relationsMembers = relation.getMembers();
    227                 Relation modifiedRelation = MergeOverlapAction.getNew(relation, newRelations);
    228             modifiedRelation.setMembers(null);
    229 //            boolean isChanged = false;
    230             for (int i=0; i < relationsMembers.size(); i++) {
    231                 RelationMember rm = relationsMembers.get(i);
    232 //                RelationMember rm = relation.getMember(i);
    233 //                RelationMember rmNew;
    234                 RelationMemberConflictDecision decision = getDecision(relation, i);
    235                 if (decision == null) {
    236                     modifiedRelation.addMember(rm);
    237                 } else {
    238                         System.out.println(modifiedRelation);
    239                         System.out.println(111);
    240                     switch(decision.getDecision()) {
    241                     case KEEP:
    242 //                      modifiedRelation.removeMembersFor(newPrimitive);
    243                         System.out.println(222);
    244                         if (newPrimitive instanceof Way) {
    245                                 modifiedRelation.addMember(new RelationMember(decision.getRole(), MergeOverlapAction.getOld((Way)newPrimitive, oldWays)));
    246                         }
    247                         else {
    248                                 modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));
    249                         }
    250 //                      modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));
    251                         break;
    252                     case REMOVE:
    253                         System.out.println(333);
    254 //                      modifiedRelation.removeMembersFor(rm.getMember());
    255 //                        isChanged = true;
    256                         // do nothing
    257                         break;
    258                     case UNDECIDED:
    259                         // FIXME: this is an error
    260                         break;
    261                     }
    262                 }
    263             }
    264         }
    265 
    266         /**
    267          * Builds a collection of commands executing the decisions made in this model.
    268          *
    269          * @param newPrimitive the primitive which members shall refer to if the
    270          * decision is {@see RelationMemberConflictDecisionType#REPLACE}
    271          * @return a list of commands
    272          */
    273         public void buildRelationCorrespondance(OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
    274             for (Relation relation : relations) {
    275                 buildResolveCorrespondance(relation, newPrimitive, newRelations, oldWays);
    276             }
    277         }
    278 
    279         protected boolean isChanged(Relation relation, OsmPrimitive newPrimitive) {
    280             for (int i=0; i < relation.getMembersCount(); i++) {
    281                 RelationMemberConflictDecision decision = getDecision(relation, i);
    282                 if (decision == null) {
    283                     continue;
    284                 }
    285                 switch(decision.getDecision()) {
    286                 case REMOVE: return true;
    287                 case KEEP:
    288                     if (!relation.getMember(i).getRole().equals(decision.getRole()))
    289                         return true;
    290                     if (relation.getMember(i).getMember() != newPrimitive)
    291                         return true;
    292                 case UNDECIDED:
    293                     // FIXME: handle error
    294                 }
    295             }
    296             return false;
    297         }
    298 
    299         /**
    300          * Replies the set of relations which have to be modified according
    301          * to the decisions managed by this model.
    302          *
    303          * @param newPrimitive the primitive which members shall refer to if the
    304          * decision is {@see RelationMemberConflictDecisionType#REPLACE}
    305          *
    306          * @return the set of relations which have to be modified according
    307          * to the decisions managed by this model
    308          */
    309         public Set<Relation> getModifiedRelations(OsmPrimitive newPrimitive) {
    310             HashSet<Relation> ret = new HashSet<>();
    311             for (Relation relation: relations) {
    312                 if (isChanged(relation, newPrimitive)) {
    313                     ret.add(relation);
    314                 }
    315             }
    316             return ret;
    317         }
    318     }
     274        }
     275    }
     276
     277    /**
     278     * Builds a collection of commands executing the decisions made in this model.
     279     *
     280     * @param newPrimitive the primitive which members shall refer to if the
     281     * decision is {@see RelationMemberConflictDecisionType#REPLACE}
     282     * @return a list of commands
     283     */
     284    public void buildRelationCorrespondance(OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) {
     285        for (Relation relation : relations) {
     286                buildResolveCorrespondance(relation, newPrimitive, newRelations, oldWays);
     287        }
     288    }
     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    }
     329}
Note: See TracChangeset for help on using the changeset viewer.