All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openstreetmap.atlas.checks.validation.points.LoneNodeCheck Maven / Gradle / Ivy

There is a newer version: 6.3.12
Show newest version
package org.openstreetmap.atlas.checks.validation.points;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

import org.openstreetmap.atlas.checks.base.BaseCheck;
import org.openstreetmap.atlas.checks.flag.CheckFlag;
import org.openstreetmap.atlas.geography.atlas.items.Area;
import org.openstreetmap.atlas.geography.atlas.items.AtlasObject;
import org.openstreetmap.atlas.geography.atlas.items.LineItem;
import org.openstreetmap.atlas.geography.atlas.items.Point;
import org.openstreetmap.atlas.tags.HighwayTag;
import org.openstreetmap.atlas.tags.RailwayTag;
import org.openstreetmap.atlas.utilities.configuration.Configuration;

/**
 * This check verifies lone {@link Point}s with highway tag that they follow the tagging principles.
 *
 * @author mm-ciub
 */
public class LoneNodeCheck extends BaseCheck
{
    private static final long serialVersionUID = -1489101405354234053L;

    private static final List DEFAULT_HIGHWAY_VALUES_CHECKED = List.of("crossing",
            "turning_circle", "traffic_signals", "stop", "give_way", "motorway_junction",
            "mini_roundabout", "passing_place", "turning_loop");
    private static final Predicate HAS_HIGHWAY_RAILWAY = obj -> obj
            .getTag(HighwayTag.KEY).isPresent() || obj.getTag(RailwayTag.KEY).isPresent();
    private static final String LONE_NODE_INSTRUCTION = "This node {0,number,#} has a Highway tag but is not part of any way that has a highway or railway tag. Either add such a tag to the appropriate parent or remove the highway tag from the node.";
    private static final List FALLBACK_INSTRUCTIONS = Collections
            .singletonList(LONE_NODE_INSTRUCTION);

    private List highwayValuesToCheck;

    /**
     * Default constructor.
     *
     * @param configuration
     *            the JSON configuration for this check
     */

    public LoneNodeCheck(final Configuration configuration)
    {
        super(configuration);
        this.highwayValuesToCheck = this
                .configurationValue(configuration, "valid.highway.tag",
                        DEFAULT_HIGHWAY_VALUES_CHECKED)
                .stream().map(String::toLowerCase).collect(Collectors.toList());
    }

    /**
     * The object is valid if it is a Node and has a highway tag with specific values.
     *
     * @param object
     *            the atlas object supplied by the Atlas-Checks framework for evaluation
     * @return {@code true} if this object should be checked
     */
    @Override
    public boolean validCheckForObject(final AtlasObject object)
    {
        final Optional highwayValue = object.getTag(HighwayTag.KEY);
        return object instanceof Point && highwayValue.isPresent()
                && this.highwayValuesToCheck.contains(highwayValue.get())
                && !this.isFlagged(object.getOsmIdentifier());
    }

    @Override
    protected Optional flag(final AtlasObject object)
    {
        this.markAsFlagged(object.getOsmIdentifier());

        if (this.isLoneNode(object))
        {
            return Optional.of(this.createFlag(object,
                    this.getLocalizedInstruction(0, object.getOsmIdentifier())));
        }
        return Optional.empty();
    }

    @Override
    protected List getFallbackInstructions()
    {
        return FALLBACK_INSTRUCTIONS;
    }

    /**
     * Check if there are no connected ways with highway or railway tag.
     *
     * @param object
     *            to be checked
     * @return true if no way is found
     */
    @SuppressWarnings("unchecked")
    private boolean isLoneNode(final AtlasObject object)
    {
        final var atlas = object.getAtlas();
        final var pointLocation = ((Point) object).getLocation();
        final Iterable connectedLines = atlas.lineItemsContaining(pointLocation,
                (Predicate) HAS_HIGHWAY_RAILWAY);
        final Iterable connectedAreas = atlas.areasCovering(pointLocation,
                (Predicate) HAS_HIGHWAY_RAILWAY);
        return StreamSupport.stream(connectedAreas.spliterator(), false).count() == 0
                && StreamSupport.stream(connectedLines.spliterator(), false).count() == 0;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy