@@ -5565,31 +5565,37 @@ function _compactIri(activeCtx, iri, value, relativeTo, reverse) {
55655565
55665566 // no term or @vocab match, check for possible CURIEs
55675567 var choice = null ;
5568- for ( var term in activeCtx . mappings ) {
5569- var definition = activeCtx . mappings [ term ] ;
5570- // skip null definitions and terms with colons, they can't be prefixes
5571- if ( ! definition || definition . _termHasColon ) {
5572- continue ;
5573- }
5574- // skip entries with @ids that are not partial matches
5575- if ( ! ( iri . length > definition [ '@id' ] . length &&
5576- iri . indexOf ( definition [ '@id' ] ) === 0 ) ) {
5577- continue ;
5578- }
5579-
5580- // a CURIE is usable if:
5581- // 1. it has no mapping, OR
5582- // 2. value is null, which means we're not compacting an @value, AND
5583- // the mapping matches the IRI)
5584- var curie = term + ':' + iri . substr ( definition [ '@id' ] . length ) ;
5585- var isUsableCurie = ( ! ( curie in activeCtx . mappings ) ||
5586- ( value === null && activeCtx . mappings [ curie ] [ '@id' ] === iri ) ) ;
5587-
5588- // select curie if it is shorter or the same length but lexicographically
5589- // less than the current choice
5590- if ( isUsableCurie && ( choice === null ||
5591- _compareShortestLeast ( curie , choice ) < 0 ) ) {
5592- choice = curie ;
5568+ var idx = 0 ;
5569+ var partialMatches = [ ] ;
5570+ var iriMap = activeCtx . fastCurieMap ;
5571+ // check for partial matches of against `iri`, which means look until
5572+ // iri.length - 1, not full length
5573+ var maxPartialLength = iri . length - 1 ;
5574+ for ( ; idx < maxPartialLength && iri [ idx ] in iriMap ; ++ idx ) {
5575+ iriMap = iriMap [ iri [ idx ] ] ;
5576+ if ( '' in iriMap ) {
5577+ partialMatches . push ( iriMap [ '' ] [ 0 ] ) ;
5578+ }
5579+ }
5580+ // check partial matches in reverse order to prefer longest ones first
5581+ for ( var i = partialMatches . length - 1 ; i >= 0 ; -- i ) {
5582+ var entry = partialMatches [ i ] ;
5583+ var terms = entry . terms ;
5584+ for ( var ti = 0 ; ti < terms . length ; ++ ti ) {
5585+ // a CURIE is usable if:
5586+ // 1. it has no mapping, OR
5587+ // 2. value is null, which means we're not compacting an @value, AND
5588+ // the mapping matches the IRI
5589+ var curie = terms [ ti ] + ':' + iri . substr ( entry . iri . length ) ;
5590+ var isUsableCurie = ( ! ( curie in activeCtx . mappings ) ||
5591+ ( value === null && activeCtx . mappings [ curie ] [ '@id' ] === iri ) ) ;
5592+
5593+ // select curie if it is shorter or the same length but lexicographically
5594+ // less than the current choice
5595+ if ( isUsableCurie && ( choice === null ||
5596+ _compareShortestLeast ( curie , choice ) < 0 ) ) {
5597+ choice = curie ;
5598+ }
55935599 }
55945600 }
55955601
@@ -6212,6 +6218,10 @@ function _getInitialContext(options) {
62126218 }
62136219 var inverse = activeCtx . inverse = { } ;
62146220
6221+ // variables for building fast CURIE map
6222+ var fastCurieMap = activeCtx . fastCurieMap = { } ;
6223+ var irisToTerms = { } ;
6224+
62156225 // handle default language
62166226 var defaultLanguage = activeCtx [ '@language' ] || '@none' ;
62176227
@@ -6236,10 +6246,25 @@ function _getInitialContext(options) {
62366246 for ( var ii = 0 ; ii < ids . length ; ++ ii ) {
62376247 var iri = ids [ ii ] ;
62386248 var entry = inverse [ iri ] ;
6249+ var isKeyword = _isKeyword ( iri ) ;
62396250
6240- // initialize entry
62416251 if ( ! entry ) {
6252+ // initialize entry
62426253 inverse [ iri ] = entry = { } ;
6254+
6255+ if ( ! isKeyword && ! mapping . _termHasColon ) {
6256+ // init IRI to term map and fast CURIE prefixes
6257+ irisToTerms [ iri ] = [ term ] ;
6258+ var fastCurieEntry = { iri : iri , terms : irisToTerms [ iri ] } ;
6259+ if ( iri [ 0 ] in fastCurieMap ) {
6260+ fastCurieMap [ iri [ 0 ] ] . push ( fastCurieEntry ) ;
6261+ } else {
6262+ fastCurieMap [ iri [ 0 ] ] = [ fastCurieEntry ] ;
6263+ }
6264+ }
6265+ } else if ( ! isKeyword && ! mapping . _termHasColon ) {
6266+ // add IRI to term match
6267+ irisToTerms [ iri ] . push ( term ) ;
62436268 }
62446269
62456270 // add new entry
@@ -6274,9 +6299,50 @@ function _getInitialContext(options) {
62746299 }
62756300 }
62766301
6302+ // build fast CURIE map
6303+ for ( var key in fastCurieMap ) {
6304+ _buildIriMap ( fastCurieMap , key , 1 ) ;
6305+ }
6306+
62776307 return inverse ;
62786308 }
62796309
6310+ /**
6311+ * Runs a recursive algorithm to build a lookup map for quickly finding
6312+ * potential CURIEs.
6313+ *
6314+ * @param iriMap the map to build.
6315+ * @param key the current key in the map to work on.
6316+ * @param idx the index into the IRI to compare.
6317+ */
6318+ function _buildIriMap ( iriMap , key , idx ) {
6319+ var entries = iriMap [ key ] ;
6320+ var next = iriMap [ key ] = { } ;
6321+
6322+ var iri ;
6323+ var letter ;
6324+ for ( var i = 0 ; i < entries . length ; ++ i ) {
6325+ iri = entries [ i ] . iri ;
6326+ if ( idx >= iri . length ) {
6327+ letter = '' ;
6328+ } else {
6329+ letter = iri [ idx ] ;
6330+ }
6331+ if ( letter in next ) {
6332+ next [ letter ] . push ( entries [ i ] ) ;
6333+ } else {
6334+ next [ letter ] = [ entries [ i ] ] ;
6335+ }
6336+ }
6337+
6338+ for ( var key in next ) {
6339+ if ( key === '' ) {
6340+ continue ;
6341+ }
6342+ _buildIriMap ( next , key , idx + 1 ) ;
6343+ }
6344+ }
6345+
62806346 /**
62816347 * Adds the term for the given entry if not already added.
62826348 *
0 commit comments