Index: trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 2205)
+++ trunk/src/org/openstreetmap/josm/data/osm/OsmPrimitive.java	(revision 2206)
@@ -35,10 +35,17 @@
 abstract public class OsmPrimitive implements Comparable<OsmPrimitive>, Tagged {
 
+    private static final int FLAG_MODIFIED = 1 << 0;
+    private static final int FLAG_VISIBLE  = 1 << 1;
+    private static final int FLAG_DISABLED = 1 << 2;
+    private static final int FLAG_DELETED  = 1 << 3;
+    private static final int FLAG_FILTERED = 1 << 4;
+    private static final int FLAG_SELECTED = 1 << 5;
+
     /**
      * Replies the sub-collection of {@see OsmPrimitive}s of type <code>type</code> present in
      * another collection of {@see OsmPrimitive}s. The result collection is a list.
-     * 
+     *
      * If <code>list</code> is null, replies an empty list.
-     * 
+     *
      * @param <T>
      * @param list  the original list
@@ -60,7 +67,7 @@
      * Replies the sub-collection of {@see OsmPrimitive}s of type <code>type</code> present in
      * another collection of {@see OsmPrimitive}s. The result collection is a set.
-     * 
+     *
      * If <code>list</code> is null, replies an empty set.
-     * 
+     *
      * @param <T>
      * @param list  the original collection
@@ -117,38 +124,6 @@
     private long id = 0;
 
-    /**
-     * <code>true</code> if the object has been modified since it was loaded from
-     * the server. In this case, on next upload, this object will be updated.
-     * Deleted objects are deleted from the server. If the objects are added (id=0),
-     * the modified is ignored and the object is added to the server.
-     *
-     */
-    private boolean modified = false;
-
-    /**
-     * <code>true</code>, if the object has been deleted.
-     *
-     */
-    private boolean deleted = false;
-
-    /**
-     * Visibility status as specified by the server. The visible attribute was
-     * introduced with the 0.4 API to be able to communicate deleted objects
-     * (they will have visible=false).
-     *
-     */
-    private boolean visible = true;
-
-    /**
-     * <code>true</code>, if the object has been set inactive
-     *
-     */
-    private boolean disabled = false;
-
-    /**
-     * <code>true</code>, if the object has been filtered out
-     *
-     */
-    private boolean filtered = false;
+    private volatile byte flags;
+
 
     /**
@@ -157,10 +132,4 @@
      */
     public User user = null;
-
-    /**
-     * If set to true, this object is currently selected.
-     *
-     */
-    private volatile boolean selected = false;
 
     /**
@@ -208,5 +177,10 @@
      */
     public void setDisabled(boolean disabled) {
-        this.disabled = disabled;
+        if (disabled) {
+            flags |= FLAG_DISABLED;
+        } else {
+            flags &= ~FLAG_DISABLED;
+        }
+
     }
 
@@ -217,5 +191,5 @@
      */
     public boolean isDisabled() {
-        return disabled;
+        return (flags & FLAG_DISABLED) != 0;
     }
     /**
@@ -225,5 +199,9 @@
      */
     public void setFiltered(boolean filtered) {
-        this.filtered = filtered;
+        if (filtered) {
+            flags |= FLAG_FILTERED;
+        } else {
+            flags &= ~FLAG_FILTERED;
+        }
     }
     /**
@@ -233,5 +211,5 @@
      */
     public boolean isFiltered() {
-        return filtered;
+        return (flags & FLAG_FILTERED) != 0;
     }
 
@@ -243,5 +221,9 @@
      */
     public void setSelected(boolean selected) {
-        this.selected = selected;
+        if (selected) {
+            flags |= FLAG_SELECTED;
+        } else {
+            flags &= ~FLAG_SELECTED;
+        }
     }
     /**
@@ -252,5 +234,5 @@
      */
     public boolean isSelected() {
-        return selected;
+        return (flags & FLAG_SELECTED) != 0;
     }
 
@@ -261,5 +243,9 @@
      */
     public void setModified(boolean modified) {
-        this.modified = modified;
+        if (modified) {
+            flags |= FLAG_MODIFIED;
+        } else {
+            flags &= ~FLAG_MODIFIED;
+        }
     }
 
@@ -268,9 +254,12 @@
      * the server. In this case, on next upload, this object will be updated.
      *
+     * Deleted objects are deleted from the server. If the objects are added (id=0),
+     * the modified is ignored and the object is added to the server.
+     *
      * @return <code>true</code> if the object has been modified since it was loaded from
      * the server
      */
     public boolean isModified() {
-        return modified;
+        return (flags & FLAG_MODIFIED) != 0;
     }
 
@@ -282,5 +271,5 @@
      */
     public boolean isDeleted() {
-        return deleted;
+        return (flags & FLAG_DELETED) != 0;
     }
 
@@ -292,5 +281,5 @@
      */
     public boolean isUsable() {
-        return !deleted && !incomplete && !disabled;
+        return !isDeleted() && !incomplete && !isDisabled();
     }
 
@@ -304,5 +293,5 @@
      */
     public boolean isVisible() {
-        return visible;
+        return (flags & FLAG_VISIBLE) != 0;
     }
 
@@ -318,5 +307,9 @@
         if (id == 0 && visible == false)
             throw new IllegalStateException(tr("A primitive with ID = 0 can't be invisible."));
-        this.visible = visible;
+        if (visible) {
+            flags |= FLAG_VISIBLE;
+        } else {
+            flags &= ~FLAG_VISIBLE;
+        }
     }
 
