Changeset 4816 in josm


Ignore:
Timestamp:
2012-01-18T19:48:23+01:00 (12 years ago)
Author:
simon04
Message:

fix #7257, fix #4093 - Provide an option to automatically download elements after a reference error

Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/HelpAwareOptionPane.java

    r3501 r4816  
    1313import java.util.List;
    1414
    15 import javax.swing.AbstractAction;
    16 import javax.swing.Action;
    17 import javax.swing.Icon;
    18 import javax.swing.JButton;
    19 import javax.swing.JComponent;
    20 import javax.swing.JDialog;
    21 import javax.swing.JLabel;
    22 import javax.swing.JOptionPane;
    23 import javax.swing.KeyStroke;
    24 import javax.swing.SwingUtilities;
     15import javax.swing.*;
    2516
    2617import org.openstreetmap.josm.gui.help.HelpBrowser;
     
    167158
    168159        if (msg instanceof String) {
    169             msg = new JLabel((String)msg);
     160            JEditorPane pane = new JEditorPane();
     161            pane.setContentType("text/html");
     162            pane.setText((String) msg);
     163            pane.setEditable(false);
     164            pane.setOpaque(false);
     165            msg = pane;
    170166        }
    171167
  • trunk/src/org/openstreetmap/josm/gui/io/AbstractUploadTask.java

    r4191 r4816  
    88import java.net.HttpURLConnection;
    99import java.text.SimpleDateFormat;
     10import java.util.Arrays;
     11import java.util.Collection;
    1012import java.util.Collections;
    1113import java.util.Date;
     
    3133import org.openstreetmap.josm.io.OsmApiPrimitiveGoneException;
    3234import org.openstreetmap.josm.tools.DateUtils;
     35import org.openstreetmap.josm.tools.ExceptionUtil;
    3336import org.openstreetmap.josm.tools.ImageProvider;
     37import org.openstreetmap.josm.tools.Pair;
    3438
    3539public abstract class AbstractUploadTask extends PleaseWaitRunnable {
     
    206210     * a non-deleted way on the server.
    207211     */
    208     protected void handleUploadConflictForNodeStillInUse(long nodeId, long wayId) {
     212    protected void handleUploadPreconditionFailedConflict(OsmApiException e, Pair<OsmPrimitive, Collection<OsmPrimitive>> conflict) {
    209213        ButtonSpec[] options = new ButtonSpec[] {
    210214                new ButtonSpec(
    211215                        tr("Prepare conflict resolution"),
    212216                        ImageProvider.get("ok"),
    213                         tr("Click to download all parent ways for node {0}", nodeId),
     217                        tr("Click to download all referring objects for {0}", conflict.a),
    214218                        null /* no specific help context */
    215219                ),
     
    217221                        tr("Cancel"),
    218222                        ImageProvider.get("cancel"),
    219                         tr("Click to cancel and to resume editing the map", nodeId),
     223                        tr("Click to cancel and to resume editing the map"),
    220224                        null /* no specific help context */
    221225                )
    222226        };
    223         String msg =  tr("<html>Uploading <strong>failed</strong> because you tried "
    224                 + "to delete node {0} which is still in use in way {1}.<br><br>"
    225                 + "Click <strong>{2}</strong> to download all parent ways of node {0}.<br>"
    226                 + "If necessary JOSM will create conflicts which you can resolve in the Conflict Resolution Dialog."
    227                 + "</html>",
    228                 nodeId, wayId, options[0].text
    229         );
    230 
     227        String msg = ExceptionUtil.explainPreconditionFailed(e).replace("</html>", "<br><br>" + tr(
     228                "Click <strong>{0}</strong> to load them now.<br>"
     229                + "If necessary JOSM will create conflicts which you can resolve in the Conflict Resolution Dialog.",
     230                options[0].text)) + "</html>";
    231231        int ret = HelpAwareOptionPane.showOptionDialog(
    232232                Main.parent,
    233233                msg,
    234                 tr("Node still in use"),
     234                tr("Object still in use"),
    235235                JOptionPane.ERROR_MESSAGE,
    236236                null,
     
    238238                options[0],
    239239                "/Action/Upload#NodeStillInUseInWay"
    240         );
    241         if (ret != 0) return;
    242         DownloadReferrersAction.downloadReferrers(Main.map.mapView.getEditLayer(), nodeId, OsmPrimitiveType.NODE);
     240);
     241        if (ret == 0) {
     242            DownloadReferrersAction.downloadReferrers(Main.map.mapView.getEditLayer(), Arrays.asList(conflict.a));
     243        }
    243244    }
    244245
     
    263264            return;
    264265        }
    265         pattern = "Node (\\d+) is still used by way (\\d+).";
    266         p = Pattern.compile(pattern);
    267         m = p.matcher(e.getErrorHeader());
    268         if (m.matches()) {
    269             handleUploadConflictForNodeStillInUse(Long.parseLong(m.group(1)), Long.parseLong(m.group(2)));
    270             return;
    271         }
    272266        System.out.println(tr("Warning: error header \"{0}\" did not match with an expected pattern", e.getErrorHeader()));
    273267        handleUploadConflictForUnknownConflict();
     
    280274     */
    281275    protected void handlePreconditionFailed(OsmApiException e) {
    282         String pattern = "Precondition failed: Node (\\d+) is still used by way (\\d+).";
    283         Pattern p = Pattern.compile(pattern);
    284         Matcher m = p.matcher(e.getErrorHeader());
    285         if (m.matches()) {
    286             handleUploadConflictForNodeStillInUse(Long.parseLong(m.group(1)), Long.parseLong(m.group(2)));
    287             return;
    288         }
    289         System.out.println(tr("Warning: error header \"{0}\" did not match with an expected pattern", e.getErrorHeader()));
    290         ExceptionDialogUtil.explainPreconditionFailed(e);
     276        // in the worst case, ExceptionUtil.parsePreconditionFailed is executed trice - should not be too expensive
     277        Pair<OsmPrimitive, Collection<OsmPrimitive>> conflict = ExceptionUtil.parsePreconditionFailed(e.getErrorHeader());
     278        if (conflict != null) {
     279            handleUploadPreconditionFailedConflict(e, conflict);
     280        } else {
     281            System.out.println(tr("Warning: error header \"{0}\" did not match with an expected pattern", e.getErrorHeader()));
     282            ExceptionDialogUtil.explainPreconditionFailed(e);
     283        }
    291284    }
    292285
  • trunk/src/org/openstreetmap/josm/tools/ExceptionUtil.java

    r4703 r4816  
    2323
    2424import org.openstreetmap.josm.Main;
     25import org.openstreetmap.josm.data.osm.Node;
     26import org.openstreetmap.josm.data.osm.OsmPrimitive;
     27import org.openstreetmap.josm.data.osm.Relation;
     28import org.openstreetmap.josm.data.osm.Way;
    2529import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
    2630import org.openstreetmap.josm.io.ChangesetClosedException;
     
    3337import org.openstreetmap.josm.io.auth.CredentialsManager;
    3438
     39@SuppressWarnings("CallToThreadDumpStack")
    3540public class ExceptionUtil {
    3641    private ExceptionUtil() {
     
    4651        String msg = tr(
    4752                "<html>Failed to initialize communication with the OSM server {0}.<br>"
    48                 + "Check the server URL in your preferences and your internet connection.</html>", Main.pref.get(
     53                + "Check the server URL in your preferences and your internet connection.", Main.pref.get(
    4954                        "osm-server.url", "http://api.openstreetmap.org/api"));
    5055        return msg;
     
    7075    }
    7176
    72     /**
    73      * Explains a precondition exception when a child relation could not be deleted because
    74      * it is still referred to by an undeleted parent relation.
    75      *
    76      * @param e the exception
    77      * @param childRelation the child relation
    78      * @param parentRelation the parent relation
    79      * @return
    80      */
    81     public static String explainDeletedRelationStillInUse(OsmApiException e, long childRelation, long parentRelation) {
    82         String msg = tr(
    83                 "<html><strong>Failed</strong> to delete <strong>relation {0}</strong>."
    84                 + " It is still referred to by relation {1}.<br>"
    85                 + "Please load relation {1}, remove the reference to relation {0}, and upload again.</html>",
    86                 childRelation,parentRelation
    87         );
    88         return msg;
    89     }
    90    
    91     /**
    92      * Explains a precondition exception when a child node could not be deleted because
    93      * it is still referred to by undeleted parent ways.
    94      *
    95      * @param e the exception
    96      * @param childNode the child node
    97      * @param parentWays the parent ways
    98      * @return
    99      */
    100     public static String explainDeletedNodeStillInUse(OsmApiException e, long childNode, Collection<Long> parentWays) {
    101         String ids = parentWays.size() == 1 ? parentWays.iterator().next().toString() : parentWays.toString();
    102         String msg = trn(
    103                 "<html><strong>Failed</strong> to delete <strong>node {0}</strong>."
    104                 + " It is still referred to by way {1}.<br>"
    105                 + "Please load the way, remove the reference to the node, and upload again.</html>",
    106                 "<html><strong>Failed</strong> to delete <strong>node {0}</strong>."
    107                 + " It is still referred to by ways {1}.<br>"
    108                 + "Please load the ways, remove the reference to the node, and upload again.</html>",
    109                 parentWays.size(), childNode, ids
    110         );
    111         return msg;
     77    public static Pair<OsmPrimitive, Collection<OsmPrimitive>> parsePreconditionFailed(String msg) {
     78        final String ids = "(\\d+(?:,\\d+)*)";
     79        final Collection<OsmPrimitive> refs = new TreeSet<OsmPrimitive>(); // error message can contain several times the same way
     80        Matcher m;
     81        m = Pattern.compile(".*Node (\\d+) is still used by relations " + ids + ".*").matcher(msg);
     82        if (m.matches()) {
     83            OsmPrimitive n = new Node(Long.parseLong(m.group(1)));
     84            for (String s : m.group(2).split(",")) {
     85                refs.add(new Relation(Long.parseLong(m.group(2))));
     86            }
     87            return Pair.create(n, refs);
     88        }
     89        m = Pattern.compile(".*Node (\\d+) is still used by ways " + ids + ".*").matcher(msg);
     90        if (m.matches()) {
     91            OsmPrimitive n = new Node(Long.parseLong(m.group(1)));
     92            for (String s : m.group(2).split(",")) {
     93                refs.add(new Way(Long.parseLong(m.group(2))));
     94            }
     95            return Pair.create(n, refs);
     96        }
     97        m = Pattern.compile(".*The relation (\\d+) is used in relations? " + ids + ".*").matcher(msg);
     98        if (m.matches()) {
     99            OsmPrimitive n = new Relation(Long.parseLong(m.group(1)));
     100            for (String s : m.group(2).split(",")) {
     101                refs.add(new Relation(Long.parseLong(m.group(2))));
     102            }
     103            return Pair.create(n, refs);
     104        }
     105        m = Pattern.compile(".*Way (\\d+) is still used by relations " + ids + ".*").matcher(msg);
     106        if (m.matches()) {
     107            OsmPrimitive n = new Way(Long.parseLong(m.group(1)));
     108            for (String s : m.group(2).split(",")) {
     109                refs.add(new Relation(Long.parseLong(m.group(2))));
     110            }
     111            return Pair.create(n, refs);
     112        }
     113        m = Pattern.compile(".*Way (\\d+) requires the nodes with id in " + ids + ".*").matcher(msg); // ... ", which either do not exist, or are not visible"
     114        if (m.matches()) {
     115            OsmPrimitive n = new Way(Long.parseLong(m.group(1)));
     116            for (String s : m.group(2).split(",")) {
     117                refs.add(new Node(Long.parseLong(m.group(2))));
     118            }
     119            return Pair.create(n, refs);
     120        }
     121        return null;
    112122    }
    113123
     
    120130        e.printStackTrace();
    121131        String msg = e.getErrorHeader();
    122         if (msg != null) {
    123             Matcher m = Pattern.compile("Precondition failed: The relation (\\d+) is used in relation (\\d+)\\.").matcher(msg);
    124             if (m.matches()) {
    125                 long childRelation = Long.parseLong(m.group(1));
    126                 long parentRelation = Long.parseLong(m.group(2));
    127                 return explainDeletedRelationStillInUse(e, childRelation, parentRelation);
     132        Pair<OsmPrimitive, Collection<OsmPrimitive>> conflict = parsePreconditionFailed(e.getErrorHeader());
     133        if (conflict != null) {
     134            OsmPrimitive firstRefs = conflict.b.iterator().next();
     135            Long objId = conflict.a.getId();
     136            Collection<Long> refIds= Utils.transform(conflict.b, new Utils.Function<OsmPrimitive, Long>() {
     137
     138                @Override
     139                public Long apply(OsmPrimitive x) {
     140                    return x.getId();
     141                }
     142            });
     143            String refIdsString = refIds.size() == 1 ? refIds.iterator().next().toString() : refIds.toString();
     144            if (conflict.a instanceof Node) {
     145                if (firstRefs instanceof Node) {
     146                    return "<html>" + trn(
     147                            "<strong>Failed</strong> to delete <strong>node {0}</strong>."
     148                            + " It is still referred to by node {1}.<br>"
     149                            + "Please load the node, remove the reference to the node, and upload again.",
     150                            "<strong>Failed</strong> to delete <strong>node {0}</strong>."
     151                            + " It is still referred to by nodes {1}.<br>"
     152                            + "Please load the nodes, remove the reference to the node, and upload again.",
     153                            conflict.b.size(), objId, refIdsString) + "</html>";
     154                } else if (firstRefs instanceof Way) {
     155                    return "<html>" + trn(
     156                            "<strong>Failed</strong> to delete <strong>node {0}</strong>."
     157                            + " It is still referred to by way {1}.<br>"
     158                            + "Please load the way, remove the reference to the node, and upload again.",
     159                            "<strong>Failed</strong> to delete <strong>node {0}</strong>."
     160                            + " It is still referred to by ways {1}.<br>"
     161                            + "Please load the ways, remove the reference to the node, and upload again.",
     162                            conflict.b.size(), objId, refIdsString) + "</html>";
     163                } else if (firstRefs instanceof Relation) {
     164                    return "<html>" + trn(
     165                            "<strong>Failed</strong> to delete <strong>node {0}</strong>."
     166                            + " It is still referred to by relation {1}.<br>"
     167                            + "Please load the relation, remove the reference to the node, and upload again.",
     168                            "<strong>Failed</strong> to delete <strong>node {0}</strong>."
     169                            + " It is still referred to by relations {1}.<br>"
     170                            + "Please load the relations, remove the reference to the node, and upload again.",
     171                            conflict.b.size(), objId, refIdsString) + "</html>";
     172                } else {
     173                    throw new IllegalStateException();
     174                }
     175            } else if (conflict.a instanceof Way) {
     176                if (firstRefs instanceof Node) {
     177                    return "<html>" + trn(
     178                            "<strong>Failed</strong> to delete <strong>way {0}</strong>."
     179                            + " It is still referred to by node {1}.<br>"
     180                            + "Please load the node, remove the reference to the way, and upload again.",
     181                            "<strong>Failed</strong> to delete <strong>way {0}</strong>."
     182                            + " It is still referred to by nodes {1}.<br>"
     183                            + "Please load the nodes, remove the reference to the way, and upload again.",
     184                            conflict.b.size(), objId, refIdsString) + "</html>";
     185                } else if (firstRefs instanceof Way) {
     186                    return "<html>" + trn(
     187                            "<strong>Failed</strong> to delete <strong>way {0}</strong>."
     188                            + " It is still referred to by way {1}.<br>"
     189                            + "Please load the way, remove the reference to the way, and upload again.",
     190                            "<strong>Failed</strong> to delete <strong>way {0}</strong>."
     191                            + " It is still referred to by ways {1}.<br>"
     192                            + "Please load the ways, remove the reference to the way, and upload again.",
     193                            conflict.b.size(), objId, refIdsString) + "</html>";
     194                } else if (firstRefs instanceof Relation) {
     195                    return "<html>" + trn(
     196                            "<strong>Failed</strong> to delete <strong>way {0}</strong>."
     197                            + " It is still referred to by relation {1}.<br>"
     198                            + "Please load the relation, remove the reference to the way, and upload again.",
     199                            "<strong>Failed</strong> to delete <strong>way {0}</strong>."
     200                            + " It is still referred to by relations {1}.<br>"
     201                            + "Please load the relations, remove the reference to the way, and upload again.",
     202                            conflict.b.size(), objId, refIdsString) + "</html>";
     203                } else {
     204                    throw new IllegalStateException();
     205                }
     206            } else if (conflict.a instanceof Relation) {
     207                if (firstRefs instanceof Node) {
     208                    return "<html>" + trn(
     209                            "<strong>Failed</strong> to delete <strong>relation {0}</strong>."
     210                            + " It is still referred to by node {1}.<br>"
     211                            + "Please load the node, remove the reference to the relation, and upload again.",
     212                            "<strong>Failed</strong> to delete <strong>relation {0}</strong>."
     213                            + " It is still referred to by nodes {1}.<br>"
     214                            + "Please load the nodes, remove the reference to the relation, and upload again.",
     215                            conflict.b.size(), objId, refIdsString) + "</html>";
     216                } else if (firstRefs instanceof Way) {
     217                    return "<html>" + trn(
     218                            "<strong>Failed</strong> to delete <strong>relation {0}</strong>."
     219                            + " It is still referred to by way {1}.<br>"
     220                            + "Please load the way, remove the reference to the relation, and upload again.",
     221                            "<strong>Failed</strong> to delete <strong>relation {0}</strong>."
     222                            + " It is still referred to by ways {1}.<br>"
     223                            + "Please load the ways, remove the reference to the relation, and upload again.",
     224                            conflict.b.size(), objId, refIdsString) + "</html>";
     225                } else if (firstRefs instanceof Relation) {
     226                    return "<html>" + trn(
     227                            "<strong>Failed</strong> to delete <strong>relation {0}</strong>."
     228                            + " It is still referred to by relation {1}.<br>"
     229                            + "Please load the relation, remove the reference to the relation, and upload again.",
     230                            "<strong>Failed</strong> to delete <strong>relation {0}</strong>."
     231                            + " It is still referred to by relations {1}.<br>"
     232                            + "Please load the relations, remove the reference to the relation, and upload again.",
     233                            conflict.b.size(), objId, refIdsString) + "</html>";
     234                } else {
     235                    throw new IllegalStateException();
     236                }
     237            } else {
     238                throw new IllegalStateException();
    128239            }
    129             m = Pattern.compile("Precondition failed: Node (\\d+) is still used by ways (\\d+(?:,\\d+)*)\\.").matcher(msg);
    130             if (m.matches()) {
    131                 long childNode = Long.parseLong(m.group(1));
    132                 Set<Long> parentWays = new TreeSet<Long>(); // Error message can contain several times the same way
    133                 for (String s : m.group(2).split(",")) {
    134                     parentWays.add(Long.parseLong(s));
    135                 }
    136                 return explainDeletedNodeStillInUse(e, childNode, parentWays);
    137             }
    138         }
    139         msg = tr(
    140                 "<html>Uploading to the server <strong>failed</strong> because your current<br>"
    141                 + "dataset violates a precondition.<br>" + "The error message is:<br>" + "{0}" + "</html>",
    142                 escapeReservedCharactersHTML(e.getMessage()));
    143         return msg;
     240        } else {
     241            return tr(
     242                    "<html>Uploading to the server <strong>failed</strong> because your current<br>"
     243                    + "dataset violates a precondition.<br>" + "The error message is:<br>" + "{0}" + "</html>",
     244                    escapeReservedCharactersHTML(e.getMessage()));
     245        }
    144246    }
    145247
     
    276378                if (closeDate == null) {
    277379                    msg = tr(
    278                             "<html>Closing of changeset <strong>{0}</strong> failed <br>because it has already been closed.</html>",
     380                            "<html>Closing of changeset <strong>{0}</strong> failed <br>because it has already been closed.",
    279381                            changesetId
    280382                    );
     
    283385                    msg = tr(
    284386                            "<html>Closing of changeset <strong>{0}</strong> failed<br>"
    285                             +" because it has already been closed on {1}.</html>",
     387                            +" because it has already been closed on {1}.",
    286388                            changesetId,
    287389                            dateFormat.format(closeDate)
     
    295397                    msg
    296398            );
    297         }
    298         msg = tr(
    299                 "<html>The server reported that it has detected a conflict.</html>"
    300         );
     399        } else {
     400            msg = tr(
     401                    "<html>The server reported that it has detected a conflict.");
     402        }
    301403        return msg;
    302404    }
     
    313415        msg = tr(
    314416                "<html>Failed to upload to changeset <strong>{0}</strong><br>"
    315                 +"because it has already been closed on {1}.</html>",
     417                +"because it has already been closed on {1}.",
    316418                e.getChangesetId(),
    317419                e.getClosedOn() == null ? "?" : dateFormat.format(e.getClosedOn())
     
    354456        String message = tr("<html>Failed to open a connection to the remote server<br>" + "''{0}''<br>"
    355457                + "for security reasons. This is most likely because you are running<br>"
    356                 + "in an applet and because you did not load your applet from ''{1}''.</html>", apiUrl, host);
     458                + "in an applet and because you did not load your applet from ''{1}''.", apiUrl, host);
    357459        return message;
    358460    }
     
    369471        String apiUrl = e.getUrl();
    370472        String message = tr("<html>Failed to open a connection to the remote server<br>" + "''{0}''.<br>"
    371                 + "Please check your internet connection.</html>", apiUrl);
     473                + "Please check your internet connection.", apiUrl);
    372474        e.printStackTrace();
    373475        return message;
     
    417519        String apiUrl = e.getUrl();
    418520        String message = tr("<html>The OSM server<br>" + "''{0}''<br>" + "reported an internal server error.<br>"
    419                 + "This is most likely a temporary problem. Please try again later.</html>", apiUrl);
     521                + "This is most likely a temporary problem. Please try again later.", apiUrl);
    420522        e.printStackTrace();
    421523        return message;
     
    495597        String message = tr("<html>Failed to open a connection to the remote server<br>" + "''{0}''.<br>"
    496598                + "Host name ''{1}'' could not be resolved. <br>"
    497                 + "Please check the API URL in your preferences and your internet connection.</html>", apiUrl, host);
     599                + "Please check the API URL in your preferences and your internet connection.", apiUrl, host);
    498600        e.printStackTrace();
    499601        return message;
  • trunk/src/org/openstreetmap/josm/tools/Utils.java

    r4668 r4816  
    2121import java.util.ArrayList;
    2222import java.util.Collection;
     23import java.util.Iterator;
    2324import java.util.List;
    2425
     
    396397        return sorted;
    397398    }
     399
     400    /**
     401     * Represents a function that can be applied to objects of {@code A} and
     402     * returns objects of {@code B}.
     403     * @param <A> class of input objects
     404     * @param <B> class of transformed objects
     405     */
     406    public static interface Function<A, B> {
     407
     408        /**
     409         * Applies the function on {@code x}.
     410         * @param x an object of
     411         * @return the transformed object
     412         */
     413        B apply(A x);
     414    }
     415
     416    /**
     417     * Transforms the collection {@code c} into an unmodifiable collection and
     418     * applies the {@link Function} {@code f} on each element upon access.
     419     * @param <A> class of input collection
     420     * @param <B> class of transformed collection
     421     * @param c a collection
     422     * @param f a function that transforms objects of {@code A} to objects of {@code B}
     423     * @return the transformed unmodifiable collection
     424     */
     425    public static <A, B> Collection<B> transform(final Collection<A> c, final Function<A, B> f) {
     426        return new Collection<B>() {
     427
     428            @Override
     429            public int size() {
     430                return c.size();
     431            }
     432
     433            @Override
     434            public boolean isEmpty() {
     435                return c.isEmpty();
     436            }
     437
     438            @Override
     439            public boolean contains(Object o) {
     440                return c.contains(o);
     441            }
     442
     443            @Override
     444            public Object[] toArray() {
     445                return c.toArray();
     446            }
     447
     448            @Override
     449            public <T> T[] toArray(T[] a) {
     450                return c.toArray(a);
     451            }
     452
     453            @Override
     454            public String toString() {
     455                return c.toString();
     456            }
     457
     458            @Override
     459            public Iterator<B> iterator() {
     460                return new Iterator<B>() {
     461
     462                    private Iterator<A> it = c.iterator();
     463
     464                    @Override
     465                    public boolean hasNext() {
     466                        return it.hasNext();
     467                    }
     468
     469                    @Override
     470                    public B next() {
     471                        return f.apply(it.next());
     472                    }
     473
     474                    @Override
     475                    public void remove() {
     476                        throw new UnsupportedOperationException();
     477                    }
     478                };
     479            }
     480
     481            @Override
     482            public boolean add(B e) {
     483                throw new UnsupportedOperationException();
     484            }
     485
     486            @Override
     487            public boolean remove(Object o) {
     488                throw new UnsupportedOperationException();
     489            }
     490
     491            @Override
     492            public boolean containsAll(Collection<?> c) {
     493                throw new UnsupportedOperationException();
     494            }
     495
     496            @Override
     497            public boolean addAll(Collection<? extends B> c) {
     498                throw new UnsupportedOperationException();
     499            }
     500
     501            @Override
     502            public boolean removeAll(Collection<?> c) {
     503                throw new UnsupportedOperationException();
     504            }
     505
     506            @Override
     507            public boolean retainAll(Collection<?> c) {
     508                throw new UnsupportedOperationException();
     509            }
     510
     511            @Override
     512            public void clear() {
     513                throw new UnsupportedOperationException();
     514            }
     515        };
     516    }
    398517}
Note: See TracChangeset for help on using the changeset viewer.