/** * @param relation * The {@link Relation} for which to create seeds for * @return an array of identifiers corresponding to the first unused identifier for each * relation member in the given Relation */ private long[] createIdentifierSeeds(final Relation relation) { // Assume any member can be split, so create a seed for each one final long[] seeds = new long[relation.members().size()]; for (int seedIndex = 0; seedIndex < seeds.length; seedIndex++) { long identifier = relation.members().get(seedIndex).getEntity().getIdentifier(); final long originalAtlasIdentifier = new ReverseIdentifierFactory() .getFirstAtlasIdentifier(identifier); final Set<Long> createdWaysForIdentifier = this.slicedPointAndLineChanges .getDeletedToCreatedLineMapping().get(originalAtlasIdentifier); if (createdWaysForIdentifier != null) { // Grab the first Atlas identifier for this entity and increment at offset identifier = identifier + createdWaysForIdentifier.size() * CountrySlicingIdentifierFactory.IDENTIFIER_SCALE; } seeds[seedIndex] = identifier; } return seeds; }
private Stream<AtlasItem> leafMembers() { final Stream<AtlasItem> nonRelationMembers = members().stream() .map(RelationMember::getEntity).filter(entity -> !(entity instanceof Relation)) .map(entity -> (AtlasItem) entity); final Stream<AtlasItem> relationMembers = members().stream().map(RelationMember::getEntity) .filter(entity -> entity instanceof Relation).map(entity -> (Relation) entity) .flatMap(Relation::leafMembers); return Stream.concat(nonRelationMembers, relationMembers); } }
@Override public RelationMemberList allKnownOsmMembers() { final List<RelationMember> members = new ArrayList<>(); for (final Relation candidate : multiAtlas() .relationAllRelationsWithSameOsmIdentifier(this.identifier)) { candidate.members().forEach(relationMember -> members.add(relationMember)); } return new RelationMemberList(members); }
/** * Assign this {@link CompleteRelation} with members. * <p> * In case this {@link CompleteRelation} is created from an existing relation, and the new * member list has had some existing members removed, use * {@link #withMembersAndSource(RelationMemberList, Relation)} * * @param members * The full members of the Relation * @return This */ public CompleteRelation withMembers(final RelationMemberList members) { return withMembers(members.asBean(), members.bounds()); }
if (this.getMemberList().size() != that.getMemberList().size()) for (final RelationMember thisMember : this.members) final RelationMember thatMember = that.get(index++); if (thisMember == null && thatMember != null || thisMember != null && thatMember == null)
@Test public void testRemoveRelationMemberIsReflectedInMemberListAutomatically() { final Atlas atlas = this.rule.getAtlas(); final ChangeBuilder changeBuilder = new ChangeBuilder(); final Relation disconnectedFeatures = atlas.relation(41834000000L); // Remove the point from the list final RelationMemberList newMembers = new RelationMemberList(disconnectedFeatures.members() .stream().filter(member -> !(member.getEntity() instanceof Point)) .collect(Collectors.toList())); // Here only remove the point. Do not remove the member in the relation. It should // automatically be removed. changeBuilder.add(new FeatureChange(ChangeType.REMOVE, CompletePoint.shallowFrom(atlas.point(41822000000L)))); final Change change = changeBuilder.get(); final Atlas changeAtlas = new ChangeAtlas(atlas, change); Assert.assertEquals(newMembers.asBean(), changeAtlas.relation(41834000000L).members().asBean()); final Relation parentRelation = changeAtlas.relation(41860000000L); final Relation fromRelation = (Relation) Iterables.stream(parentRelation.members()) .firstMatching(member -> "child1".equals(member.getRole())).get().getEntity(); Assert.assertEquals(newMembers.asBean(), fromRelation.members().asBean()); }
@Override public RelationMemberList allKnownOsmMembers() { return membersFor(attribute(Relation::allKnownOsmMembers).asBean()); }
final RelationMemberList newMembers = new RelationMemberList(relation.members() .stream().filter(member -> !member.getEntity().equals(edge)) .collect(Collectors.toList())); return CompleteRelation.shallowFrom(relation)
@Test public void testRelationMemberLocationItemInclusion() { // Based on https://www.openstreetmap.org/relation/578254 - the Node in the Relation gets // created as both an Atlas point and node. Let's verify that the Relation consists of both. final Atlas slicedRawAtlas = this.setup.getNodeAndPointAsRelationMemberAtlas(); final CountryBoundaryMap boundaryMap = CountryBoundaryMap .fromPlainText(new InputStreamResource(() -> WaySectionProcessorTest.class .getResourceAsStream("nodeAndPointRelationMemberBoundaryMap.txt"))); final Atlas finalAtlas = new WaySectionProcessor(slicedRawAtlas, AtlasLoadingOption.createOptionWithAllEnabled(boundaryMap)).run(); final RelationMemberList members = finalAtlas.relation(578254000000L).members(); Assert.assertEquals("Six members - 2 pairs of reverse edges, 1 node and 1 point", 6, members.size()); Assert.assertEquals("Single point", 1, members.stream() .filter(member -> member.getEntity().getType() == ItemType.POINT).count()); Assert.assertEquals("Single node", 1, members.stream() .filter(member -> member.getEntity().getType() == ItemType.NODE).count()); }
.forEach(member -> toProcess.add(member.getEntity()));
@Override public LocationIterableProperties toGeoJsonBuildingBlock() { final Map<String, String> tags = getTags(); tags.put("identifier", String.valueOf(getIdentifier())); tags.put("osmIdentifier", String.valueOf(getOsmIdentifier())); tags.put("itemType", String.valueOf(getType())); final Optional<String> shardName = getAtlas().metaData().getShardName(); shardName.ifPresent(shard -> tags.put("shard", shard)); final StringList parentRelations = new StringList(); this.relations().forEach(relation -> { final RelationMember member = relation.members().get(getIdentifier(), getType()); parentRelations.add(member.getRelationIdentifier() + "-" + member.getRole()); }); if (!parentRelations.isEmpty()) { tags.put("parentRelations", parentRelations.join(", ")); } return new GeoJsonBuilder.LocationIterableProperties(getClosedGeometry(), tags); }
private RelationMemberList membersFor(final RelationBean bean) { if (bean == null) { return null; } final List<RelationMember> memberList = new ArrayList<>(); for (final RelationBeanItem item : bean) { memberList.add(new RelationMember(item.getRole(), getAtlas().entity(item.getIdentifier(), item.getType()), getIdentifier())); } final RelationMemberList result = new RelationMemberList(memberList); bean.getExplicitlyExcluded().forEach(result::addItemExplicitlyExcluded); return result; }
@Test public void testShallow() { final Atlas atlas = this.rule.getAtlas(); final Relation source = atlas.relation(22); final CompleteRelation result = CompleteRelation.shallowFrom(source); Assert.assertEquals(source.getIdentifier(), result.getIdentifier()); Assert.assertEquals(source.bounds(), result.bounds()); result.withMembersAndSource(new RelationMemberList(source.members()), source); Assert.assertEquals(source.members().asBean(), result.members().asBean()); result.withMembersAndSource(source.members().asBean(), source, source.bounds()); Assert.assertEquals(source.bounds(), result.bounds()); Assert.assertEquals(source.members().asBean(), result.members().asBean()); result.withAllKnownOsmMembers(source.allKnownOsmMembers().asBean()); Assert.assertEquals(source.allKnownOsmMembers().asBean(), result.allKnownOsmMembers().asBean()); result.withOsmRelationIdentifier(source.osmRelationIdentifier()); Assert.assertEquals(source.osmRelationIdentifier(), result.osmRelationIdentifier()); result.withRelationIdentifiers(source.relations().stream().map(Relation::getIdentifier) .collect(Collectors.toSet())); Assert.assertEquals( source.relations().stream().map(Relation::getIdentifier) .collect(Collectors.toSet()), result.relations().stream().map(Relation::getIdentifier) .collect(Collectors.toSet())); } }
@Override public Relation relation(final long identifier) { final Relation relation = entityFor(identifier, ItemType.RELATION, () -> this.source.relation(identifier), (sourceEntity, overrideEntity) -> new ChangeRelation(this, (Relation) sourceEntity, (Relation) overrideEntity)); /* * If the relation was not found in this atlas, return null. Additionally, we check to see * if the relation has no members. If so, it is considered empty and is dropped from the * atlas. This logic, combined with the logic in ChangeRelation.membersFor, will * automatically handle removing non-empty but shallow relations as well. */ if (relation == null) { return null; } if (relation.members().isEmpty()) { return null; } return relation; }
private boolean differentRelations(final Relation baseRelation, final Relation alterRelation) { try { final RelationMemberList baseMembers = baseRelation.members(); final RelationMemberList alterMembers = alterRelation.members(); return !baseMembers.equals(alterMembers) && !differentRelationMemberListsWithMatch(baseMembers, alterMembers); } catch (final Exception e) { throw new CoreException("Unable to compare relations {} and {}", baseRelation, alterRelation, e); } }
/** * This function will validate if the supplied atlas object is valid for the check. * * @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) { // Object must be either a MultiPolygon Relation with at least one member, or an Area with // a place=islet, place=island, place=archipelago, or natural=water tag return (object instanceof Relation && IS_MULTIPOLYGON_WATER_RELATION.test(object) && ((Relation) object).members().size() >= 2) || (object instanceof Area && (TagPredicates.IS_WATER_BODY.test(object) || IS_ISLET.test(object) || IS_ISLAND.test(object)) && !this.isFlagged(object.getIdentifier())); }
@Test public void testRemoveRelationMember() { final Atlas atlas = this.rule.getAtlas(); final ChangeBuilder changeBuilder = new ChangeBuilder(); final Relation disconnectedFeatures = atlas.relation(41834000000L); // Remove the point from the list final RelationMemberList newMembers = new RelationMemberList(disconnectedFeatures.members() .stream().filter(member -> !(member.getEntity() instanceof Point)) .collect(Collectors.toList())); changeBuilder.add( new FeatureChange(ChangeType.ADD, CompleteRelation.shallowFrom(disconnectedFeatures) .withMembersAndSource(newMembers, disconnectedFeatures))); changeBuilder.add(new FeatureChange(ChangeType.REMOVE, CompletePoint.shallowFrom(atlas.point(41822000000L)))); final Change change = changeBuilder.get(); final Atlas changeAtlas = new ChangeAtlas(atlas, change); Assert.assertEquals(newMembers.asBean(), changeAtlas.relation(41834000000L).members().asBean()); final Relation parentRelation = changeAtlas.relation(41860000000L); final Relation fromRelation = (Relation) Iterables.stream(parentRelation.members()) .firstMatching(member -> "child1".equals(member.getRole())).get().getEntity(); Assert.assertEquals(newMembers.asBean(), fromRelation.members().asBean()); }
public static CompleteRelation from(final Relation relation) { return new CompleteRelation(relation.getIdentifier(), relation.getTags(), relation.bounds(), relation.members().asBean(), relation.allRelationsWithSameOsmIdentifier().stream().map(Relation::getIdentifier) .collect(Collectors.toList()), relation.allKnownOsmMembers().asBean(), relation.osmRelationIdentifier(), relation.relations().stream().map(Relation::getIdentifier) .collect(Collectors.toSet())); }