@@ -343,11 +343,10 @@ exports.isValidFSM = maybe => {
343343 *
344344 */
345345exports . getFSM = entity => {
346- const fsmPair = entity . parameters && entity . parameters . find ( ( { key} ) => key === '$invoke' ) // parameter binding?
347- || entity . annotations && entity . annotations . find ( ( { key} ) => key === 'fsm' ) // or annotation?
346+ const fsmAnnotation = exports . fsmAnnotation ( entity )
348347
349- if ( fsmPair ) {
350- return openwhiskComposer . deserialize ( fsmPair . value )
348+ if ( fsmAnnotation ) {
349+ return openwhiskComposer . deserialize ( fsmAnnotation . value )
351350 }
352351}
353352
@@ -398,29 +397,44 @@ exports.moveAside = (wsk, name) => repl.qexec(`mv "${name}" "${name}-orig"`)
398397 }).then(() => ({ ok: name }))*/
399398
400399/**
401- * Merge previous and current and internal annotations
400+ * Merge previous and current and internal annotations. Take all of
401+ * the new (A2) annotations and add in any old (A1) annotations that
402+ * are not replaced by new ones.
402403 *
403404 */
404405const mergeAnnotations = ( A1 = [ ] , A2 = [ ] , type , fsm ) => {
405- const annotations = A1 . concat ( A2 ) ,
406- fsmAnnotation = annotations . find ( ( { key} ) => key === 'fsm' ) ,
407- badgesAnnotation = annotations . find ( ( { key} ) => key === 'wskng.combinators' ) ,
408- badge = { "type" :"composition" , "role" :"replacement" , "badge" :type }
406+ // map from annotation key to "is new"
407+ const inA2 = A2 . reduce ( ( M , { key} ) => {
408+ M [ key ] = true
409+ return M
410+ } , { } )
409411
410- if ( ! fsmAnnotation ) {
411- annotations . push ( { key : 'fsm' , value : fsm } )
412- } else {
413- fsmAnnotation . value = fsm
414- }
412+ // any old annotations are are not replaced by new ones
413+ const filteredA1 = A1 . filter ( ( { key} ) => ! inA2 [ key ] )
415414
416- if ( ! badgesAnnotation ) {
417- annotations . push ( { key : 'wskng.combinators' , value : [ badge ] } )
418- } else {
419- const existing = badgesAnnotation . value . find ( ( { type} ) => type === 'composition' )
420- if ( existing ) {
421- existing . badge = type
415+ // the union of old and new
416+ const annotations = A2 . concat ( filteredA1 )
417+
418+ if ( type && fsm ) {
419+ const fsmAnnotation = annotations . find ( ( { key} ) => key === 'fsm' ) || annotations . find ( ( { key} ) => key === 'conductor' ) ,
420+ badgesAnnotation = annotations . find ( ( { key} ) => key === 'wskng.combinators' ) ,
421+ badge = { "type" :"composition" , "role" :"replacement" , "badge" :type }
422+
423+ if ( ! fsmAnnotation ) {
424+ annotations . push ( { key : 'fsm' , value : fsm } )
422425 } else {
423- badgesAnnotation . push ( badge )
426+ fsmAnnotation . value = fsm
427+ }
428+
429+ if ( ! badgesAnnotation ) {
430+ annotations . push ( { key : 'wskng.combinators' , value : [ badge ] } )
431+ } else {
432+ const existing = badgesAnnotation . value . find ( ( { type} ) => type === 'composition' )
433+ if ( existing ) {
434+ existing . badge = type
435+ } else {
436+ badgesAnnotation . push ( badge )
437+ }
424438 }
425439 }
426440
@@ -452,7 +466,9 @@ exports.create = ({name, fsm, type, annotations=[], parameters=[], wsk, commandT
452466 // now we merge together the parameters and annotations
453467 const fsmAction = fsm . encode ( fqnAppName ) . actions [ 0 ] . action
454468 fsmAction . parameters = currentAction . parameters . concat ( parameters ) . concat ( fsmAction . parameters || [ ] ) ,
455- fsmAction . annotations = mergeAnnotations ( currentAction . annotations , annotations . concat ( fsmAction . annotations || [ ] ) , type , fsm )
469+ fsmAction . annotations = mergeAnnotations ( currentAction . annotations ,
470+ mergeAnnotations ( annotations || [ ] , fsmAction . annotations || [ ] ) ,
471+ type , fsm )
456472 return fsmAction
457473 } )
458474 . then ( fsmAction => wsk . owOpts ( { // add common flags to the requewst
@@ -482,12 +498,28 @@ exports.update = ({name, entity, fsm, type, wsk, commandTree, execOptions}) => {
482498 *
483499 */
484500exports . isAnApp = action => {
485- const allManagement = action . annotations && action . annotations . find ( ( { key} ) => key === 'wskng.combinators' ) ,
486- anyAppManagement = allManagement && util . isArray ( allManagement . value ) && allManagement . value . find ( ( { type} ) => type === 'composition' )
501+ const anno = action && action . annotations && action . annotations . find ( ( { key} ) => key === 'conductor' )
502+ return anno && anno . value
503+ }
504+
505+ /**
506+ * Return the annotation that stores the IR/fsm
507+ *
508+ */
509+ exports . fsmAnnotation = action => {
510+ const anno = action . annotations . find ( ( { key} ) => key === 'fsm' )
511+ || action . annotations . find ( ( { key} ) => key === 'conductor' )
487512
488- return anyAppManagement
513+ // avoid conductor:true as indicating the presence of an FSM
514+ return anno && anno . value !== true ? anno : undefined
489515}
490516
517+ /**
518+ * Does the given action have an IR/fsm associated with it?
519+ *
520+ */
521+ exports . hasFSM = action => ! ! exports . fsmAnnotation ( action )
522+
491523/**
492524 * Helper method for kill and purge operations, which share enough code...
493525 *
@@ -693,7 +725,7 @@ exports.hasUnknownOptions = (options, expected) => {
693725 */
694726exports . decorateAsApp = ( { action, viewName= 'app' , commandPrefix= 'app get' , doVisualize, options} ) => {
695727 action . prettyType = appBadge
696- action . fsm = action . annotations . find ( ( { key } ) => key === 'fsm' ) . value
728+ action . fsm = exports . fsmAnnotation ( action ) . value
697729
698730 if ( action . exec ) {
699731 action . exec . prettyKind = 'app'
@@ -714,7 +746,7 @@ exports.decorateAsApp = ({action, viewName='app', commandPrefix='app get', doVis
714746 . concat ( exports . vizAndfsmViewModes ( visualize , commandPrefix , undefined , options ) )
715747 . concat ( exports . zoomToFitButtons ( controller ) )
716748
717- return view
749+ return view || action
718750
719751 } else {
720752 return action
0 commit comments