Index: MemberTableLinkedCellRenderer.java
--- MemberTableLinkedCellRenderer.java Base (BASE)
+++ MemberTableLinkedCellRenderer.java Locally Modified (Based On LOCAL)
@@ -39,7 +39,8 @@
             return;
 
         int ymax=this.getSize().height - 1;
-        int xloop = 8;
+        int xloop = 10;
+        int xowloop = 3;
         int xoff = this.getSize().width / 2;
         if (value.isLoop) {
             xoff -= xloop / 2 - 1;
@@ -90,11 +91,51 @@
 
         /* vertical lines */
         g.setColor(Color.black);
-        g.drawLine(xoff, y1, xoff, y2);
         if (value.isLoop) {
             g.drawLine(xoff+xloop, y1, xoff+xloop, y2);
         }
 
+        if (value.isOnewayHead) {
+            g.setColor(Color.green);
+            y1 = 6;
+            g.drawImage(corners,xoff-xowloop,y1-3,xoff-xowloop+3,y1, 0,0,3,3, new Color(0,0,0,0), null);
+            g.drawImage(corners,xoff+xowloop-2,y1-3,xoff+xowloop+1,y1, 2,0,5,3, new Color(0,0,0,0), null);
+            g.drawLine(xoff-xowloop+3,y1-3,xoff+xowloop-3,y1-3);
+
+            g.setColor(Color.black);
+            if(value.linkPrev) g.drawLine(xoff, 0, xoff, y1-3);
+        }
+
+        if(value.isOnewayTail){
+            g.setColor(Color.green);
+            y2 = ymax - 6;
+            g.drawLine(xoff-xowloop, y2, xoff-xowloop, y2+2);
+            g.drawImage(corners,xoff-xowloop,y2+1,xoff-xowloop+3,y2+4, 0,2,3,5, new Color(0,0,0,0), null);
+            g.drawImage(corners,xoff+xowloop-2,y2+1,xoff+xowloop+1,y2+4, 2,2,5,5, new Color(0,0,0,0), null);
+            g.drawLine(xoff-xowloop+3,y2+3,xoff+xowloop-3,y2+3);
+
+            g.setColor(Color.black);
+            if(value.linkNext) g.drawLine(xoff, y2+3, xoff, ymax+4);
+        }
+
+        if (value.isOnewayLoopForwardPart || value.isOnewayLoopBackwardPart) {
+            g.setColor(Color.green);
+            g.drawLine(xoff+xowloop, y1, xoff+xowloop, y2);
+            g.drawLine(xoff-xowloop, y1, xoff-xowloop, y2);
+        }
+
+        g.setColor(Color.black);
+        if (!value.isOnewayLoopForwardPart && !value.isOnewayLoopBackwardPart){
+            g.drawLine(xoff, y1, xoff, y2);
+        }
+        if (value.isOnewayLoopForwardPart) {
+            g.drawLine(xoff-xowloop, y1, xoff-xowloop, y2);
+        }
+        if (value.isOnewayLoopBackwardPart) {
+            g.drawLine(xoff+xowloop, y1, xoff+xowloop, y2);
+        }
+        
+
         /* special icons */
         Image arrow = null;
         switch (value.direction) {
@@ -105,13 +146,34 @@
             arrow = arrowUp;
             break;
         }
-        if ((arrow != null) && (value.linkPrev || value.linkNext)) {
-            g.drawImage(arrow, xoff-3, (y1 + y2) / 2 - 2, null);
-        }
-        else if (value.direction == Direction.ROUNDABOUT_LEFT) {
+        if (value.direction == Direction.ROUNDABOUT_LEFT) {
             g.drawImage(roundabout_left, xoff-6, 1, null);
         } else if (value.direction == Direction.ROUNDABOUT_RIGHT) {
             g.drawImage(roundabout_right, xoff-6, 1, null);
         }
+
+        if (!value.isOnewayLoopForwardPart && !value.isOnewayLoopBackwardPart &&
+                (arrow != null)) {
+            g.drawImage(arrow, xoff-3, (y1 + y2) / 2 - 2, null);
     }
+
+        if (value.isOnewayLoopForwardPart) {
+            if ((arrow != null)) {
+                g.drawImage(arrow, xoff-xowloop-3, (y1 + y2) / 2 - 2, null);
 }
+        }
+
+        if (value.isOnewayLoopBackwardPart) {
+            if(value.isOnewayLoopForwardPart) {
+                if(arrow == arrowDown)
+                    arrow = arrowUp;
+                else if (arrow == arrowUp)
+                    arrow = arrowDown;
+            }
+
+            if ((arrow != null)) {
+                g.drawImage(arrow, xoff+xowloop-3, (y1 + y2) / 2 - 2, null);
+            }
+        }
+    }
+}
Index: MemberTableModel.java
--- MemberTableModel.java Base (BASE)
+++ MemberTableModel.java Locally Modified (Based On LOCAL)
@@ -795,7 +795,7 @@
      *
      * Else the direction is given as follows:
      * Let the relation be a route of oneway streets, and someone travels them in the given order.
