src/main/java/de/blau/android/osm/StorageDelegator.java
/**
     * Given the existing relation membership of a way, add a split off way to the same ones
     * 
     * @param way the existing Way
     * @param wasClosed indicate if the existing way was closed
     * @param newWay the new Way
     * @param changedElements add changed Relations to this
     * @return a Set containing any issues
     */
Given the existing relation membership of a way, add a split off way to the same ones


Given the existing relation membership of a way add a split off way to the same ones
@NonNull
    private List<Result> addSplitWayToRelations(@NonNull final Way way, boolean wasClosed, @NonNull Way newWay, @NonNull List<OsmElement> changedElements) {
        List<Result> result = new ArrayList<>();
        if (way.getParentRelations() != null) {
            Set<Relation> relations = new HashSet<>(way.getParentRelations()); 
            dirty = true;
            /*
             * iterate through relations, for all except restrictions add the new way to the relation, for now simply
             * after the old way
             */
            for (Relation r : relations) {
                Log.d(DEBUG_TAG, "addSplitWayToRelations processing relation (#" + r.getOsmId() + "/" + relations.size() + ")");
                List<RelationMember> members = r.getAllMembers(way);
                if (members.isEmpty()) {
                    Log.d(DEBUG_TAG, "Unconsistent state detected way " + way.getOsmId() + " should be relation member");
                    ACRAHelper.nocrashReport(null, "Unconsistent state detected way " + way.getOsmId() + " should be relation member");
                    continue;
                }
                undo.save(r);
                String type = r.getTagWithKey(Tags.KEY_TYPE);
                boolean isRoute = Tags.VALUE_ROUTE.equals(type);
                boolean isRestrictionLike = Tags.VALUE_RESTRICTION.equals(type)
                        || (!Tags.VALUE_MULTIPOLYGON.equals(type) && !Tags.VALUE_BOUNDARY.equals(type) && !isRoute && hasFromViaTo(r));
                for (RelationMember rm : members) {
                    Log.d(DEBUG_TAG, "addSplitWayToRelations member " + rm);
                    int memberPos = r.getPosition(rm);
                    String role = rm.getRole();
                    boolean isVia = Tags.isVia(type, role);
                    if (isRestrictionLike && !isVia) {
                        List<RelationMember> rl = Tags.getVia(type, r);
                        boolean foundVia = false;
                        for (int j = 0; j < rl.size(); j++) {
                            RelationMember viaRm = rl.get(j);
                            OsmElement viaE = viaRm.getElement();
                            if (viaE instanceof Node) {
                                if (((Way) rm.getElement()).hasNode((Node) viaE)) {
                                    foundVia = true;
                                }
                            } else if (viaE instanceof Way && ((Way) rm.getElement()).hasCommonNode((Way) viaE)) {
                                foundVia = true;
                            }
                        }
                        Log.d(DEBUG_TAG, "addSplitWayToRelations foundVia " + foundVia);
                        if (!foundVia) {
                            replaceMemberWay(r, rm, way, newWay);
                        }
                    } else if (isRestrictionLike && isVia && wasClosed) {
                        List<RelationMember> fromMembers = r.getMembersWithRole(Tags.ROLE_FROM);
                        if (fromMembers != null && fromMembers.size() == 1) {
                            OsmElement fromElement = fromMembers.get(0).getElement();
                            if (fromElement instanceof Way) {
                                if (((Way) fromElement).hasNode(newWay.getFirstNode())) { 
                                    replaceMemberWay(r, rm, way, newWay);
                                }
                            }
                        }
                    } else { 
                        RelationMember newMember = new RelationMember(rm.getRole(), newWay); 
                        RelationMember prevMember = r.getMemberAt(memberPos - 1);
                        RelationMember nextMember = r.getMemberAt(memberPos + 1);
                        /*
                         * We need to determine if to insert the new way before or after the existing member If the new
                         * way has a common node with the previous member or if the existing way has a common node with
                         * the following member we insert before, otherwise we insert after the existing member.
                         * 
                         * FIXME To do this really properly we would have to download the previous and next elements for
                         * routes
                         */
                        if (hasCommonNode(prevMember, newWay)) {
                            r.addMemberBefore(rm, newMember);
                        } else if (hasCommonNode(nextMember, way)) {
                            r.addMemberBefore(rm, newMember);
                        } else {
                            r.addMemberAfter(rm, newMember);
                            boolean hasPrev = prevMember != null;
                            boolean hasNext = nextMember != null;
                            if (isRoute && (hasPrev || hasNext) && (!hasPrev || !prevMember.downloaded()) && (!hasNext || !nextMember.downloaded())) {
                                Log.w(DEBUG_TAG, "Incomplete route relation " + r.getOsmId() + " modified");
                                Result relationResult = new Result();
                                relationResult.setElement(r);
                                relationResult.addIssue(SplitIssue.SPLIT_ROUTE_ORDERING);
                                result.add(relationResult);
                            }
                        }
                        newWay.addParentRelation(r);
                    }
                }
                r.updateState(OsmElement.STATE_MODIFIED);
                apiStorage.insertElementSafe(r);
                changedElements.add(r);
            }
        }
        return result;
    }
