@@ -5,24 +5,52 @@ const retCode = require('./../utils/enums/CLI-errors')
55
66class LuisGenBuilder {
77 static build ( luisApp ) {
8- let result = new LuisGen ( )
9- try {
10- result . intents = processIntents ( luisApp . intents ) ;
11- result . entities = extractEntities ( luisApp . entities ) ;
12- result . prebuiltEntities = extractEntities ( luisApp . prebuiltEntities , true ) ;
13- result . closedLists = extractEntities ( luisApp . closedLists ) ;
14- result . regex_entities = extractEntities ( luisApp . regex_entities ) ;
15- result . patternAnyEntities = extractEntities ( luisApp . patternAnyEntities ) ;
16- result . composites = extractComposites ( luisApp . composites ) ;
17- } catch ( err ) {
18- throw ( new error ( retCode . errorCode . INVALID_INPUT_FILE , "Invalid LUIS JSON file content." ) )
8+ let buildWithVersion ;
9+ if ( luisApp . luis_schema_version < "5" ) {
10+ buildWithVersion = buildUpToVersion4 ;
11+ } else if ( luisApp . luis_schema_version >= "6.0.0" ) {
12+ buildWithVersion = buildVersion6 ;
13+ } else {
14+ throw ( new error ( retCode . errorCode . INVALID_INPUT_FILE , "Invalid LUIS JSON schema version." ) )
1915 }
20- return result
16+
17+ return buildWithVersion ( luisApp ) ;
2118 }
2219}
2320
2421module . exports = LuisGenBuilder
2522
23+ const buildUpToVersion4 = function ( luisApp ) {
24+ let result = new LuisGen ( )
25+ try {
26+ result . intents = processIntents ( luisApp . intents ) ;
27+ result . entities = extractEntities ( luisApp . entities ) ;
28+ result . prebuiltEntities = extractEntities ( luisApp . prebuiltEntities , true ) ;
29+ result . closedLists = extractEntities ( luisApp . closedLists ) ;
30+ result . regex_entities = extractEntities ( luisApp . regex_entities ) ;
31+ result . patternAnyEntities = extractEntities ( luisApp . patternAnyEntities ) ;
32+ result . composites = extractComposites ( luisApp . composites ) ;
33+ } catch ( err ) {
34+ throw ( new error ( retCode . errorCode . INVALID_INPUT_FILE , "Invalid LUIS JSON file content." ) )
35+ }
36+ return result
37+ }
38+
39+ const buildVersion6 = function ( luisApp ) {
40+ let result = new LuisGen ( )
41+ try {
42+ result . intents = processIntents ( luisApp . intents ) ;
43+ [ result . entities , result . composites ] = extractEntitiesV6 ( luisApp . entities ) ;
44+ result . prebuiltEntities = extractEntities ( luisApp . prebuiltEntities , true ) ;
45+ result . closedLists = extractEntities ( luisApp . closedLists ) ;
46+ result . regex_entities = extractEntities ( luisApp . regex_entities ) ;
47+ result . patternAnyEntities = extractEntities ( luisApp . patternAnyEntities ) ;
48+ } catch ( err ) {
49+ throw ( new error ( retCode . errorCode . INVALID_INPUT_FILE , "Invalid LUIS JSON file content." ) )
50+ }
51+ return result
52+ }
53+
2654const processIntents = function ( intents ) {
2755 const result = [ ] ;
2856 intents . forEach ( ( intent ) => {
@@ -69,4 +97,83 @@ const extractEntities = function(entities, builtIn = false) {
6997 }
7098 } ) ;
7199 return result ;
100+ }
101+
102+ const extractEntitiesV6 = function ( entities ) {
103+ // This method provides a simplified topological sort to
104+ // solve potential instanceOf dependecies in the v6 entities
105+
106+ const simpleEntitiesResult = [ ] ;
107+ const compositeEntitiesResult = [ ] ;
108+ const simpleEntitiesWithType = { } ;
109+ const resolveEntityType = function ( entityName ) {
110+ const entityStack = [ ] ;
111+ let entityType = simpleEntitiesWithType [ entityName ] ;
112+
113+ while ( simpleEntitiesWithType [ entityType ] ) {
114+ entityStack . push ( entityName ) ;
115+ entityName = entityType ;
116+ entityType = simpleEntitiesWithType [ entityName ] ;
117+ }
118+
119+ while ( entityName ) {
120+ simpleEntitiesWithType [ entityName ] = entityType ;
121+ entityName = entityStack . pop ( ) ;
122+ }
123+ }
124+
125+ const firstPassStack = entities . slice ( ) ;
126+
127+ while ( firstPassStack . length ) {
128+ const entity = firstPassStack . pop ( ) ;
129+
130+ if ( Array . isArray ( entity . children ) && entity . children . length ) {
131+ firstPassStack . push ( ...entity . children ) ;
132+ } else if ( ! entity . children || ( Array . isArray ( entity . children ) && entity . children . length == 0 ) ) {
133+ // is simple entity
134+ if ( entity . instanceOf ) {
135+ // If the entity order in the schema was not modified by hand,
136+ // this algorithm will solve instanceOf dependencies.
137+ const last_type = simpleEntitiesWithType [ entity . instanceOf ] || entity . instanceOf ;
138+ simpleEntitiesWithType [ entity . name ] = last_type ;
139+ }
140+ } else {
141+ throw CLIError ( "Malformed JSON: entity.children should be an array" ) ;
142+ }
143+ }
144+
145+ // This is a second pass for simple entities.
146+ // If the JSON was modified by hand and there's a dependency
147+ // in the instanceOf field to an entity that appears later,
148+ // the type won't be resolved correctly with one pass.
149+ for ( const entityName in simpleEntitiesWithType ) {
150+ resolveEntityType ( entityName ) ;
151+ }
152+
153+ const processSimpleEntity = function ( entity , listToAppend ) {
154+ listToAppend . push (
155+ entity . instanceOf ? { name : entity . name , instanceOf : simpleEntitiesWithType [ entity . instanceOf ] || entity . instanceOf } : entity . name
156+ )
157+ }
158+
159+ const baseParseEntity = function ( entityList , childList , topLevel = false ) {
160+ entityList . forEach ( entity => {
161+ if ( Array . isArray ( entity . children ) && entity . children . length ) {
162+ const compositeEntity = { compositeName : propertyHelper . normalizeName ( entity . name ) , attributes : [ ] } ;
163+ baseParseEntity ( entity . children , compositeEntity . attributes ) ;
164+ compositeEntitiesResult . push ( compositeEntity ) ;
165+ if ( ! topLevel ) {
166+ childList . push ( { name : entity . name , compositeInstanceOf : true } )
167+ }
168+ } else {
169+ processSimpleEntity (
170+ entity ,
171+ topLevel ? simpleEntitiesResult : childList
172+ )
173+ }
174+ } ) ;
175+ }
176+
177+ baseParseEntity ( entities , null , true ) ;
178+ return [ simpleEntitiesResult , compositeEntitiesResult ] ;
72179}
0 commit comments