-     * Direction is FORWARD if it is legel and BACKWARD if it is illegal to do so for the given way.
+     * Direction is FORWARD if it is legal and BACKWARD if it is illegal to do so for the given way.
      *
      **/
     private Direction determineDirection(int ref_i,Direction ref_direction, int k) {
@@ -940,6 +940,10 @@
         int firstGroupIdx=0;
         boolean resetFirstGoupIdx=false;
 
+        Integer firstOnewayGroupIdx=null;
+        boolean isReversePart = false;
+        Integer lastForwardPart = null;
+
         for (int i=0; i<members.size(); ++i) {
             if (resetFirstGoupIdx) {
                 firstGroupIdx = i;
@@ -960,14 +964,52 @@
                 continue;
             }
 
+            if (isOneway(m)) {
+                if(firstOnewayGroupIdx == null){
+                    firstOnewayGroupIdx = i;
+                    isReversePart = false;
+                }
+            } else {
+                isReversePart = false;
+                firstOnewayGroupIdx = null;
+                if(i > 0 && !con.get(i-1).isOnewayTail && (con.get(i-1).isOnewayLoopBackwardPart
+                        || con.get(i-1).isOnewayLoopForwardPart))
+                    firstGroupIdx = i;
+            }
+
             boolean linkPrev = (i != firstGroupIdx);
             boolean linkNext;
             Direction dir;
             if (linkPrev) {
-                dir = determineDirection(i-1, con.get(i-1).direction, i);
+                Direction refDir = con.get(i-1).direction;
+                
+                dir = determineDirection(i-1, refDir, i);
                 linkNext = (determineDirection(i, dir, i+1) != NONE);
+                
+                if(firstOnewayGroupIdx != null && !isReversePart) { //oneway loop - forward part
+                    Direction dirow = NONE;
+                    if (con.get(firstOnewayGroupIdx) != null)
+                        dirow = reverse(con.get(firstOnewayGroupIdx).direction);
+                    else //first in oneway loop
+                        dirow = reverse(dir);
+                
+                    if (firstOnewayGroupIdx != i && determineDirection(firstOnewayGroupIdx, dirow, i) != NONE) { // start of backward part
+                        dir = determineDirection(firstOnewayGroupIdx, dirow, i);
+                        linkNext = (determineDirection(i, dir, i+1) != NONE);
+                        lastForwardPart = i-1;
+                        isReversePart = true;
             }
-            else {
+
+                    if (determineDirection(firstOnewayGroupIdx, dirow, i+1) != NONE) {
+                        linkNext = true;
+                    }
+                }
+                    
+            } else {
+                if (isOneway(m)){
+                    if(m.getRole().equals("backward")) dir = BACKWARD;
+                    else dir = FORWARD;
+                } else
                 if (roundaboutType(i) != NONE) {
                     dir = determineDirection(i, roundaboutType(i), i+1) != NONE ? roundaboutType(i) : NONE;
                 } else { /** guess the direction and see if it fits with the next member */
@@ -987,12 +1029,29 @@
 
             con.set(i, new WayConnectionType(linkPrev, linkNext, dir));
 
+            if (isOneway(m)) {
+                if (firstOnewayGroupIdx == i) {
+                    con.get(i).isOnewayHead = true;
+                    con.get(i).isOnewayLoopForwardPart = true;
+                }
+
+                if(isReversePart) con.get(i).isOnewayLoopBackwardPart = true;
+                else con.get(i).isOnewayLoopForwardPart = true;
+
+                if(lastForwardPart != null && determineDirection(i, dir, lastForwardPart) != NONE){
+                    con.get(i).isOnewayTail = true;
+                    firstOnewayGroupIdx = null;  
+                }
+            }
+
             if (! linkNext) {
                 boolean loop;
-                if (i == firstGroupIdx) {
-                    loop = determineDirection(i, FORWARD, i) == FORWARD;
+                int lastGroupIdx = i;
+                if(isOneway(m) && lastForwardPart != null) lastGroupIdx = lastForwardPart;
+                if (lastGroupIdx == firstGroupIdx) { //is primitive loop
+                    loop = determineDirection(lastGroupIdx, FORWARD, lastGroupIdx) == FORWARD;
                 } else {
-                    loop = determineDirection(i, dir, firstGroupIdx) == con.get(firstGroupIdx).direction;
+                    loop = determineDirection(lastGroupIdx, con.get(lastGroupIdx).direction, firstGroupIdx) == con.get(firstGroupIdx).direction;
                 }
                 if (loop) {
                     for (int j=firstGroupIdx; j <= i; ++j) {
@@ -1007,4 +1066,14 @@
         //            System.err.println(con.get(i));
         //        }
     }
+
+    private static Direction reverse(Direction dir){
+        if(dir == FORWARD) return BACKWARD;
+        if(dir == BACKWARD) return FORWARD;
+        return dir;
 }
+
+    public static boolean isOneway(RelationMember m){
+        return m.getRole().equals("forward") || m.getRole().equals("backward");
+    }
+}
Index: RelationNodeMap.java
--- RelationNodeMap.java Base (BASE)
+++ RelationNodeMap.java Locally Modified (Based On LOCAL)
@@ -4,9 +4,7 @@
 import static org.openstreetmap.josm.gui.dialogs.relation.WayConnectionType.Direction.NONE;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
 import java.util.TreeMap;
 import java.util.TreeSet;
 
@@ -35,15 +33,35 @@
     private TreeMap<Node, TreeSet<Integer>> nodesMap;
     private TreeMap<Integer, TreeSet<Node>> waysMap;
     /*
+     * Maps for oneways (forward/backward roles)
+     */
+    private TreeMap<Node, TreeSet<Integer>> nodesOnewayMap = new TreeMap<Node, TreeSet<Integer>>();;
+    private TreeMap<Integer, TreeSet<Node>> waysOnewayMap = new TreeMap<Integer, TreeSet<Node>>();
+    private TreeMap<Node, TreeSet<Integer>> nodesOnewayReverseMap = new TreeMap<Node, TreeSet<Integer>>();;
+    private TreeMap<Integer, TreeSet<Node>> waysOnewayReverseMap = new TreeMap<Integer, TreeSet<Node>>();
+    /*
      * Used to keep track of what members are done.
      */
     private TreeSet<Integer> remaining;
+    private TreeMap<Integer, TreeSet<Node>> remainingOneway = new TreeMap<Integer, TreeSet<Node>>();;
 
     /**
      * All members that are incomplete or not a way
      */
     private List<Integer> notSortable = new ArrayList<Integer>();
 
+    private static Node firstOnewayNode(RelationMember m){
+        if(!m.isWay()) return null;
+        if(m.getRole().equals("backward")) return m.getWay().lastNode();
+        return m.getWay().firstNode();
+    }
+
+    private static Node lastOnewayNode(RelationMember m){
+        if(!m.isWay()) return null;
+        if(m.getRole().equals("backward")) return m.getWay().firstNode();
+        return m.getWay().lastNode();
+    }
+
     RelationNodeMap(List<RelationMember> members) {
         nodesMap = new TreeMap<Node, TreeSet<Integer>>();
         waysMap = new TreeMap<Integer, TreeSet<Node>>();
@@ -56,11 +74,20 @@
             }
             else {
                 Way w = m.getWay();
-                if (MemberTableModel.roundaboutType(w) != NONE) {
+                if((MemberTableModel.roundaboutType(w) != NONE) || MemberTableModel.isOneway(m)) {
+                    if ((MemberTableModel.roundaboutType(w) != NONE) || w.firstNode() == w.lastNode()) {
                     for (Node nd : w.getNodes()) {
                         addPair(nd, i);
                     }
                 } else {
+                        addNodeWayMap(firstOnewayNode(m), i);
+                        addWayNodeMap(lastOnewayNode(m), i);
+                        addNodeWayMapReverse(lastOnewayNode(m), i);
+                        addWayNodeMapReverse(firstOnewayNode(m), i);
+                        addRemainingForward(firstOnewayNode(m), i);
+                        addRemainingForward(lastOnewayNode(m), i);
+                    }
+                } else {
                     addPair(w.firstNode(), i);
                     addPair(w.lastNode(), i);
                 }
@@ -68,30 +95,28 @@
         }
 
         remaining = new TreeSet<Integer>();
-        for (Integer k : waysMap.keySet()) {
-            remaining.add(k);
-        }
+        remaining.addAll(waysMap.keySet());
 
         /*
          * Clean up the maps, i.e. remove nodes from roundabouts and dead ends that
          * cannot be used in future. (only for performance)
          */
-        Iterator<Map.Entry<Node,TreeSet<Integer>>> it = nodesMap.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry<Node,TreeSet<Integer>> nodeLinks = it.next();
-
-            if (nodeLinks.getValue().size() < 2) {
-                if (nodeLinks.getValue().size() != 1) throw new AssertionError();
-
-                Integer d_way = nodeLinks.getValue().iterator().next();
-                TreeSet<Node> d_way_nodes = waysMap.get(d_way);
-                d_way_nodes.remove(nodeLinks.getKey());
-
-                it.remove();
-                continue;
+//        Iterator<Map.Entry<Node,TreeSet<Integer>>> it = nodesMap.entrySet().iterator();
+//        while (it.hasNext()) {
+//            Map.Entry<Node,TreeSet<Integer>> nodeLinks = it.next();
+//
+//            if (nodeLinks.getValue().size() < 2) {
+//                if (nodeLinks.getValue().size() != 1) throw new AssertionError();
+//
+//                Integer d_way = nodeLinks.getValue().iterator().next();
+//                TreeSet<Node> d_way_nodes = waysMap.get(d_way);
+//                d_way_nodes.remove(nodeLinks.getKey());
+//
+//                it.remove();
+//                continue;
+//            }
+//        }
             }
-        }
-    }
 
     private void addPair(Node n, int i) {
         TreeSet<Integer> ts = nodesMap.get(n);
@@ -109,22 +134,157 @@
         ts2.add(n);
     }
 
+    private void addNodeWayMap(Node n, int i) {
+        TreeSet<Integer> ts = nodesOnewayMap.get(n);
+        if (ts == null) {
+            ts = new TreeSet<Integer>();
+            nodesOnewayMap.put(n, ts);
+        }
+        ts.add(i);
+    }
+
+    private void addWayNodeMap(Node n, int i) {
+        TreeSet<Node> ts2 = waysOnewayMap.get(i);
+        if (ts2 == null) {
+            ts2 = new TreeSet<Node>();
+            waysOnewayMap.put(i, ts2);
+        }
+        ts2.add(n);
+    }
+
+    private void addNodeWayMapReverse(Node n, int i) {
+        TreeSet<Integer> ts = nodesOnewayReverseMap.get(n);
+        if (ts == null) {
+            ts = new TreeSet<Integer>();
+            nodesOnewayReverseMap.put(n, ts);
+        }
+        ts.add(i);
+    }
+
+    private void addWayNodeMapReverse(Node n, int i) {
+        TreeSet<Node> ts2 = waysOnewayReverseMap.get(i);
+        if (ts2 == null) {
+            ts2 = new TreeSet<Node>();
+            waysOnewayReverseMap.put(i, ts2);
+        }
+        ts2.add(n);
+    }
+
+    private void addRemainingForward(Node n, int i) {
+        TreeSet<Node> ts2 = remainingOneway.get(i);
+        if (ts2 == null) {
+            ts2 = new TreeSet<Node>();
+            remainingOneway.put(i, ts2);
+        }
+        ts2.add(n);
+    }
+
+    Integer firstOneway = null;
+    Node lastOnewayNode = null;
+
     /**
      * Return a relation member that is linked to the
-     * member 'i', but has not been popped jet.
+     * member 'i', but has not been popped yet.
      * Return null if there is no such member left.
      */
     public Integer popAdjacent(Integer i) {
-        TreeSet<Node> nodes = waysMap.get(i);
+        System.out.println ("i: " + i);
+        if (firstOneway != null) return popOnewayAdjacent(i);
+
+        TreeSet<Node> nodes = new TreeSet<Node>();
+        if (waysMap.containsKey(i)) nodes.addAll(waysMap.get(i));
         for (Node n : nodes) {
             TreeSet<Integer> adj = nodesMap.get(n);
-            if (!adj.isEmpty()) {
+            if (adj != null && !adj.isEmpty()) {
                 Integer j = adj.iterator().next();
                 done(j);
                 waysMap.get(j).remove(n);
                 return j;
             }
         }
+
+        for (Node n : nodes) {
+            TreeSet<Integer> adj = nodesOnewayMap.get(n);
+            if (adj != null && !adj.isEmpty()) {
+                Integer j = adj.iterator().next();
+                doneOneway(j);
+                firstOneway = j;
+                waysOnewayMap.get(j).remove(n);
+                return j;
+            }
+        }
+        
+        firstOneway = i;
+        return popOnewayAdjacent(i);
+    }
+
+    private Integer popOnewayAdjacent(Integer i) {
+        if (lastOnewayNode == null) { //Forward part
+            TreeSet<Node> nodes = new TreeSet<Node>();
+                if (waysOnewayMap.containsKey(i)) nodes.addAll(waysOnewayMap.get(i));
+                for (Node n : nodes) {
+                    TreeSet<Integer> adj = nodesOnewayMap.get(n);
+                    if (adj != null && !adj.isEmpty()) {
+                        Integer j = adj.iterator().next();
+
+                        TreeSet<Node> nodes1 = new TreeSet<Node>();
+                        if (waysOnewayReverseMap.containsKey(j)) nodes1.addAll(waysOnewayReverseMap.get(j));
+                        for (Node n1 : nodes1) {
+                            if(nodesMap.containsKey(n1) || (nodesOnewayMap.containsKey(n1) && nodesOnewayMap.get(n1).size() > 1)) {
+                                lastOnewayNode = n1;
+                                i = firstOneway;
+                                break;
+                            }
+                        }
+
+                        if (lastOnewayNode == null){
+                            waysOnewayMap.get(j).remove(n);
+                            doneOneway(j);
+                            return j;
+                        }
+                    }
+            }
+        }
+
+        if (lastOnewayNode != null) { //Backward part
+            TreeSet<Node> nodes = new TreeSet<Node>();
+            if (waysOnewayReverseMap.containsKey(i)) nodes.addAll(waysOnewayReverseMap.get(i));
+            if (waysMap.containsKey(i)) nodes.addAll(waysMap.get(i));
+            for (Node n : nodes) {
+                if(n == lastOnewayNode) {
+                    firstOneway = null;
+                    lastOnewayNode = null;
+                    TreeSet<Integer> adj = nodesMap.get(n);
+                    if (adj != null && !adj.isEmpty()) {
+                        Integer j = adj.iterator().next();
+                        waysMap.get(j).remove(n);
+                        done(j);
+                        return j;
+                    }
+
+                    adj = nodesOnewayMap.get(n);
+                    if (adj != null && !adj.isEmpty()) {
+                        Integer j = adj.iterator().next();
+                        doneOneway(j);
+                        firstOneway = j;
+                        waysOnewayMap.get(j).remove(n);
+                        return j;
+                    }
+                }
+
+                TreeSet<Integer> adj = nodesOnewayReverseMap.get(n);
+                if (adj != null && !adj.isEmpty()) {
+                    Integer j = adj.iterator().next();
+                    waysOnewayReverseMap.get(j).remove(n);
+                    doneOneway(j);
+                    return j;
+                }
+            }
+        }
+
+        firstOneway = null;
+        lastOnewayNode = null;
+        
         return null;
     }
 
@@ -133,16 +293,31 @@
      * every sortable member has been processed.
      */
     public Integer pop() {
-        if (remaining.isEmpty()) return null;
+        if (!remaining.isEmpty()){
         Integer i = remaining.iterator().next();
         done(i);
         return i;
     }
 
+        if (remainingOneway.isEmpty()) return null;
+        Integer i = remainingOneway.keySet().iterator().next();
+        doneOneway(i);
+        return i;
+    }
+
     /**
      * This relation member has been processed.
      * Remove references in the nodesMap.
      */
+    private void doneOneway(Integer i) {
+        TreeSet<Node> nodesForward = remainingOneway.get(i);
+        for (Node n : nodesForward) {
+            if(nodesOnewayMap.containsKey(n)) nodesOnewayMap.get(n).remove(i);
+            if(nodesOnewayReverseMap.containsKey(n)) nodesOnewayReverseMap.get(n).remove(i);
+        }
+        remainingOneway.remove(i);
+    }
+
     private void done(Integer i) {
         remaining.remove(i);
         TreeSet<Node> nodes = waysMap.get(i);
Index: WayConnectionType.java
--- WayConnectionType.java Base (BASE)
+++ WayConnectionType.java Locally Modified (Based On LOCAL)
@@ -35,6 +35,11 @@
     /** True, if the element is part of a closed loop of ways. */
     public boolean isLoop;
 
+    public boolean isOnewayLoopForwardPart = false;
+    public boolean isOnewayLoopBackwardPart = false;
+    public boolean isOnewayHead = false;
+    public boolean isOnewayTail = false;
+
     public boolean isRoundabout = false;
 
     public WayConnectionType(boolean linkPrev, boolean linkNext, Direction direction) {
