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 version3)
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
Updated 22 days ago