@ NonNull private List < Result > addSplitWayToRelations ( @ NonNull final Way way , boolean wasClosed , @ NonNull Way newWay , @ NonNull List < OsmElement > changedElements ) { List < Result > result = new ArrayList < > ( ) ; if ( way . getParentRelations ( ) != null ) { Set < Relation > relations = new HashSet < > ( way . getParentRelations ( ) ) ; dirty = true ; /*
             * iterate through relations, for all except restrictions add the new way to the relation, for now simply
             * after the old way
             */ for ( Relation r : relations ) { Log . d ( DEBUG_TAG , "addSplitWayToRelations processing relation (#" + r . getOsmId ( ) + "/" + relations . size ( ) + ")" ) ; List < RelationMember > members = r . getAllMembers ( way ) ; if ( members . isEmpty ( ) ) { Log . d ( DEBUG_TAG , "Unconsistent state detected way " + way . getOsmId ( ) + " should be relation member" ) ; ACRAHelper . nocrashReport ( null , "Unconsistent state detected way " + way . getOsmId ( ) + " should be relation member" ) ; continue ; } undo . save ( r ) ; String type = r . getTagWithKey ( Tags . KEY_TYPE ) ; boolean isRoute = Tags . VALUE_ROUTE . equals ( type ) ; boolean isRestrictionLike = Tags . VALUE_RESTRICTION . equals ( type ) || ( ! Tags . VALUE_MULTIPOLYGON . equals ( type ) && ! Tags . VALUE_BOUNDARY . equals ( type ) && ! isRoute && hasFromViaTo ( r ) ) ; for ( RelationMember rm : members ) { Log . d ( DEBUG_TAG , "addSplitWayToRelations member " + rm ) ; int memberPos = r . getPosition ( rm ) ; String role = rm . getRole ( ) ; boolean isVia = Tags . isVia ( type , role ) ; if ( isRestrictionLike && ! isVia ) { List < RelationMember > rl = Tags . getVia ( type , r ) ; boolean foundVia = false ; for ( int j = 0 ; j < rl . size ( ) ; j ++ ) { RelationMember viaRm = rl . get ( j ) ; OsmElement viaE = viaRm . getElement ( ) ; if ( viaE instanceof Node ) { if ( ( ( Way ) rm . getElement ( ) ) . hasNode ( ( Node ) viaE ) ) { foundVia = true ; } } else if ( viaE instanceof Way && ( ( Way ) rm . getElement ( ) ) . hasCommonNode ( ( Way ) viaE ) ) { foundVia = true ; } } Log . d ( DEBUG_TAG , "addSplitWayToRelations foundVia " + foundVia ) ; if ( ! foundVia ) { replaceMemberWay ( r , rm , way , newWay ) ; } } else if ( isRestrictionLike && isVia && wasClosed ) { List < RelationMember > fromMembers = r . getMembersWithRole ( Tags . ROLE_FROM ) ; if ( fromMembers != null && fromMembers . size ( ) == 1 ) { OsmElement fromElement = fromMembers . get ( 0 ) . getElement ( ) ; if ( fromElement instanceof Way ) { if ( ( ( Way ) fromElement ) . hasNode ( newWay . getFirstNode ( ) ) ) { replaceMemberWay ( r , rm , way , newWay ) ; } } } } else { RelationMember newMember = new RelationMember ( rm . getRole ( ) , newWay ) ; RelationMember prevMember = r . getMemberAt ( memberPos - 1 ) ; RelationMember nextMember = r . getMemberAt ( memberPos + 1 ) ; /*
                         * We need to determine if to insert the new way before or after the existing member If the new
                         * way has a common node with the previous member or if the existing way has a common node with
                         * the following member we insert before, otherwise we insert after the existing member.
                         * 
                         * FIXME To do this really properly we would have to download the previous and next elements for
                         * routes
                         */ if ( hasCommonNode ( prevMember , newWay ) ) { r . addMemberBefore ( rm , newMember ) ; } else if ( hasCommonNode ( nextMember , way ) ) { r . addMemberBefore ( rm , newMember ) ; } else { r . addMemberAfter ( rm , newMember ) ; boolean hasPrev = prevMember != null ; boolean hasNext = nextMember != null ; if ( isRoute && ( hasPrev || hasNext ) && ( ! hasPrev || ! prevMember . downloaded ( ) ) && ( ! hasNext || ! nextMember . downloaded ( ) ) ) { Log . w ( DEBUG_TAG , "Incomplete route relation " + r . getOsmId ( ) + " modified" ) ; Result relationResult = new Result ( ) ; relationResult . setElement ( r ) ; relationResult . addIssue ( SplitIssue . SPLIT_ROUTE_ORDERING ) ; result . add ( relationResult ) ; } } newWay . addParentRelation ( r ) ; } } r . updateState ( OsmElement . STATE_MODIFIED ) ; apiStorage . insertElementSafe ( r ) ; changedElements . add ( r ) ; } } return result ; }
Given the existing relation membership of a way, add a split off way to the same ones
Given the existing relation membership of a way add a split off way to the same ones
// check for relation membership // copy and only unique relations! // determine if the relation is potentially like a restriction, as hasFromViaTo is fairly expensive // avoid calling it if we are sure that it can't be restriction like // attempt to handle turn restrictions correctly, if element is the via way, copying relation // membership to both is ok // check if the old way has a node in common with the via relation member, if no assume the // new way has // very rough check // swap // default handling of relations membership // use the same role