How to migrate to topology attributes
How to migrate to topology attributes
Introduction to topology attributes
Starting with Location Library 1.0.29, you can read data from the Topology
Attributes layer, which is planned to replace the following layers:
- Road Attributes
- Navigation Attributes
- Advanced Navigation Attributes
The Topology Attributes layer consolidates all attributes currently provided by
these existing layers, which are now deprecated in favor of the unified layer
and will be removed.
This change is driven by a similar migration happening in HMC, our source
catalog. Since our OM4LL catalogs depend on HMC, we are aligning our structure
accordingly to maintain compatibility and consistency across systems.
The Topology Attributes layer is available in the following catalogs:
hrn:here:data::olp-here:here-optimized-map-for-location-library-2(starting
from version7521)hrn:here:data::olp-here:om4ll-gt-jpn-prod-v2(starting from version11)hrn:here:data::olp-here-krmpp:om4ll-hae-kor-prod-v2(starting from version
3)
Note: if you open an older map version, the Topology Attributes layer will
return empty data.
Migration overview
The Road Attributes, Navigation Attributes, and Advanced Navigation Attributes
layers are deprecated and will be removed in favor of the Topology Attributes
layer.
Depending on your use case, some changes to your codebase may be required to
migrate to Topology Attributes.
Migrating property maps to topology attributes
To migrate Property Maps to Topology Attributes you should replace all usages of
deprecated layers.
Before migration:
import com.here.platform.location.core.graph.{PointBasedPropertyMap, RangeBasedPropertyMap}
import com.here.platform.location.inmemory.graph.Vertex
import com.here.platform.location.integration.optimizedmap.advancednavigationattributes._
import com.here.platform.location.integration.optimizedmap.graph.PropertyMaps
import com.here.platform.location.integration.optimizedmap.navigationattributes._
import com.here.platform.location.integration.optimizedmap.roadattributes._
val roadAttributes = PropertyMaps(optimizedMap).roadAttributes
val navigationAttributes = PropertyMaps(optimizedMap).navigationAttributes
val advancedNavigationAttributes = PropertyMaps(optimizedMap).advancedNavigationAttributes
val functionalClasses: RangeBasedPropertyMap[Vertex, FunctionalClass] =
roadAttributes.functionalClass
val trafficMessageChannelCodes: RangeBasedPropertyMap[Vertex, Set[TrafficMessageChannelCode]] =
navigationAttributes.trafficMessageChannelCodes
val railwayCrossings: PointBasedPropertyMap[Vertex, RailwayCrossing] =
advancedNavigationAttributes.railwayCrossingimport com.here.platform.location.core.graph.javadsl.PointBasedPropertyMap;
import com.here.platform.location.core.graph.javadsl.RangeBasedPropertyMap;
import com.here.platform.location.inmemory.graph.Vertex;
import com.here.platform.location.integration.optimizedmap.advancednavigationattributes.RailwayCrossing;
import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
import com.here.platform.location.integration.optimizedmap.navigationattributes.TrafficMessageChannelCode;
import com.here.platform.location.integration.optimizedmap.roadattributes.FunctionalClass;
PropertyMaps.RoadAttributes roadAttributes = new PropertyMaps(optimizedMap).roadAttributes();
PropertyMaps.NavigationAttributes navigationAttributes =
new PropertyMaps(optimizedMap).navigationAttributes();
PropertyMaps.AdvancedNavigationAttributes advancedNavigationAttributes =
new PropertyMaps(optimizedMap).advancedNavigationAttributes();
RangeBasedPropertyMap<Vertex, FunctionalClass> functionalClasses =
roadAttributes.functionalClass();
RangeBasedPropertyMap<Vertex, Set<TrafficMessageChannelCode>> trafficMessageChannelCodes =
navigationAttributes.trafficMessageChannelCodes();
PointBasedPropertyMap<Vertex, RailwayCrossing> railwayCrossings =
advancedNavigationAttributes.railwayCrossing();After migration:
import com.here.platform.location.core.graph.{PointBasedPropertyMap, RangeBasedPropertyMap}
import com.here.platform.location.inmemory.graph.Vertex
import com.here.platform.location.integration.optimizedmap.advancednavigationattributes._
import com.here.platform.location.integration.optimizedmap.graph.PropertyMaps
import com.here.platform.location.integration.optimizedmap.navigationattributes._
import com.here.platform.location.integration.optimizedmap.roadattributes._
val topologyAttributes = PropertyMaps(optimizedMap).topologyAttributes
val functionalClasses: RangeBasedPropertyMap[Vertex, FunctionalClass] =
topologyAttributes.functionalClass
val trafficMessageChannelCodes: RangeBasedPropertyMap[Vertex, Set[TrafficMessageChannelCode]] =
topologyAttributes.trafficMessageChannelCodes
val railwayCrossings: PointBasedPropertyMap[Vertex, RailwayCrossing] =
topologyAttributes.railwayCrossingimport com.here.platform.location.core.graph.javadsl.PointBasedPropertyMap;
import com.here.platform.location.core.graph.javadsl.RangeBasedPropertyMap;
import com.here.platform.location.inmemory.graph.Vertex;
import com.here.platform.location.integration.optimizedmap.advancednavigationattributes.RailwayCrossing;
import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
import com.here.platform.location.integration.optimizedmap.navigationattributes.TrafficMessageChannelCode;
import com.here.platform.location.integration.optimizedmap.roadattributes.FunctionalClass;
PropertyMaps.TopologyAttributes topologyAttributes =
new PropertyMaps(optimizedMap).topologyAttributes();
RangeBasedPropertyMap<Vertex, FunctionalClass> functionalClasses =
topologyAttributes.functionalClass();
RangeBasedPropertyMap<Vertex, Set<TrafficMessageChannelCode>> trafficMessageChannelCodes =
topologyAttributes.trafficMessageChannelCodes();
PointBasedPropertyMap<Vertex, RailwayCrossing> railwayCrossings =
topologyAttributes.railwayCrossing();Reading from deprecated layers
If the Topology Attributes layer is not available for your catalog or map
version, you can access the deprecated layers as follows (e.g., reading from the
Road Attributes layer):
import com.here.platform.data.client.base.scaladsl.BaseClient
import com.here.platform.location.core.graph.RangeBasedProperty
import com.here.platform.location.integration.optimizedmap.OptimizedMap
import com.here.platform.location.integration.optimizedmap.dcl2.OptimizedMapCatalog
import com.here.platform.location.integration.optimizedmap.graph.PropertyMaps
import com.here.platform.location.integration.optimizedmap.roadattributes._
val baseClient = BaseClient()
val optimizedMap = OptimizedMapCatalog
.from(OptimizedMap.v2.HRN)
.usingBaseClient(baseClient)
.newInstance
// Map version in which the Topology Attributes layer is empty.
.version(7520L)
val roadAttributes = PropertyMaps(optimizedMap).roadAttributes
val functionalClasses: Seq[RangeBasedProperty[FunctionalClass]] =
roadAttributes.functionalClass(vertex)
val overpassUnderpasses: Seq[RangeBasedProperty[OverpassUnderpass]] =
roadAttributes.overpassUnderpass(vertex)
val officialCountryCodes: Seq[RangeBasedProperty[OfficialCountryCode]] =
roadAttributes.officialCountryCode(vertex)
val physicalAttributes: Seq[RangeBasedProperty[PhysicalAttribute]] =
roadAttributes.physicalAttribute(vertex)
val roadClasses: Seq[RangeBasedProperty[RoadClass]] = roadAttributes.roadClass(vertex)
val specialTrafficAreaCategories: Seq[RangeBasedProperty[SpecialTrafficAreaCategory]] =
roadAttributes.specialTrafficAreaCategory(vertex)
val userDefinedCountryCodes: Seq[RangeBasedProperty[UserDefinedCountryCode]] =
roadAttributes.userDefinedCountryCode(vertex)import com.here.platform.data.client.base.javadsl.BaseClient;
import com.here.platform.data.client.base.javadsl.BaseClientJava;
import com.here.platform.location.core.graph.javadsl.RangeBasedProperty;
import com.here.platform.location.core.graph.javadsl.RangeBasedPropertyMap;
import com.here.platform.location.inmemory.graph.Vertex;
import com.here.platform.location.integration.optimizedmap.OptimizedMap;
import com.here.platform.location.integration.optimizedmap.OptimizedMapLayers;
import com.here.platform.location.integration.optimizedmap.dcl2.javadsl.OptimizedMapCatalog;
import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
import com.here.platform.location.integration.optimizedmap.roadattributes.*;
BaseClient baseClient = BaseClientJava.instance();
OptimizedMapLayers optimizedMap =
OptimizedMapCatalog.from(OptimizedMap.v2.HRN)
.usingBaseClient(baseClient)
.newInstance()
// Map version in which the Topology Attributes layer is empty.
.version(7520L);
PropertyMaps.RoadAttributes roadAttributes = new PropertyMaps(optimizedMap).roadAttributes();
RangeBasedPropertyMap<Vertex, FunctionalClass> functionalClass =
roadAttributes.functionalClass();
List<RangeBasedProperty<FunctionalClass>> functionalClasses = functionalClass.get(vertex);
RangeBasedPropertyMap<Vertex, OverpassUnderpass> overpassUnderpass =
roadAttributes.overpassUnderpass();
List<RangeBasedProperty<OverpassUnderpass>> overpassUnderpasses = overpassUnderpass.get(vertex);
RangeBasedPropertyMap<Vertex, OfficialCountryCode> officialCountryCode =
roadAttributes.officialCountryCode();
List<RangeBasedProperty<OfficialCountryCode>> officialCountryCodes =
officialCountryCode.get(vertex);
RangeBasedPropertyMap<Vertex, PhysicalAttribute> physicalAttribute =
roadAttributes.physicalAttribute();
List<RangeBasedProperty<PhysicalAttribute>> physicalAttributes = physicalAttribute.get(vertex);
RangeBasedPropertyMap<Vertex, RoadClass> roadClass = roadAttributes.roadClass();
List<RangeBasedProperty<RoadClass>> roadClasses = roadClass.get(vertex);
RangeBasedPropertyMap<Vertex, SpecialTrafficAreaCategory> specialTrafficAreaCategory =
roadAttributes.specialTrafficAreaCategory();
List<RangeBasedProperty<SpecialTrafficAreaCategory>> specialTrafficAreaCategories =
specialTrafficAreaCategory.get(vertex);
List<RangeBasedProperty<UserDefinedCountryCode>> userDefinedCountryCodes =
roadAttributes.userDefinedCountryCode().get(vertex);Important: Accessing deprecated layers is strongly discouraged. These APIs are
maintained only for backward compatibility and may be removed in future
releases without notice. Whenever possible, migrate to the Topology Attributes
to ensure long-term stability and compatibility.
Using deprecated layers in TMC
If you're using a map version to create a TMC reference where the Topology
Attributes layer is empty, you'll encounter a
LinearLocationNotRepresentedInTmcException.
A new experimental API has been introduced that allows you to use deprecated
layers when building creator:
import com.here.platform.data.client.base.scaladsl.BaseClient
import com.here.platform.location.compilation.heremapcontent.NavigationAttributeDescription
import com.here.platform.location.integration.optimizedmap.dcl2.OptimizedMapCatalog
import com.here.platform.location.integration.optimizedmap.graph.{Graphs, PropertyMaps}
import com.here.platform.location.integration.optimizedmap.{OptimizedMap, OptimizedMapLayers}
import com.here.platform.location.referencing.{
LocationReferencingPropertyMaps,
TmcLocationReferenceCreators
}
val baseClient = BaseClient()
val optimizedMap: OptimizedMapLayers =
OptimizedMapCatalog
.from(OptimizedMap.v2.HRN)
.usingBaseClient(baseClient)
// Request TMC attributes.
.withNavigationAttributes(NavigationAttributeDescription.TrafficMessageChannelCode)
.newInstance
// Map version in which the Topology Attributes layer is empty.
.version(7520L)
val propertyMaps = PropertyMaps(optimizedMap)
val graphs = Graphs(optimizedMap)
val locationReferencingPropertyMaps = LocationReferencingPropertyMaps(optimizedMap)
val tmcCreator = TmcLocationReferenceCreators.tmc(
propertyMaps.length,
graphs.forward,
locationReferencingPropertyMaps.tmcCodeToLinearLocation,
propertyMaps.navigationAttributes.trafficMessageChannelCodes,
None
)import com.here.platform.data.client.base.javadsl.BaseClient;
import com.here.platform.data.client.base.javadsl.BaseClientJava;
import com.here.platform.location.compilation.heremapcontent.NavigationAttributeDescription;
import com.here.platform.location.integration.optimizedmap.OptimizedMap;
import com.here.platform.location.integration.optimizedmap.OptimizedMapLayers;
import com.here.platform.location.integration.optimizedmap.dcl2.javadsl.OptimizedMapCatalog;
import com.here.platform.location.integration.optimizedmap.graph.javadsl.Graphs;
import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
import com.here.platform.location.referencing.LinearLocation;
import com.here.platform.location.referencing.LocationReferenceCreator;
import com.here.platform.location.referencing.javadsl.LocationReferencingPropertyMaps;
import com.here.platform.location.referencing.javadsl.TmcLocationReferenceCreators;
import com.here.platform.location.tpeg2.tmc.TMCLocationReference;
final BaseClient baseClient = BaseClientJava.instance();
final OptimizedMapLayers optimizedMap =
OptimizedMapCatalog.from(OptimizedMap.v2.HRN)
.usingBaseClient(baseClient)
// Request TMC attributes.
.withNavigationAttributes(NavigationAttributeDescription.TrafficMessageChannelCode())
.newInstance()
// Map version in which the Topology Attributes layer is empty.
.version(7520L);
final PropertyMaps propertyMaps = new PropertyMaps(optimizedMap);
final Graphs graphs = new Graphs(optimizedMap);
final LocationReferencingPropertyMaps locationReferencingPropertyMaps =
new LocationReferencingPropertyMaps(optimizedMap);
final LocationReferenceCreator<LinearLocation, TMCLocationReference> tmcCreator =
TmcLocationReferenceCreators.tmc(
propertyMaps.length(),
graphs.forward(),
locationReferencingPropertyMaps.tmcCodeToLinearLocation(),
propertyMaps.navigationAttributes().trafficMessageChannelCodes(),
Optional.empty());Important: This API should only be used when working with older map versions
that do not contain data in the Topology Attributes layer. For all other
cases, use the standard APIs to ensure compatibility and future-proofing.
List of new methods:
tmcextendedTmcpiecewiseExtendedTmc
TMC resolver doesn't use Topology attributes, no changes are required.
Using deprecated layers in OLR
If you're using a map version where the Topology Attributes layer is empty, you
won't receive any exceptions when creating or resolving references. Instead, you
will receive incomplete results.
A new experimental API has been introduced that allows you to use deprecated
layers when building creator and resolver:
import com.here.platform.data.client.base.scaladsl.BaseClient
import com.here.platform.location.compilation.heremapcontent.{
NavigationAttributeDescription,
RoadAttributeDescription
}
import com.here.platform.location.integration.optimizedmap.dcl2.OptimizedMapCatalog
import com.here.platform.location.integration.optimizedmap.geospatial.ProximitySearches
import com.here.platform.location.integration.optimizedmap.graph.{
Graphs,
PropertyMaps,
RoadAccess
}
import com.here.platform.location.integration.optimizedmap.{OptimizedMap, OptimizedMapLayers}
import com.here.platform.location.referencing.olr.FormOfWayRangeBasedPropertyMap
import com.here.platform.location.referencing.{
OlrLocationReferenceCreators,
OlrLocationReferenceResolvers
}
val baseClient = BaseClient()
val optimizedMap: OptimizedMapLayers =
OptimizedMapCatalog
.from(OptimizedMap.v2.HRN)
.usingBaseClient(baseClient)
// Request OLR attributes.
.withRoadAttributes(RoadAttributeDescription.FunctionalClass,
RoadAttributeDescription.PhysicalAttribute,
RoadAttributeDescription.SpecialTrafficAreaCategory)
.withNavigationAttributes(NavigationAttributeDescription.RoadUsage)
.newInstance
// Map version in which the Topology Attributes layer is empty.
.version(7520L)
val graphs = Graphs(optimizedMap)
val propertyMaps = PropertyMaps(optimizedMap)
val roadAttributes = propertyMaps.roadAttributes
val navigationAttributes = propertyMaps.navigationAttributes
val accessType =
RoadAccess.Automobile | RoadAccess.Bus | RoadAccess.Motorcycle | RoadAccess.Taxi
val creator = OlrLocationReferenceCreators.linear(
graphs.forward,
graphs.reverse,
propertyMaps.geometry,
propertyMaps.length,
propertyMaps.roadAccess(accessType),
roadAttributes.functionalClass,
new FormOfWayRangeBasedPropertyMap(
roadAttributes.physicalAttribute,
navigationAttributes.roadUsage,
propertyMaps.roadAccess,
roadAttributes.specialTrafficAreaCategory
)
)
val resolver = OlrLocationReferenceResolvers.linear(
ProximitySearches.vertexGeometrySegments(optimizedMap.geometry),
graphs.forward,
propertyMaps.geometry,
propertyMaps.length,
propertyMaps.roadAccess(accessType),
roadAttributes.functionalClass,
new FormOfWayRangeBasedPropertyMap(
roadAttributes.physicalAttribute,
navigationAttributes.roadUsage,
propertyMaps.roadAccess,
roadAttributes.specialTrafficAreaCategory
)
)import com.here.platform.data.client.base.javadsl.BaseClient;
import com.here.platform.data.client.base.javadsl.BaseClientJava;
import com.here.platform.location.compilation.heremapcontent.NavigationAttributeDescription;
import com.here.platform.location.compilation.heremapcontent.RoadAttributeDescription;
import com.here.platform.location.integration.optimizedmap.OptimizedMap;
import com.here.platform.location.integration.optimizedmap.OptimizedMapLayers;
import com.here.platform.location.integration.optimizedmap.dcl2.javadsl.OptimizedMapCatalog;
import com.here.platform.location.integration.optimizedmap.geospatial.javadsl.ProximitySearches;
import com.here.platform.location.integration.optimizedmap.graph.RoadAccess;
import com.here.platform.location.integration.optimizedmap.graph.RoadAccessType;
import com.here.platform.location.integration.optimizedmap.graph.javadsl.Graphs;
import com.here.platform.location.integration.optimizedmap.graph.javadsl.PropertyMaps;
import com.here.platform.location.referencing.LinearLocation;
import com.here.platform.location.referencing.LocationReferenceCreator;
import com.here.platform.location.referencing.LocationReferenceResolver;
import com.here.platform.location.referencing.javadsl.OlrLocationReferenceCreators;
import com.here.platform.location.referencing.javadsl.OlrLocationReferenceResolvers;
import com.here.platform.location.referencing.olr.javadsl.FormOfWayRangeBasedPropertyMap;
import com.here.platform.location.tpeg2.olr.LinearLocationReference;
final BaseClient baseClient = BaseClientJava.instance();
final OptimizedMapLayers optimizedMap =
OptimizedMapCatalog.from(OptimizedMap.v2.HRN)
.usingBaseClient(baseClient)
// Request OLR attributes.
.withRoadAttributes(
RoadAttributeDescription.FunctionalClass(),
RoadAttributeDescription.PhysicalAttribute(),
RoadAttributeDescription.SpecialTrafficAreaCategory())
.withNavigationAttributes(NavigationAttributeDescription.RoadUsage())
.newInstance()
// Map version in which the Topology Attributes layer is empty.
.version(7520L);
final Graphs graphs = new Graphs(optimizedMap);
final PropertyMaps propertyMaps = new PropertyMaps(optimizedMap);
final PropertyMaps.RoadAttributes roadAttributes = propertyMaps.roadAttributes();
final PropertyMaps.NavigationAttributes navigationAttributes =
propertyMaps.navigationAttributes();
final RoadAccessType accessType =
new RoadAccessType(
RoadAccess.Automobile.mask()
| RoadAccess.Bus.mask()
| RoadAccess.Motorcycle.mask()
| RoadAccess.Taxi.mask());
final LocationReferenceCreator<LinearLocation, LinearLocationReference> creator =
OlrLocationReferenceCreators.linear(
graphs.forward(),
graphs.reverse(),
propertyMaps.geometry(),
propertyMaps.length(),
propertyMaps.roadAccess(accessType),
roadAttributes.functionalClass(),
new FormOfWayRangeBasedPropertyMap(
roadAttributes.physicalAttribute(),
navigationAttributes.roadUsage(),
propertyMaps.roadAccess(),
roadAttributes.specialTrafficAreaCategory()));
final LocationReferenceResolver<LinearLocationReference, LinearLocation> resolver =
OlrLocationReferenceResolvers.linear(
ProximitySearches.vertexGeometrySegments(optimizedMap.geometry()),
graphs.forward(),
propertyMaps.geometry(),
propertyMaps.length(),
propertyMaps.roadAccess(accessType),
roadAttributes.functionalClass(),
new FormOfWayRangeBasedPropertyMap(
roadAttributes.physicalAttribute(),
navigationAttributes.roadUsage(),
PropertyMaps.roadAccess(optimizedMap.roadAccess()),
roadAttributes.specialTrafficAreaCategory()));Important: This API should only be used when working with older map versions
that do not contain data in the Topology Attributes layer. For all other
cases, use the standard APIs to ensure compatibility and future-proofing.
List of new methods for building creator and resolver:
linearclosedLinearpointAlongLinepoiWithAccessPointolr