@@ -456,7 +449,11 @@
      */
     public void setDeleted(boolean deleted) {
-        this.modified = deleted;
-        this.deleted = deleted;
-        this.selected = false;
+        if (deleted) {
+            flags |= FLAG_DELETED;
+        } else {
+            flags &= ~FLAG_DELETED;
+        }
+        setModified(deleted);
+        setSelected(false);
     }
 
@@ -623,11 +620,8 @@
         keys = osm.keys == null ? null : new HashMap<String, String>(osm.keys);
         id = osm.id;
-        modified = osm.modified;
-        deleted = osm.deleted;
-        setSelected(osm.isSelected());
         timestamp = osm.timestamp;
         version = osm.version;
         incomplete = osm.incomplete;
-        visible = osm.visible;
+        flags = osm.flags;
         clearCached();
         clearErrors();
@@ -674,9 +668,9 @@
 
         return
-        deleted == other.deleted
-        && modified == other.modified
+        isDeleted() == other.isDeleted()
+        && isModified() == other.isModified()
         && timestamp == other.timestamp
         && version == other.version
-        && visible == other.visible
+        && isVisible() == other.isVisible()
         && (user == null ? other.user==null : user==other.user);
     }
Index: trunk/src/org/openstreetmap/josm/data/osm/RelationMember.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/RelationMember.java	(revision 2205)
+++ trunk/src/org/openstreetmap/josm/data/osm/RelationMember.java	(revision 2206)
@@ -25,6 +25,4 @@
      */
     public String getRole() {
-        if (role == null)
-            return "";
         return role;
     }
@@ -36,5 +34,5 @@
      */
     public boolean hasRole() {
-        return role != null && !"".equals(role);
+        return !"".equals(role);
     }
 
@@ -95,5 +93,5 @@
     /**
      *
-     * @return Member
+     * @return Member. Returned value is never null.
      * @since 1937
      */
@@ -102,5 +100,16 @@
     }
 
+    /**
+     *
+     * @param role Can be null, in this case it's save as ""
+     * @param member Cannot be null
+     */
     public RelationMember(String role, OsmPrimitive member) {
+        if (role == null) {
+            role = "";
+        }
+        if (member == null) {
+            throw new IllegalArgumentException("Relation member cannot be null");
+        }
         this.role = role;
         this.member = member;
@@ -109,9 +118,10 @@
     /**
      * Copy constructor.
+     * This constructor is left only for backwards compatibility. Copying RelationMember doesn't make sense
+     * because it's immutable
      * @param other relation member to be copied.
      */
     public RelationMember(RelationMember other) {
-        role = other.role;
-        member = other.member;
+        this(other.role, other.member);
     }
 
@@ -127,6 +137,4 @@
      */
     public boolean refersTo(OsmPrimitive primitive) {
-        if (primitive == null) return false;
-        if (member == null) return false;
         return member == primitive;
     }
@@ -136,6 +144,6 @@
         final int prime = 31;
         int result = 1;
-        result = prime * result + ((member == null) ? 0 : member.hashCode());
-        result = prime * result + ((role == null) ? 0 : role.hashCode());
+        result = prime * result + member.hashCode();
+        result = prime * result + role.hashCode();
         return result;
     }
@@ -143,22 +151,10 @@
     @Override
     public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
+        if (obj instanceof RelationMember) {
+            RelationMember other = (RelationMember) obj;
+            return member.equals(other.getMember()) && role.equals(other.getRole());
+        } else {
             return false;
-        if (getClass() != obj.getClass())
-            return false;
-        RelationMember other = (RelationMember) obj;
-        if (member == null) {
-            if (other.member != null)
-                return false;
-        } else if (!member.equals(other.member))
-            return false;
-        if (role == null) {
-            if (other.role != null)
-                return false;
-        } else if (!role.equals(other.role))
-            return false;
-        return true;
+        }
     }
 }
Index: trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 2205)
+++ trunk/src/org/openstreetmap/josm/data/osm/visitor/MapPaintVisitor.java	(revision 2206)
@@ -582,8 +582,5 @@
             //    System.out.println("member " + m.member + " selected " + r.selected);
 
-            if(m.getMember() == null) {
-                // TODO Nullable member will not be allowed after RelationMember.member is encalupsed
-                r.putError(tr("Empty member in relation."), true);
-            } else if(m.getMember().isDeleted()) {
+            if (m.getMember().isDeleted()) {
                 r.putError(tr("Deleted member ''{0}'' in relation.",
                         m.getMember().getDisplayName(DefaultNameFormatter.getInstance())), true);
@@ -678,5 +675,4 @@
                 if("-1".equals(onewayviastr)) {
                     onewayvia = true;
-                    Node t = firstNode;
                     firstNode = lastNode;
                     lastNode = firstNode;
@@ -851,8 +847,5 @@
         for (RelationMember m : r.getMembers())
         {
-            if(m.getMember() == null) {
-                //TODO Remove useless nullcheck when RelationMember.member is encalupsed
-                r.putError(tr("Empty member in relation."), true);
-            } else if(m.getMember().isDeleted()) {
+            if (m.getMember().isDeleted()) {
                 r.putError(tr("Deleted member ''{0}'' in relation.",
                         m.getMember().getDisplayName(DefaultNameFormatter.getInstance())), true);
