Here are some sample functions that use OD. These were extracted from our GEODE-level guideline authoring tool. Don't get confused about what is happening in Read/WriteSteps(): We are mapping to and from GEODE-level steps, which are each stored as a number of GLIF-level steps. I have prepended the data types used by the code, in case it helps to understand what is going on. These are in IDL syntax. See also the GS.idl file, available view the GLIF overview located at http://dsg.harvard.edu/public/intermed/glif_overview.html. The types below use some of the GS types. Note also that the steps that are stored contain some values not found in GLIF (a strict GLIF parser would presumably ignore those fields). I believe these are marked throughout the code. If you ignore all the fluff, you will see that OD is really pretty easy to use. /**************************************************************************/ /* TYPEDEFS */ // Patient data defn element (superset of GLIF-level data element) typedef struct t_GAt_PatientData { // GLIF fields tUInt4 id; string name; string type; string possible_values; string temporal_constraint; string didactics; // Supplemental fields GSt_Selection cardinality; unsigned long k; boolean min_max_specified; float min_value; float max_value; boolean normal_specified; float min_normal; float max_normal; string boolean_constraint; } GAt_PatientData; typedef sequence GAt_PatientDataSeq; // Action specification (superset of GLIF-level action) enum GAt_ActionMode { GAk_AMInvalidMode, GAk_AMWait, GAk_AMTrigger }; enum GAt_ActionType { GAk_ATInvalid, GAk_ATDataCollect, GAk_ATOrderTest, GAk_ATTherapy }; // Struct type for dealing with didactics enum GAt_StructType { GAk_Action, GAk_Step }; typedef struct t_GAt_Action { // GLIF fields tUInt4 id; string name; GAt_ActionType intention; CUt_UInt4Seq patient_data; string description; GSt_MaterialSeq didactics; // Supplemental fields tBoolean required; GAt_ActionMode mode; } GAt_Action; typedef sequence GAt_ActionSeq; // Node type enum GAt_NodeType { GAk_Geode, GAk_GlifBranch, GAk_GlifCond, GAk_GlifAction, GAk_GlifSync }; typedef sequence GAt_StringSeq; // High-level guideline step specification (supplements information // stored in the flowchart viewer; maps to several GLIF-level nodes) typedef struct t_GAt_Step { // Node type GAt_NodeType node_type; // Core fields tUInt4 id; GSt_MaterialSeq didactics; string eligibility; // Branches GSt_Selection branches_card; tUInt4 branches_k; GSt_Ordering branches_order; // Actions GSt_Selection action_card; tUInt4 action_k; CUt_UInt4Seq actions; // Conditions string spec; // Continuation for glif-syncronization nodes GSt_Continue cont; // URLs GAt_StringSeq urls; } GAt_Step; typedef sequence GAt_StepSeq; --------------------------- And here is the code itself --------------------------- /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::WriteToDisk() * * DESCRIPTION: * * Write this guideline to disk at the given file location; * the file will be overwritten. * * PARAMETERS: * * CORBA_Environment * -- The environment. * const char * -- The file name (full path) * * RETURNS: * * void. * * EXCEPTIONS: * * ex_CORBA_BAD_OPERATION -- File IO error * ex_CORBA_NO_RESOURCES -- Disk full * */ void _i_GAC_Auth::WriteToDisk(CORBA_Environment *ev, const char *filename) { tError err; ODC_ParseTree *parse = NULL; GOODMEM(ev); GOODMEM(filename); // Create parse tree parse = new ODC_ParseTree(); CHECK_MEM_EXCEPTION(parse, ev); // Build instances for patient data, actions, steps, and guideline // as a whole PackGuidelineObj(ev, parse); CHECK_EXCEPTION(ev); PackSteps(ev, parse); CHECK_EXCEPTION(ev); PackActions(ev, parse); CHECK_EXCEPTION(ev); PackPtData(ev, parse); CHECK_EXCEPTION(ev); // Write to file err = parse->WriteTree(filename, TRUE); CHECK_ERROR_EXCEPTION(err, ev); // Success delete parse; return; // Failure exception: if (parse != NULL) delete parse; return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::PackPtData() * * DESCRIPTION: * * Pack patient data definitions onto the given parse tree, for subsequent * output to disk. * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_ParseTree * -- Parse tree to add to * * RETURNS: * * void. * * EXCEPTIONS: * * None. * * NOTES: * * Packs a superset of GLIF, to include also the cardinality of the possible * values (one of, some of, all of, k of), min/max acceptible and normal * values, and a boolean constraint on values. * */ void _i_GAC_Auth::PackPtData(CORBA_Environment *ev, ODC_ParseTree *parse) { ODC_Class *ptdata_class; CUt_HashEntry *hash_e; CUt_HashSearch search; GAt_PatientData *data; ODC_InstanceID *ptdata_id = NULL; ODC_Instance *inst; tError err = kNoError; ODC_Member *mem; GOODMEM(ev); GOODMEM(parse); // Classes ptdata_class = parse->AddClass("Patient_Data"); CHECK_MEM_EXCEPTION(ptdata_class, ev); // Find first entry hash_e = CU_FirstHashEntry(&fPtDataDefns, &search); if (hash_e == NULL) return; // Write each item while (hash_e != NULL) { // Find item data = (GAt_PatientData *) (hash_e->clientData); GOODMEM(data); // Add instance for this data defn ptdata_id = new ODC_InstanceID(data->id, &err); CHECK_ERROR_EXCEPTION(err, ev); CHECK_MEM_EXCEPTION(ptdata_id, ev); inst = parse->AddInstance(ptdata_class, ptdata_id, FALSE); CHECK_MEM_EXCEPTION(inst, ev); ptdata_id = NULL; // Name and type if (data->name != NULL) { mem = inst->fMembers->AddStringMember("name", data->name, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } if (data->type != NULL) { mem = inst->fMembers->AddStringMember("type", data->type, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } // Possible values if (data->possible_values != NULL) { PackStringAsSequence(ev, data->possible_values, "possible_values", inst); CHECK_EXCEPTION(ev); } // Temporal constraint if (data->temporal_constraint != NULL) { mem = inst->fMembers->AddStringMember("temporal_constraint", data->temporal_constraint, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } // Didactics if (data->didactics != NULL) { PackStringAsSequence(ev, data->didactics, "didactics", inst); CHECK_EXCEPTION(ev); } // Cardinality : Not GLIF if (data->cardinality != GSk_BadValueSel) { mem = inst->fMembers->AddEnumMember("cardinality", GA_GSSelectionToString(data->cardinality, TRUE)); CHECK_MEM_EXCEPTION(mem, ev); if (data->cardinality == GSk_KOf) { mem = inst->fMembers->AddIntMember("k", data->k); CHECK_MEM_EXCEPTION(mem, ev); } } // Min/max value : Not GLIF if (data->min_max_specified) { mem = inst->fMembers->AddFloatMember("min_value", data->min_value, FALSE); CHECK_MEM_EXCEPTION(mem, ev); mem = inst->fMembers->AddFloatMember("max_value", data->max_value, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } // Min/max normal : Not GLIF if (data->normal_specified) { mem = inst->fMembers->AddFloatMember("min_normal", data->min_normal, FALSE); CHECK_MEM_EXCEPTION(mem, ev); mem = inst->fMembers->AddFloatMember("max_normal", data->max_normal, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } // Boolean constraint : Not GLIF if (data->boolean_constraint != NULL) { mem = inst->fMembers->AddStringMember("boolean_constraint", data->boolean_constraint, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } // Find next entry hash_e = CU_NextHashEntry(&search); } // Success return; // Failure exception: if (ptdata_id != NULL) delete ptdata_id; return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::PackActions() * * DESCRIPTION: * * Pack action items onto given parse tree, for subsequent output to disk. * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_ParseTree * -- Parse tree to add to. * * RETURNS: * * void. * * EXCEPTIONS: * * None. * * NOTES: * * Packs a superset of GLIF, to include also information on whether the * action is globally required, and mode information used for action * execution. * */ void _i_GAC_Auth::PackActions(CORBA_Environment *ev, ODC_ParseTree *parse) { ODC_Class *action_class; ODC_Class *pd_class; ODC_Class *material_class; CUt_HashEntry *hash_e; CUt_HashSearch search; GAt_Action *action; ODC_InstanceID *action_id = NULL; ODC_Instance *inst; tError err = kNoError; ODC_Member *mem; GOODMEM(ev); GOODMEM(parse); // Classes action_class = parse->AddClass("Action_Spec"); CHECK_MEM_EXCEPTION(action_class, ev); pd_class = parse->AddClass("Patient_Data"); CHECK_MEM_EXCEPTION(pd_class, ev); material_class = parse->AddClass("Local_Material"); CHECK_MEM_EXCEPTION(material_class, ev); // Find first entry hash_e = CU_FirstHashEntry(&fActions, &search); if (hash_e == NULL) return; // Write each item while (hash_e != NULL) { tUInt4 i; // Find item action = (GAt_Action *) (hash_e->clientData); GOODMEM(action); // Add instance for this action action_id = new ODC_InstanceID(action->id, &err); CHECK_ERROR_EXCEPTION(err, ev); CHECK_MEM_EXCEPTION(action_id, ev); inst = parse->AddInstance(action_class, action_id, FALSE); CHECK_MEM_EXCEPTION(inst, ev); action_id = NULL; // Name and intention if (action->name != NULL) { mem = inst->fMembers->AddStringMember("name", action->name, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } if (action->intention != GAk_ATInvalid) { mem = inst->fMembers->AddStringMember("intention", GA_ActionTypeToString(action->intention, TRUE), FALSE); CHECK_MEM_EXCEPTION(mem, ev); } // Patient data if (action->intention == GAk_ATDataCollect) { CUt_HashEntry *pd_hash_e; CUt_HashSearch pd_search; ODC_MemberList *pd_list; // Add sequence for objrefs mem = inst->fMembers->AddSeqMember("patient_data", &pd_list); CHECK_MEM_EXCEPTION(mem, ev); CHECK_MEM_EXCEPTION(pd_list, ev); // Add objrefs to patient data entries for (i = 0; i < action->patient_data._length; i++) { mem = pd_list->AddObjRefMember(NULL, pd_class, action->patient_data._buffer[i]); CHECK_MEM_EXCEPTION(mem, ev); } } // Description if (action->description != NULL) { mem = inst->fMembers->AddStringMember("description", action->description, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } // Didactics if (action->didactics._length > 0) { PackDidactics(ev, inst, GAk_Action, (void*) action, material_class); CHECK_EXCEPTION(ev); } // Whether or not manditory : Not GLIF mem = inst->fMembers->AddBoolMember("required", action->required); CHECK_MEM_EXCEPTION(mem, ev); // Mode : Not GLIF if (action->mode != GAk_AMInvalidMode) { mem = inst->fMembers->AddEnumMember("mode", GA_ActionModeToString(action->mode, TRUE)); CHECK_MEM_EXCEPTION(mem, ev); } // Find next entry hash_e = CU_NextHashEntry(&search); } // Success return; // Failure exception: if (action_id != NULL) delete action_id; return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::PackSteps() * * DESCRIPTION: * * Pack all guideline steps onto the given parse tree, for subsequent * output to disk. * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_ParseTree * -- Parse tree to add to. * * RETURNS: * * void. * * EXCEPTIONS: * * None. * * NOTES: * * Each step is mapped onto a collection of GLIF nodes, which as a whole * capture the information stored in the step. * * The group exported starts with a branch node, which branches to one * action node for each action associated with the step. The branch * node's selection method defines action cardinality. Each action * node contains one action. * * Following the action node, is a synch node with continuation set * to ProceedAfterOne. * * Following the synch node, is a second branch node that branches to * one conditional node for each outgoing branch on the step. The * branch node's selection method defines cardinality of outgoing * branches. Each conditional node contains the branch condition * and upon TRUE branches to the target of the corresponding outgoing * path. Upon FALSE, the conditional nodes branch to the NULL node. * * In the event that there are no actions in the node, the initial branch * node is used instead for branching directly to the conditionals (if any), * and its selection metho and cardinality define those of the conditionals * instead. * * The GLIF steps are output, one instance at a time, with identifier * denoted as GSXX_YY where XX is the step ID and YY is 0 for the initial * branch node, 1 for the first action node, and so on. Furthermore, * each each node that is part of a geode-level higher level node * contains a marker field called "geode", which is set to TRUE. Thus, * the higher-level step construct can unambiguously be reconstructed upon * subsequent disk read, and can be combined with lower-level constructs * if necessary. * * A superset of GLIF is output, to include also fields defining the * short_name of guideline steps, the short_spec for Criterions (contains * the short path label), and the selection_k for actions and conditions. * */ // Local utility to create step IDs static ODC_InstanceID *GA_MakeStepID(CORBA_Environment *ev, tUInt4 step_id, tUInt4 seq) { char tmp_str[64]; ODC_InstanceID *id; tError err; // Create identifier sprintf(tmp_str, "GS%d_%d", step_id, seq); id = new ODC_InstanceID(tmp_str, &err); CHECK_ERROR_EXCEPTION(err, ev); CHECK_MEM_EXCEPTION(id, ev); // Success return id; // Failure exception: return NULL; } // Implementation void _i_GAC_Auth::PackSteps(CORBA_Environment *ev, ODC_ParseTree *parse) { ODC_Class *bstep_class; ODC_Class *astep_class; ODC_Class *sstep_class; ODC_Class *cstep_class; ODC_Class *trans_class; ODC_Class *action_class; ODC_Class *criterion_class; ODC_Class *material_class; ODC_MemberList *criterion_list; CUt_HashEntry *hash_e; CUt_HashSearch search; GAt_Step *step; GAt_Step *tmp_step; FVt_TransitionSeq trans; FVt_IDLNode node; ODC_InstanceID *inst_id = NULL; ODC_Instance *inst; ODC_Member *mem; tError err = kNoError; tUInt4 i; char tmp_str[64]; GOODMEM(ev); GOODMEM(parse); // Set up CORBA_InitType(_tc_FVt_TransitionSeq, &trans); CORBA_InitType(_tc_FVt_IDLNode, &node); // Classes bstep_class = parse->AddClass("Branch_Step"); CHECK_MEM_EXCEPTION(bstep_class, ev); astep_class = parse->AddClass("Action_Step"); CHECK_MEM_EXCEPTION(astep_class, ev); sstep_class = parse->AddClass("Synchronization_Step"); CHECK_MEM_EXCEPTION(sstep_class, ev); cstep_class = parse->AddClass("Conditional_Step"); CHECK_MEM_EXCEPTION(cstep_class, ev); trans_class = parse->AddClass("Transition"); CHECK_MEM_EXCEPTION(trans_class, ev); action_class = parse->AddClass("Action_Spec"); CHECK_MEM_EXCEPTION(action_class, ev); criterion_class = parse->AddClass("Boolean_Criterion"); CHECK_MEM_EXCEPTION(criterion_class, ev); material_class = parse->AddClass("Local_Material"); CHECK_MEM_EXCEPTION(material_class, ev); // Find first entry hash_e = CU_FirstHashEntry(&fSteps, &search); if (hash_e == NULL) return; // Write each item while (hash_e != NULL) { tUInt4 step_seq; tUInt4 i; ODC_MemberList *branch_list; tUInt4 synch_id; // Find step step = (GAt_Step *) (hash_e->clientData); GOODMEM(step); node = fFV->GetNodeByID(ev, step->id); CHECK_EXCEPTION(ev); step_seq = 0; // // Create leading branch node: contains name / long name / didactics // and branches to action nodes, if there are actions (or to any existing // conditionals, if there are no actions). // if (step->node_type == GAk_Geode) { // geode node // Add instance for branch node inst_id = GA_MakeStepID(ev, step->id, step_seq++); CHECK_EXCEPTION(ev); inst = parse->AddInstance(bstep_class, inst_id, FALSE); CHECK_MEM_EXCEPTION(inst, ev); inst_id = NULL; // Add Geode marker mem = inst->fMembers->AddBoolMember("geode", TRUE); CHECK_MEM_EXCEPTION(mem, ev); } else { // glif node // Create identifier sprintf(tmp_str, "%d", step->id); inst_id = new ODC_InstanceID(tmp_str, &err); CHECK_ERROR_EXCEPTION(err, ev); CHECK_MEM_EXCEPTION(inst_id, ev); if (step->node_type == GAk_GlifBranch) inst = parse->AddInstance(bstep_class, inst_id, FALSE); else if (step->node_type == GAk_GlifCond) inst = parse->AddInstance(cstep_class, inst_id, FALSE); if (step->node_type == GAk_GlifAction) inst = parse->AddInstance(astep_class, inst_id, FALSE); if (step->node_type == GAk_GlifSync) inst = parse->AddInstance(sstep_class, inst_id, FALSE); CHECK_MEM_EXCEPTION(inst, ev); } // Name if (step->node_type == GAk_GlifCond) { mem = inst->fMembers->AddStringMember("name", "", FALSE); CHECK_MEM_EXCEPTION(mem, ev); } else if ((node.long_name != NULL) && (strlen(node.long_name) > 0)) { mem = inst->fMembers->AddStringMember("name", node.long_name, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } else if ((node.short_name != NULL) && (strlen(node.short_name) > 0)) { mem = inst->fMembers->AddStringMember("name", node.short_name, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } else { mem = inst->fMembers->AddStringMember("name", "", FALSE); CHECK_MEM_EXCEPTION(mem, ev); } if (step->node_type == GAk_Geode) { // GEODE STEP // Short name : Not GLIF if ((node.long_name != NULL) && (strlen(node.long_name) > 0) && (node.short_name != NULL)) { mem = inst->fMembers->AddStringMember("short_name", node.short_name, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } // Eligibility : Not GLIF if (step->eligibility != NULL) { PackStringAsSequence(ev, step->eligibility, "eligibility", inst); CHECK_EXCEPTION(ev); } // // Add branches to action nodes, if any // if (step->actions._length > 0) { // Selection method if (step->action_card != GSk_BadValueSel) { mem = inst->fMembers->AddEnumMember("selection_method", GA_GSSelectionToString(step->action_card, TRUE)); CHECK_MEM_EXCEPTION(mem, ev); } // Selection K: Not GLIF if (step->action_card == GSk_KOf) { mem = inst->fMembers->AddIntMember("selection_k", step->action_k); CHECK_MEM_EXCEPTION(mem, ev); } // Order constraint mem = inst->fMembers->AddEnumMember("order_constraint", "AnyOrder"); CHECK_MEM_EXCEPTION(mem, ev); // Branches to action nodes mem = inst->fMembers->AddSeqMember("branches", &branch_list); CHECK_MEM_EXCEPTION(mem, ev); CHECK_MEM_EXCEPTION(branch_list, ev); for (i = 0; i < step->actions._length; i++) { sprintf(tmp_str, "GS%d_%d", step->id, step_seq + i); mem = branch_list->AddObjRefMember(NULL, astep_class, tmp_str); CHECK_MEM_EXCEPTION(mem, ev); } } // // Action nodes, one for each action in the step, if any // synch_id = step_seq + step->actions._length; for (i = 0; i < step->actions._length; i++) { // Add instance for action node inst_id = GA_MakeStepID(ev, step->id, step_seq++); CHECK_EXCEPTION(ev); inst = parse->AddInstance(astep_class, inst_id, FALSE); CHECK_MEM_EXCEPTION(inst, ev); inst_id = NULL; // Geode marker mem = inst->fMembers->AddBoolMember("geode", TRUE); CHECK_MEM_EXCEPTION(mem, ev); // Action mem = inst->fMembers->AddObjRefMember("action", action_class, step->actions._buffer[i]); CHECK_MEM_EXCEPTION(mem, ev); // Next step sprintf(tmp_str, "GS%d_%d", step->id, synch_id); mem = inst->fMembers->AddObjRefMember("next_step", sstep_class, tmp_str); CHECK_MEM_EXCEPTION(mem, ev); } // // Synch node, if there were action nodes // if (step->actions._length > 0) { // Add instance for synch node ASSERT(synch_id == step_seq); inst_id = GA_MakeStepID(ev, step->id, step_seq++); CHECK_EXCEPTION(ev); inst = parse->AddInstance(sstep_class, inst_id, FALSE); CHECK_MEM_EXCEPTION(inst, ev); inst_id = NULL; // Geode marker mem = inst->fMembers->AddBoolMember("geode", TRUE); CHECK_MEM_EXCEPTION(mem, ev); // Next step sprintf(tmp_str, "GS%d_%d", step->id, step_seq); mem = inst->fMembers->AddObjRefMember("next_step", bstep_class, tmp_str); CHECK_MEM_EXCEPTION(mem, ev); // Continuation information mem = inst->fMembers->AddEnumMember("continuation", "ProceedAfterOne"); CHECK_MEM_EXCEPTION(mem, ev); } // // Branch node for transitions, if there were action nodes // (else just use the main branch node, already created above) // // Get transitions info from FV fFV->GetNextNodes(ev, step->id, 1, &trans); CHECK_EXCEPTION(ev); // Add branch step if needed if ((step->actions._length > 0) && (trans._length > 0)) { // Add instance for branch node inst_id = GA_MakeStepID(ev, step->id, step_seq++); CHECK_EXCEPTION(ev); inst = parse->AddInstance(bstep_class, inst_id, FALSE); CHECK_MEM_EXCEPTION(inst, ev); inst_id = NULL; // Geode marker mem = inst->fMembers->AddBoolMember("geode", TRUE); CHECK_MEM_EXCEPTION(mem, ev); } // // Branch info for transitions, if any // if (trans._length > 0) { // Selection method if (step->branches_card != GSk_BadValueSel) { mem = inst->fMembers->AddEnumMember("selection_method", GA_GSSelectionToString(step->branches_card, TRUE)); CHECK_MEM_EXCEPTION(mem, ev); } // Selection K: Not GLIF if (step->branches_card == GSk_KOf) { mem = inst->fMembers->AddIntMember("selection_k", step->branches_k); CHECK_MEM_EXCEPTION(mem, ev); } // Order constraint if (step->branches_order != GSk_BadValueOrder) { mem = inst->fMembers->AddEnumMember("order_constraint", GA_GSOrderingToString(step->branches_order, TRUE)); CHECK_MEM_EXCEPTION(mem, ev); } // Branches to conditional nodes mem = inst->fMembers->AddSeqMember("branches", &branch_list); CHECK_MEM_EXCEPTION(mem, ev); CHECK_MEM_EXCEPTION(branch_list, ev); for (i = 0; i < trans._length; i++) { sprintf(tmp_str, "GS%d_%d", step->id, step_seq + i); mem = branch_list->AddObjRefMember(NULL, cstep_class, tmp_str); CHECK_MEM_EXCEPTION(mem, ev); } } // // Conditional nodes, if any // if (trans._length > 0) { // Add nodes for (i = 0; i < trans._length; i++) { char *tmp_str2; char *empty_str = ""; // Add instance for conditional node inst_id = GA_MakeStepID(ev, step->id, step_seq++); CHECK_EXCEPTION(ev); inst = parse->AddInstance(cstep_class, inst_id, FALSE); CHECK_MEM_EXCEPTION(inst, ev); inst_id = NULL; // Geode marker mem = inst->fMembers->AddBoolMember("geode", TRUE); CHECK_MEM_EXCEPTION(mem, ev); // Destination sprintf(tmp_str, "GS%d_%d", trans._buffer[i].dest, 0); mem = inst->fMembers->AddObjRefMember("destination", bstep_class, tmp_str); CHECK_MEM_EXCEPTION(mem, ev); // Otherwise mem = inst->fMembers->AddObjRefMember("otherwise", bstep_class, (const char *) NULL); CHECK_MEM_EXCEPTION(mem, ev); // Criterion mem = inst->fMembers->AddInstanceMember("condition", criterion_class, "", &criterion_list); CHECK_MEM_EXCEPTION(mem, ev); CHECK_MEM_EXCEPTION(criterion_list, ev); // Criterion type mem = criterion_list->AddEnumMember("type", "three_valued"); CHECK_MEM_EXCEPTION(mem, ev); // Criterion spec (use transition long name) tmp_str2 = trans._buffer[i].long_name; if ((tmp_str2 == NULL) || strlen(tmp_str2) == 0) tmp_str2 = trans._buffer[i].short_name; if ((tmp_str2 == NULL) || strlen(tmp_str2) == 0) tmp_str2 = empty_str; mem = criterion_list->AddStringMember("spec", tmp_str2, FALSE); CHECK_MEM_EXCEPTION(mem, ev); // Criterion short spec : Not GLIF if ((tmp_str2 != trans._buffer[i].short_name) && (trans._buffer[i].short_name != NULL) && (strlen(trans._buffer[i].short_name) > 0)) { mem = criterion_list->AddStringMember("short_spec", trans._buffer[i].short_name, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } } } } else { // GLIF STEP switch (step->node_type) { case GAk_GlifBranch: { // Add branches mem = inst->fMembers->AddSeqMember("branches", &branch_list); CHECK_MEM_EXCEPTION(mem, ev); CHECK_MEM_EXCEPTION(branch_list, ev); for (i = 0; i < step->actions._length; i++) { sprintf(tmp_str, "%d", step->actions._buffer[i]); tmp_step = FindStepPtrByID(ev, step->actions._buffer[i]); if (tmp_step->node_type == GAk_GlifAction) mem = branch_list->AddObjRefMember(NULL, astep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifBranch) mem = branch_list->AddObjRefMember(NULL, bstep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifCond) mem = branch_list->AddObjRefMember(NULL, cstep_class, tmp_str); CHECK_MEM_EXCEPTION(mem, ev); } // add selection method if (step->branches_card != GSk_BadValueSel) { mem = inst->fMembers->AddEnumMember("selection_method", GA_GSSelectionToString(step->branches_card, TRUE)); CHECK_MEM_EXCEPTION(mem, ev); } // add order constraint if (step->branches_order != GSk_BadValueOrder) { mem = inst->fMembers->AddEnumMember("order_constraint", GA_GSOrderingToString(step->branches_order, TRUE)); CHECK_MEM_EXCEPTION(mem, ev); } break; } case GAk_GlifCond: { sprintf(tmp_str, "%d", step->actions._buffer[0]); // Criterion mem = inst->fMembers->AddInstanceMember("condition", criterion_class, "", &criterion_list); // Criterion type mem = criterion_list->AddEnumMember("type", "three_valued"); CHECK_MEM_EXCEPTION(mem, ev); // Criterion spec (use transition long name) mem = criterion_list->AddStringMember("spec", step->spec, FALSE); CHECK_MEM_EXCEPTION(mem, ev); // Destination sprintf(tmp_str, "%d", step->actions._buffer[1]); tmp_step = FindStepPtrByID(ev, step->actions._buffer[1]); if (tmp_step == NULL) { USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); } else if (tmp_step->node_type == GAk_GlifAction) mem = inst->fMembers->AddObjRefMember("destination", astep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifBranch) mem = inst->fMembers->AddObjRefMember("destination", bstep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifCond) mem = inst->fMembers->AddObjRefMember("destination", cstep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifSync) mem = inst->fMembers->AddObjRefMember("destination", sstep_class, tmp_str); CHECK_MEM_EXCEPTION(mem, ev); // Otherwise sprintf(tmp_str, "%d", step->actions._buffer[2]); tmp_step = FindStepPtrByID(ev, step->actions._buffer[2]); if (tmp_step == NULL) mem = inst->fMembers->AddObjRefMember("otherwise", NULL,(const char*) NULL); else if (tmp_step->node_type == GAk_GlifAction) mem = inst->fMembers->AddObjRefMember("otherwise", astep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifBranch) mem = inst->fMembers->AddObjRefMember("otherwise", bstep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifCond) mem = inst->fMembers->AddObjRefMember("otherwise", cstep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifSync) mem = inst->fMembers->AddObjRefMember("otherwise", sstep_class, tmp_str); CHECK_MEM_EXCEPTION(mem, ev); break; } case GAk_GlifAction: { // Action spec mem = inst->fMembers->AddObjRefMember("action", action_class, step->actions._buffer[0]); CHECK_MEM_EXCEPTION(mem, ev); // Next step sprintf(tmp_str, "%d", step->actions._buffer[1]); tmp_step = FindStepPtrByID(ev, step->actions._buffer[1]); if (tmp_step == NULL) mem = inst->fMembers->AddObjRefMember("next_step", NULL,(const char*) NULL); else if (tmp_step->node_type == GAk_GlifAction) mem = inst->fMembers->AddObjRefMember("next_step", astep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifBranch) mem = inst->fMembers->AddObjRefMember("next_step", bstep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifCond) mem = inst->fMembers->AddObjRefMember("next_step", cstep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifSync) mem = inst->fMembers->AddObjRefMember("next_step", sstep_class, tmp_str); CHECK_MEM_EXCEPTION(mem, ev); break; } case GAk_GlifSync: { // Next step sprintf(tmp_str, "%d", step->actions._buffer[0]); tmp_step = FindStepPtrByID(ev, step->actions._buffer[0]); if (tmp_step == NULL) mem = inst->fMembers->AddObjRefMember("next_step", NULL,(const char*) NULL); else if (tmp_step->node_type == GAk_GlifAction) mem = inst->fMembers->AddObjRefMember("next_step", astep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifBranch) mem = inst->fMembers->AddObjRefMember("next_step", bstep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifCond) mem = inst->fMembers->AddObjRefMember("next_step", cstep_class, tmp_str); else if (tmp_step->node_type == GAk_GlifSync) mem = inst->fMembers->AddObjRefMember("next_step", sstep_class, tmp_str); CHECK_MEM_EXCEPTION(mem, ev); // continue mem = inst->fMembers->AddEnumMember("continue", GA_ContinueToString(step->cont)); CHECK_MEM_EXCEPTION(mem, ev); break; } } } // Didactics if (step->didactics._length > 0) { PackDidactics(ev, inst, GAk_Step, (void*) step, material_class); CHECK_EXCEPTION(ev); } // Find next entry CORBA_ClearType(_tc_FVt_TransitionSeq, &trans); CORBA_ClearType(_tc_FVt_IDLNode, &node); hash_e = CU_NextHashEntry(&search); } // Success return; // Failure exception: if (inst_id != NULL) delete inst_id; CORBA_ClearType(_tc_FVt_IDLNode, &node); CORBA_ClearType(_tc_FVt_TransitionSeq, &trans); return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::PackGuidelineObj() * * DESCRIPTION: * * Pack main guideline object onto given parse tree, for subsequent * output to disk. * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_ParseTree * -- Parse tree to add to. * * RETURNS: * * void. * * EXCEPTIONS: * * None. * */ void _i_GAC_Auth::PackGuidelineObj(CORBA_Environment *ev, ODC_ParseTree *parse) { tError err; ODC_Instance *inst; ODC_Class *guide_class; ODC_Class *bstep_class; ODC_Class *cstep_class; ODC_Class *astep_class; ODC_Class *sstep_class; ODC_InstanceID *guide_id = NULL; ODC_Member *mem; char *tmp_str; CUt_HashEntry *hash_e; CUt_HashSearch search; tUInt4 root_id; ODC_MemberList *auth_list; ODC_MemberList *step_list; ODC_MemberList *did_list; char tmp_str2[64]; GAt_Step *tmp_step; tUInt4 i; GOODMEM(ev); GOODMEM(parse); // Instance, classes guide_class = parse->AddClass("Guideline"); CHECK_MEM_EXCEPTION(guide_class, ev); bstep_class = parse->AddClass("Branch_Step"); CHECK_MEM_EXCEPTION(bstep_class, ev); cstep_class = parse->AddClass("Conditional_Step"); CHECK_MEM_EXCEPTION(cstep_class, ev); astep_class = parse->AddClass("Action_Step"); CHECK_MEM_EXCEPTION(astep_class, ev); sstep_class = parse->AddClass("Synchronization_Step"); CHECK_MEM_EXCEPTION(sstep_class, ev); // sprintf(tmp_str2, "%d", fGuideInfo.id); guide_id = new ODC_InstanceID("", &err); CHECK_ERROR_EXCEPTION(err, ev); CHECK_MEM_EXCEPTION(guide_id, ev); inst = parse->AddInstance(guide_class, guide_id, FALSE); CHECK_MEM_EXCEPTION(inst, ev); guide_id = NULL; // Name tmp_str = fFV->Get_fName(ev); CHECK_MEM_EXCEPTION(tmp_str, ev); mem = inst->fMembers->AddStringMember("name", tmp_str, FALSE); CORBA_free(tmp_str); CHECK_MEM_EXCEPTION(mem, ev); // Authors mem = inst->fMembers->AddSeqMember("authors", &auth_list); CHECK_MEM_EXCEPTION(mem, ev); CHECK_MEM_EXCEPTION(auth_list, ev); for (i = 0; i < fGuideInfo.authors._length; i++) { mem = auth_list->AddStringMember("", fGuideInfo.authors._buffer[i], FALSE); CHECK_MEM_EXCEPTION(mem, ev); } // Eligibility criteria #if ADDLATER UNFINISHED; mem = inst->fMembers->AddObjRefMember("eligibility_criteria", NULL); CHECK_MEM_EXCEPTION(mem, ev); #endif // Intention mem = inst->fMembers->AddStringMember("intention", fGuideInfo.intention, FALSE); CHECK_MEM_EXCEPTION(mem, ev); // Sequence of steps contained by guideline mem = inst->fMembers->AddSeqMember("steps", &step_list); CHECK_MEM_EXCEPTION(mem, ev); CHECK_MEM_EXCEPTION(step_list, ev); hash_e = CU_FirstHashEntry(&fSteps, &search); if (hash_e != NULL) { while (hash_e != NULL) { GAt_Step *step; // Add step obj ref to sequence step = (GAt_Step *) (hash_e->clientData); GOODMEM(step); if (step->node_type == GAk_Geode) { sprintf(tmp_str2, "GS%d_%d", step->id, 0); mem = step_list->AddObjRefMember(NULL, bstep_class, tmp_str2); } else { // Glif step sprintf(tmp_str2, "%d", step->id); if (step->node_type == GAk_GlifAction) mem = step_list->AddObjRefMember(NULL, astep_class, tmp_str2); else if (step->node_type == GAk_GlifBranch) mem = step_list->AddObjRefMember(NULL, bstep_class, tmp_str2); else if (step->node_type == GAk_GlifCond) mem = step_list->AddObjRefMember(NULL, cstep_class, tmp_str2); else if (step->node_type == GAk_GlifSync) mem = step_list->AddObjRefMember(NULL, sstep_class, tmp_str2); } CHECK_MEM_EXCEPTION(mem, ev); // Find next entry hash_e = CU_NextHashEntry(&search); } } // First step in guideline root_id = fFV->Get_fRootNodeID(ev); CHECK_EXCEPTION(ev); tmp_step = FindStepPtrByID(ev, root_id); CHECK_EXCEPTION(ev); if (tmp_step->node_type == GAk_Geode) { // Add Geode marker mem = inst->fMembers->AddBoolMember("geode", TRUE); CHECK_MEM_EXCEPTION(mem, ev); sprintf(tmp_str2, "GS%d_%d", root_id, 0); mem = inst->fMembers->AddObjRefMember("first_step", bstep_class, tmp_str2); } else { // glif step sprintf(tmp_str2, "%d", root_id); if (tmp_step->node_type == GAk_GlifBranch) mem = inst->fMembers->AddObjRefMember("first_step", bstep_class, tmp_str2); else if (tmp_step->node_type == GAk_GlifAction) mem = inst->fMembers->AddObjRefMember("first_step", astep_class, tmp_str2); else if (tmp_step->node_type == GAk_GlifCond) mem = inst->fMembers->AddObjRefMember("first_step", cstep_class, tmp_str2); } CHECK_MEM_EXCEPTION(mem, ev); // Didactics mem = inst->fMembers->AddSeqMember("didactics", &did_list); CHECK_MEM_EXCEPTION(mem, ev); CHECK_MEM_EXCEPTION(did_list, ev); UNFINISHED; // Fill did_list! // Success return; // Failure exception: if (guide_id != NULL) delete guide_id; return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::PackStringAsSequence() * * DESCRIPTION: * * Pack the given string as a sequence with given name, treating each * line (\n-seperated) as one entry in the sequence. The sequence is * appended to the given instance. * * PARAMETERS: * * CORBA_Environment * -- The environment. * char * -- The string. * const char * -- The name of the sequence. * ODC_Instance * -- The instance to add sequence to. * * RETURNS: * * void. * * EXCEPTIONS: * * None. * */ void _i_GAC_Auth::PackStringAsSequence(CORBA_Environment *ev, char *str, const char *list_name, ODC_Instance *inst) { ODC_Member *mem; ODC_MemberList *val_list; tUInt4 i, last_pos; // Create sequence mem = inst->fMembers->AddSeqMember(list_name, &val_list); CHECK_MEM_EXCEPTION(mem, ev); CHECK_MEM_EXCEPTION(val_list, ev); // Add values, one per line for (last_pos = 0, i = 0; i < strlen(str); i++) { if (str[i] == '\n') { str[i] = '\0'; mem = val_list->AddStringMember(NULL, &str[last_pos], FALSE); str[i] = '\n'; CHECK_MEM_EXCEPTION(mem, ev); last_pos = i + 1; } } // Success return; // Failure exception: return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::PackDidactics() * * DESCRIPTION: * * Pack didactics * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_Instance * -- The instance to add sequence to. * GAt_StructType -- The type of structure. * void * -- The step or action. * ODC_Class * -- The material class. * * RETURNS: * * void. * * EXCEPTIONS: * * None. * */ void _i_GAC_Auth::PackDidactics(CORBA_Environment *ev, ODC_Instance *inst, GAt_StructType ga_struct, void* the_struct, ODC_Class *material_class) { GAt_Step *step; GAt_Action *action; ODC_Member *mem; ODC_MemberList *val_list; ODC_MemberList *local_list; tUInt4 i, last_pos; GOODMEM(ev); GOODMEM(inst); GOODMEM(the_struct); GOODMEM(material_class); // Create sequence mem = inst->fMembers->AddSeqMember("didactics", &val_list); CHECK_MEM_EXCEPTION(mem, ev); CHECK_MEM_EXCEPTION(val_list, ev); if (ga_struct == GAk_Step) { step = (GAt_Step*) the_struct; for (i = 0; i < step->didactics._length; i++) { mem = val_list->AddInstanceMember(NULL, material_class, "", &local_list); CHECK_MEM_EXCEPTION(mem, ev); mem = local_list->AddStringMember("label", step->didactics._buffer[i].label, FALSE); CHECK_MEM_EXCEPTION(mem, ev); mem = local_list->AddStringMember("MIME_type", step->didactics._buffer[i].MIME_type, FALSE); CHECK_MEM_EXCEPTION(mem, ev); mem = local_list->AddStringMember("material", step->didactics._buffer[i].data._u.material, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } } else if (ga_struct == GAk_Action) { action = (GAt_Action*) the_struct; for (i = 0; i < action->didactics._length; i++) { mem = val_list->AddInstanceMember(NULL, material_class, "", &local_list); CHECK_MEM_EXCEPTION(mem, ev); mem = local_list->AddStringMember("label", action->didactics._buffer[i].label, FALSE); CHECK_MEM_EXCEPTION(mem, ev); mem = local_list->AddStringMember("MIME_type", action->didactics._buffer[i].MIME_type, FALSE); CHECK_MEM_EXCEPTION(mem, ev); mem = local_list->AddStringMember("material", action->didactics._buffer[i].data._u.material, FALSE); CHECK_MEM_EXCEPTION(mem, ev); } } // Success return; // Failure exception: return; } #endif /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::ReadFromDisk() * * DESCRIPTION: * * Read a guideline from disk, from the given file * * PARAMETERS: * * CORBA_Environment * -- The environment. * const char * -- The file name (full path) * * RETURNS: * * void. * * EXCEPTIONS: * * ex_CORBA_BAD_PARAM -- Parse error while reading from disk. * ex_CORBA_PERSIST_STORE -- Could not open / find file. * * NOTES: * * Currently assumes one guideline per file; should be restructured later * so that UnpackGuideline drives loading of the appropriate steps into * the guideline. Also need to provide an interface for choosing which * guideline to read, etc. * */ void _i_GAC_Auth::ReadFromDisk(CORBA_Environment *ev, const char *filename) { FILE *file; char tmpstr[256]; tUInt4 root_id; tError err; ODt_ParseError perr; ODC_ParseTree *parse = NULL; GOODMEM(ev); GOODMEM(filename); // Clear any existing guideline data ClearAll(ev); CHECK_EXCEPTION(ev); // Check file type file = fopen(filename, "r"); if (file == NULL) USER_EXCEPTION(ev, ex_CORBA_PERSIST_STORE); fscanf(file, "%s\n", tmpstr); fclose(file); if (!strcmp(tmpstr, "START-GUIDELINE")) { OldReadFromDisk(ev, filename); CHECK_EXCEPTION(ev); return; } // Create GLIF parse tree parse = new ODC_ParseTree(); CHECK_MEM_EXCEPTION(parse, ev); // Read from file err = parse->ReadTree(filename, &perr); CHECK_ERROR_EXCEPTION(err, ev); // Build internal datastructures for patient data, actions, steps, // and guideline as a whole UnpackPtData(ev, parse); CHECK_EXCEPTION(ev); UnpackActions(ev, parse); CHECK_EXCEPTION(ev); UnpackSteps(ev, parse); CHECK_EXCEPTION(ev); UnpackTransitions(ev, parse); CHECK_EXCEPTION(ev); UnpackGuidelineObj(ev, parse); CHECK_EXCEPTION(ev); // Success delete parse; return; // Failure exception: if (parse != NULL) delete parse; return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::UnpackPtData() * * DESCRIPTION: * * Unpack patient data definitions from the given parse tree. * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_ParseTree * -- Parse tree. * * RETURNS: * * void. * * EXCEPTIONS: * * ex_CORBA_BAD_PARAM -- Parse error during unpack. * * NOTES: * * Unpacks a superset of GLIF, including also the cardinality of the possible * values (one of, some of, all of, k of), min/max acceptible and normal * values, and a boolean constraint on values. * */ void _i_GAC_Auth::UnpackPtData(CORBA_Environment *ev, ODC_ParseTree *parse) { GAt_PatientData data; ODC_Class *ptdata_class; ODC_Instance *inst; ODC_Member *mem; ODC_SeqValue *seq_val; ODC_StringValue *str_val; ODC_IntValue *int_val; ODC_FloatValue *float_val; ODC_EnumValue *enum_val; tUInt4 i; tError err = kNoError; tUInt4 value; GOODMEM(ev); GOODMEM(parse); // Set up CORBA_InitType(_tc_GAt_PatientData, &data); // Look up class; if none, then no patient data in file ptdata_class = parse->FindClassByName("Patient_Data"); if (ptdata_class == NULL) return; // Find first entry inst = ptdata_class->FindFirstInstance(); // Read each entry while (inst != NULL) { // Set data defn ID if (inst->fId->fIDType == ODk_IID_UNSIGNED_INT) { int_val = ODC_IntValue::narrow(inst->fId->fInstID.uns_int); value = int_val->fValue.uint; } else if (inst->fId->fIDType == ODk_IID_DEC_FLOAT) { float_val = ODC_FloatValue::narrow(inst->fId->fInstID.dec_float); value = (tUInt4) float_val->fValue; } else BARF; data.id = value; // Read through all members in instance for other data defn fields for (i = 0; i < inst->fMembers->fMembers._length; i++) { // Get this member mem = inst->fMembers->fMembers._buffer[i]; GOODMEM(mem); // Name member if (!strcmp(mem->fName->fStr, "name")) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &data.name, &str_val->fStr); CHECK_EXCEPTION(ev); } // Type member else if (!strcmp(mem->fName->fStr, "type")) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &data.type, &str_val->fStr); CHECK_EXCEPTION(ev); } // Possible values member else if (!strcmp(mem->fName->fStr, "possible_values")) { seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); data.possible_values = UnpackStringFromSequence(ev, seq_val); CHECK_EXCEPTION(ev); } // Temporal constraint member else if (!strcmp(mem->fName->fStr, "temporal_constraint")) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &data.temporal_constraint, &str_val->fStr); CHECK_EXCEPTION(ev); } // Didactics member else if (!strcmp(mem->fName->fStr, "didactics")) { seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); data.didactics = UnpackStringFromSequence(ev, seq_val); CHECK_EXCEPTION(ev); } // Cardinality type member : Not GLIF else if (!strcmp(mem->fName->fStr, "cardinality")) { enum_val = ODC_EnumValue::narrow(mem->fValue); if (enum_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); data.cardinality = GA_StringToGSSelection(enum_val->fIdent->fStr); } // Cardinality K member : Not GLIF else if (!strcmp(mem->fName->fStr, "k")) { int_val = ODC_IntValue::narrow(mem->fValue); if (int_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); data.k = int_val->fValue.uint; data.cardinality = GSk_KOf; } // Min/max value : Not GLIF else if (!strcmp(mem->fName->fStr, "min_value")) { float_val = ODC_FloatValue::narrow(mem->fValue); if (float_val != NULL) data.min_value = float_val->fValue; else { int_val = ODC_IntValue::narrow(mem->fValue); if (int_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (int_val->fType == ODk_IVT_UNSIGNED) data.min_value = int_val->fValue.uint; else data.min_value = int_val->fValue.sint; } data.min_max_specified = TRUE; } else if (!strcmp(mem->fName->fStr, "max_value")) { float_val = ODC_FloatValue::narrow(mem->fValue); if (float_val != NULL) data.max_value = float_val->fValue; else { int_val = ODC_IntValue::narrow(mem->fValue); if (int_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (int_val->fType == ODk_IVT_UNSIGNED) data.max_value = int_val->fValue.uint; else data.max_value = int_val->fValue.sint; } data.min_max_specified = TRUE; } // Min/max normal : Not GLIF else if (!strcmp(mem->fName->fStr, "min_normal")) { float_val = ODC_FloatValue::narrow(mem->fValue); if (float_val != NULL) data.min_normal = float_val->fValue; else { int_val = ODC_IntValue::narrow(mem->fValue); if (int_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (int_val->fType == ODk_IVT_UNSIGNED) data.min_normal = int_val->fValue.uint; else data.min_normal = int_val->fValue.sint; } data.normal_specified = TRUE; } else if (!strcmp(mem->fName->fStr, "max_normal")) { float_val = ODC_FloatValue::narrow(mem->fValue); if (float_val != NULL) data.max_normal = float_val->fValue; else { int_val = ODC_IntValue::narrow(mem->fValue); if (int_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (int_val->fType == ODk_IVT_UNSIGNED) data.max_normal = int_val->fValue.uint; else data.max_normal = int_val->fValue.sint; } data.normal_specified = TRUE; } // Boolean constraint : Not GLIF else if (!strcmp(mem->fName->fStr, "boolean_constraint")) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &data.boolean_constraint, &str_val->fStr); CHECK_EXCEPTION(ev); } } // Add to datastructures UpdatePatientData(ev, &data, FALSE); CHECK_EXCEPTION(ev); CORBA_ClearType(_tc_GAt_PatientData, &data); // Next patient data defn instance inst = ptdata_class->FindNextInstance(); } // Success return; // Failure exception: CORBA_ClearType(_tc_GAt_PatientData, &data); return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::UnpackActions() * * DESCRIPTION: * * Unpack action items from given parse tree. * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_ParseTree * -- Parse tree. * * RETURNS: * * void. * * EXCEPTIONS: * * None. * * NOTES: * * Unpacks a superset of GLIF, including also information on whether the * action is globally required, and mode information used for action * execution. * */ void _i_GAC_Auth::UnpackActions(CORBA_Environment *ev, ODC_ParseTree *parse) { GAt_Action action; ODC_Class *action_class; ODC_Instance *inst; ODC_Member *mem; ODC_SeqValue *seq_val; ODC_StringValue *str_val; ODC_EnumValue *enum_val; ODC_BooleanValue *bool_val; tUInt4 i; tError err = kNoError; ODC_ObjRefValue *obj_val; ODC_IntValue *int_val; ODC_FloatValue *float_val; tUInt4 value; GOODMEM(ev); GOODMEM(parse); // Set up CORBA_InitType(_tc_GAt_Action, &action); // Look up class; if none, then no patient data in file action_class = parse->FindClassByName("Action_Spec"); if (action_class == NULL) return; // Find first entry inst = action_class->FindFirstInstance(); // Read each entry while (inst != NULL) { // Set action spec ID if (inst->fId->fIDType == ODk_IID_UNSIGNED_INT) { int_val = ODC_IntValue::narrow(inst->fId->fInstID.uns_int); value = int_val->fValue.uint; } else if (inst->fId->fIDType == ODk_IID_DEC_FLOAT) { float_val = ODC_FloatValue::narrow(inst->fId->fInstID.dec_float); value = (tUInt4) float_val->fValue; } else BARF; action.id = value; // Read through all members in instance for other action fields for (i = 0; i < inst->fMembers->fMembers._length; i++) { // Get this member mem = inst->fMembers->fMembers._buffer[i]; GOODMEM(mem); // Name member if (!strcmp(mem->fName->fStr, "name")) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &action.name, &str_val->fStr); CHECK_EXCEPTION(ev); } // Intention member else if (!strcmp(mem->fName->fStr, "intention")) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); action.intention = GA_StringToActionType(str_val->fStr); } // Patient data list member else if (!strcmp(mem->fName->fStr, "patient_data")) { tUInt4 j; // Get sequence seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Get IDs for (j = 1; j <= seq_val->fItems->fMembers._length; j++) { // Extract integer ID from multiple layers obj_val = ODC_ObjRefValue::narrow(seq_val->fItems->NthMember(j)->fValue); if (obj_val != NULL) { // Patient data is a reference if (obj_val->fId->fIDType == ODk_IID_UNSIGNED_INT) { int_val = ODC_IntValue::narrow(obj_val->fId->fInstID.uns_int); value = int_val->fValue.uint; } else if (obj_val->fId->fIDType == ODk_IID_DEC_FLOAT) { float_val = ODC_FloatValue::narrow(obj_val->fId->fInstID.dec_float); value = (tUInt4) float_val->fValue * 10 + j; } } else { // embedded class inst = ODC_Instance::narrow(seq_val->fItems->NthMember(j)->fValue); if (inst->fId->fIDType == ODk_IID_UNSIGNED_INT) { int_val = ODC_IntValue::narrow(inst->fId->fInstID.uns_int); value = int_val->fValue.uint; } else if (inst->fId->fIDType == ODk_IID_DEC_FLOAT) { float_val = ODC_FloatValue::narrow(inst->fId->fInstID.dec_float); value = (tUInt4) float_val->fValue * 10 + j; } } if (int_val == NULL && float_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Append ID to list if (CORBA_SeqAppend(&action.patient_data, &value, sizeof(tUInt4)) != kNoError) MEMORY_EXCEPTION(ev); } } // Temporal constraint member else if (!strcmp(mem->fName->fStr, "description")) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &action.description, &str_val->fStr); CHECK_EXCEPTION(ev); } // Didactics member else if (!strcmp(mem->fName->fStr, "didactics")) { seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); action.didactics = UnpackDidactics(ev, seq_val); CHECK_EXCEPTION(ev); } // Required member : Not GLIF else if (!strcmp(mem->fName->fStr, "required")) { bool_val = ODC_BooleanValue::narrow(mem->fValue); if (bool_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); action.required = bool_val->fValue; } // Mode member : Not GLIF else if (!strcmp(mem->fName->fStr, "mode")) { enum_val = ODC_EnumValue::narrow(mem->fValue); if (enum_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); action.mode = GA_StringToActionMode(enum_val->fIdent->fStr); } } // Add to datastructures UpdateAction(ev, &action, FALSE); CHECK_EXCEPTION(ev); CORBA_ClearType(_tc_GAt_Action, &action); // Next action instance inst = action_class->FindNextInstance(); } // Success return; // Failure exception: CORBA_ClearType(_tc_GAt_Action, &action); return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::UnpackGeodeMenu() * * DESCRIPTION: * * * * PARAMETERS: * * CORBA_Environment* ev -- Environment for error reporting * * RETURNS: * * void * */ void _i_GAC_Auth::UnpackGeodeMenu(CORBA_Environment* ev, FVt_IDLNode* node, const ODC_Instance *inst) { GAt_URLMenuItemSeq menu_seq; ODC_Member *mem; ODC_SeqValue *seq_val; ODC_StringValue *str_val; tUInt4 num_items; tUInt4 half_items; GAC_NodeMenuTrigger_var menu_trigger; ARC_Menu_var menu; tUInt4 i; GOODMEM(ev); // Set up CORBA_InitType(_tc_GAt_URLMenuItemSeq, &menu_seq); // Menu and URL items mem = inst->fMembers->FindMember("menu"); if (mem != NULL) { seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); num_items = seq_val->fItems->fMembers._length; half_items = num_items / 2; if (num_items > 0) { if ( CORBA_SeqExpand(&menu_seq, half_items, sizeof(*menu_seq._buffer)) != kNoError ) MEMORY_EXCEPTION(ev); for ( i = 0; i < half_items; i++ ) { tUInt4 title_index = i*2 + 1; tUInt4 url_index = i*2 + 2; // Extract title str_val = ODC_StringValue::narrow(seq_val->fItems->NthMember(title_index)->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); menu_seq._buffer[i].title = CORBA_string_dup(str_val->fStr); if ( menu_seq._buffer[i].title == NULL ) MEMORY_EXCEPTION(ev); // Extract URL str_val = ODC_StringValue::narrow(seq_val->fItems->NthMember(url_index)->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); menu_seq._buffer[i].url = CORBA_string_dup(str_val->fStr); if ( menu_seq._buffer[i].url == NULL ) MEMORY_EXCEPTION(ev); menu_seq._length++; } // Create a menu for the sequence menu_trigger = new GAC_NodeMenuTrigger(ev); if ( CORBA_is_nil(menu_trigger) ) MEMORY_EXCEPTION(ev); CHECK_EXCEPTION(ev); menu_trigger->Set_fGA(ev, fThis); CHECK_EXCEPTION(ev); menu_trigger->Set_fURLItems(ev, &menu_seq); CHECK_EXCEPTION(ev); menu_trigger->Set_fNodeID(ev, node->id); CHECK_EXCEPTION(ev); node->menu = menu_trigger->CreateMenu(ev); CHECK_EXCEPTION(ev); CORBA_ClearType(_tc_GAt_URLMenuItemSeq, &menu_seq); } } return; exception: CORBA_ClearType(_tc_GAt_URLMenuItemSeq, &menu_seq); } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::UnpackSteps() * * DESCRIPTION: * * Unpack all guideline steps from the given parse tree. * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_ParseTree * -- Parse tree. * * RETURNS: * * void. * * EXCEPTIONS: * * None. * * NOTES: * * See PackSteps() for details of mapping from high-level (Geode) steps * to GLIF steps. * */ void _i_GAC_Auth::UnpackSteps(CORBA_Environment *ev, ODC_ParseTree *parse) { GAt_Step step; FVt_IDLNode node; ODC_Class *bstep_class = NULL; ODC_Class *astep_class = NULL; ODC_Class *sstep_class = NULL; ODC_Class *cstep_class = NULL; ODC_Instance *inst = NULL; ODC_Instance *binst = NULL; ODC_Instance *sinst = NULL; ODC_Instance *ainst = NULL; ODC_Instance *cinst = NULL; ODC_Member *mem; ODC_SeqValue *seq_val; ODC_IntValue *int_val; ODC_StringValue *str_val; ODC_EnumValue *enum_val; ODC_ObjRefValue *objref_val; char tmp_str[64]; tUInt4 i; GAt_NodeType step_type; ODC_FloatValue *float_val; tUInt4 value; GAt_URLMenuItemSeq menu_seq; GOODMEM(ev); GOODMEM(parse); // Set up CORBA_InitType(_tc_GAt_Step, &step); CORBA_InitType(_tc_FVt_IDLNode, &node); CORBA_InitType(_tc_GAt_URLMenuItemSeq, &menu_seq); // Look up classes bstep_class = parse->FindClassByName("Branch_Step"); astep_class = parse->FindClassByName("Action_Step"); sstep_class = parse->FindClassByName("Synchronization_Step"); cstep_class = parse->FindClassByName("Conditional_Step"); if (bstep_class != NULL) binst = bstep_class->FindFirstInstance(); if (cstep_class != NULL) cinst = cstep_class->FindFirstInstance(); if (astep_class != NULL) ainst = astep_class->FindFirstInstance(); if (sstep_class != NULL) sinst = sstep_class->FindFirstInstance(); if (binst != NULL) { inst = binst; binst = bstep_class->FindNextInstance(); step_type = GAk_GlifBranch; } else if (cinst != NULL) { inst = cinst; cinst = cstep_class->FindNextInstance(); step_type = GAk_GlifCond; } else if (ainst != NULL) { inst = ainst; ainst = astep_class->FindNextInstance(); step_type = GAk_GlifAction; } // Read each entry while (inst != NULL) { tUInt4 minor_id; tUInt4 num_items; tUInt4 half_items; tUInt4 j; // Process only leading geode branch steps, with minor_id == 0 mem = inst->fMembers->FindMember("geode"); if ((mem != NULL) && (sscanf(inst->fId->fInstID.ident->fStr, "GS%d_%d", &step.id, &minor_id) == 2) && (minor_id == 0)) { tBoolean actions_present; tUInt4 num_actions; // Set up step.node_type = GAk_Geode; node.id = step.id; actions_present = FALSE; num_actions = 0; // Check whether actions are present in this composite node if (astep_class != NULL) { sprintf(tmp_str, "GS%d_%d", step.id, 1); if (astep_class->FindInstance(tmp_str) != NULL) actions_present = TRUE; } // Read through all members in main branch step instance, // setting main step fields, and processing actions for (i = 0; i < inst->fMembers->fMembers._length; i++) { // Get this member mem = inst->fMembers->fMembers._buffer[i]; GOODMEM(mem); // Name member if (!strcmp(mem->fName->fStr, "name")) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &node.long_name, &str_val->fStr); CHECK_EXCEPTION(ev); CORBA_CopyType(ev, _tc_String, &node.short_name, &str_val->fStr); CHECK_EXCEPTION(ev); } // Short name member; Not GLIF else if (!strcmp(mem->fName->fStr, "short_name")) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &node.short_name, &str_val->fStr); CHECK_EXCEPTION(ev); } // Didactics member else if (!strcmp(mem->fName->fStr, "didactics")) { seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.didactics = UnpackDidactics(ev, seq_val); CHECK_EXCEPTION(ev); } // Eligibility member : Not GLIF else if (!strcmp(mem->fName->fStr, "eligibility")) { seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.eligibility = UnpackStringFromSequence(ev, seq_val); CHECK_EXCEPTION(ev); } // Action cardinality if (actions_present && !strcmp(mem->fName->fStr, "selection_method")) { enum_val = ODC_EnumValue::narrow(mem->fValue); if (enum_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.action_card = GA_StringToGSSelection(enum_val->fIdent->fStr); } // Action K : Not GLIF if (actions_present && !strcmp(mem->fName->fStr, "selection_k")) { int_val = ODC_IntValue::narrow(mem->fValue); if (int_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (int_val->fType != ODk_IVT_UNSIGNED) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.action_k = int_val->fValue.uint; } // Outgoing branches if (!strcmp(mem->fName->fStr, "branches")) { ODC_Instance *target_inst; tUInt4 j; // Get branch sequence seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Process actions, if any num_actions = seq_val->fItems->fMembers._length; for (j = 0; actions_present && (j < num_actions); j++) { // Find branch target mem = seq_val->fItems->fMembers._buffer[j]; objref_val = ODC_ObjRefValue::narrow(mem->fValue); if (objref_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (objref_val->fId->fIDType != ODk_IID_IDENTIFIER) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); target_inst = astep_class->FindInstance(objref_val->fId->fInstID.ident->fStr); if (target_inst == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Append action to step's list mem = target_inst->fMembers->FindMember("action"); if (mem == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); objref_val = ODC_ObjRefValue::narrow(mem->fValue); if (objref_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (objref_val->fId->fIDType != ODk_IID_UNSIGNED_INT) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (CORBA_SeqAppend(&step.actions, &objref_val->fId->fInstID.uns_int->fValue.uint, sizeof(tUInt4)) != kNoError) MEMORY_EXCEPTION(ev); } } } // Find second branch step for conditionals/transitions, if // there were actions if (actions_present && (num_actions > 0)) { sprintf(tmp_str, "GS%d_%d", step.id, num_actions + 2); inst = bstep_class->FindInstance(tmp_str); } // Process branch node for branch information, if any if (inst != NULL) { // Process branch node members for (i = 0; i < inst->fMembers->fMembers._length; i++) { // Get this member mem = inst->fMembers->fMembers._buffer[i]; GOODMEM(mem); // Branches cardinality if (!strcmp(mem->fName->fStr, "selection_method")) { enum_val = ODC_EnumValue::narrow(mem->fValue); if (enum_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.branches_card = GA_StringToGSSelection(enum_val->fIdent->fStr); } // Branches K : Not GLIF if (!strcmp(mem->fName->fStr, "selection_k")) { int_val = ODC_IntValue::narrow(mem->fValue); if (int_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (int_val->fType != ODk_IVT_UNSIGNED) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.branches_k = int_val->fValue.uint; } // Branch order constraint if (!strcmp(mem->fName->fStr, "order_constraint")) { enum_val = ODC_EnumValue::narrow(mem->fValue); if (enum_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.branches_order = GA_StringToGSOrdering(enum_val->fIdent->fStr); } } } } else { // Process glif step // Note : right now, assumes steps are unsigned integers mem = inst->fMembers->FindMember("geode"); if (mem == NULL) { if (inst->fId->fIDType == ODk_IID_UNSIGNED_INT) { int_val = ODC_IntValue::narrow(inst->fId->fInstID.uns_int); value = int_val->fValue.uint; } else if (inst->fId->fIDType == ODk_IID_DEC_FLOAT) { float_val = ODC_FloatValue::narrow(inst->fId->fInstID.dec_float); value = (tUInt4) float_val->fValue; } else BARF; step.id = value; // Set up step.node_type = step_type; node.id = step.id; // Name member mem = inst->fMembers->FindMember("name"); if (!strcmp(mem->fName->fStr, "name")) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &node.long_name, &str_val->fStr); CHECK_EXCEPTION(ev); CORBA_CopyType(ev, _tc_String, &node.short_name, &str_val->fStr); CHECK_EXCEPTION(ev); } // Didactics member mem = inst->fMembers->FindMember("didactics"); if (!strcmp(mem->fName->fStr, "didactics")) { seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.didactics = UnpackDidactics(ev, seq_val); CHECK_EXCEPTION(ev); } switch (step_type) { case GAk_GlifBranch: { tUInt4 num_items; tUInt4 branch_id; mem = inst->fMembers->FindMember("branches"); // Add sequence of branches in glif step seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); num_items = seq_val->fItems->fMembers._length; step.actions._length = num_items; step.actions._buffer = NULL; step.actions._buffer = (tUInt4*) CU_Malloc(num_items * sizeof(tUInt4)); if (step.actions._buffer == NULL) MEMORY_EXCEPTION(ev); for (i = 1; i <= num_items; i++) { objref_val = ODC_ObjRefValue::narrow(seq_val->fItems->NthMember(i)->fValue); if (objref_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); branch_id = objref_val->fId->fInstID.uns_int->fValue.uint; step.actions._buffer[i-1] = branch_id; } // Selection_method mem = inst->fMembers->FindMember("selection_method"); if (!strcmp(mem->fName->fStr, "selection_method")) { enum_val = ODC_EnumValue::narrow(mem->fValue); if (enum_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.branches_card = GA_StringToGSSelection(enum_val->fIdent->fStr); } // Branch order constraint mem = inst->fMembers->FindMember("order_constraint"); if (!strcmp(mem->fName->fStr, "order_constraint")) { enum_val = ODC_EnumValue::narrow(mem->fValue); if (enum_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.branches_order = GA_StringToGSOrdering(enum_val->fIdent->fStr); } break; } case GAk_GlifCond: { // first id in actions is cond id, 2nd is destination, and 3rd is otherwise step.actions._buffer = NULL; step.actions._length = 3; step.actions._buffer = (tUInt4*) CU_Malloc(3 * sizeof(tUInt4)); if (step.actions._buffer == NULL) MEMORY_EXCEPTION(ev); // conditional id tUInt4 tmp_id; ODC_Instance *condinst = NULL; mem = inst->fMembers->FindMember("condition"); condinst = ODC_Instance::narrow(mem->fValue); if (condinst == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); tmp_id = condinst->fId->fInstID.uns_int->fValue.uint; step.actions._buffer[0] = tmp_id; // spec mem = condinst->fMembers->FindMember("spec"); if (mem == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &step.spec, &str_val->fStr); CHECK_EXCEPTION(ev); // node name CORBA_CopyType(ev, _tc_String, &node.long_name, &str_val->fStr); CHECK_EXCEPTION(ev); // destination id mem = inst->fMembers->FindMember("destination"); if (mem == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); objref_val = ODC_ObjRefValue::narrow(mem->fValue); if (objref_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); tmp_id = objref_val->fId->fInstID.uns_int->fValue.uint; step.actions._buffer[1] = tmp_id; // otherwise id mem = inst->fMembers->FindMember("otherwise"); if (mem == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); objref_val = ODC_ObjRefValue::narrow(mem->fValue); if (objref_val->fType != NULL) tmp_id = objref_val->fId->fInstID.uns_int->fValue.uint; else tmp_id = 0; step.actions._buffer[2] = tmp_id; break; } case GAk_GlifAction: { tUInt4 tmp_id; ODC_IntValue *int_val; ODC_FloatValue *float_val; tUInt4 value; ODC_Instance *tmp_inst = NULL; // first id in actions is action spec id step.actions._buffer = NULL; step.actions._length = 2; step.actions._buffer = (tUInt4*) CU_Malloc(2 * sizeof(tUInt4)); if (step.actions._buffer == NULL) MEMORY_EXCEPTION(ev); // action spec id mem = inst->fMembers->FindMember("action"); if (mem == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); objref_val = ODC_ObjRefValue::narrow(mem->fValue); // Action spec is a reference if (objref_val != NULL) { if (objref_val->fId->fIDType == ODk_IID_UNSIGNED_INT) { int_val = ODC_IntValue::narrow(objref_val->fId->fInstID.uns_int); value = int_val->fValue.uint; } else if (objref_val->fId->fIDType == ODk_IID_DEC_FLOAT) { float_val = ODC_FloatValue::narrow(objref_val->fId->fInstID.dec_float); value = (tUInt4) float_val->fValue; } } else { // embedded class tmp_inst = ODC_Instance::narrow(mem->fValue); if (tmp_inst->fId->fIDType == ODk_IID_UNSIGNED_INT) { int_val = ODC_IntValue::narrow(tmp_inst->fId->fInstID.uns_int); value = int_val->fValue.uint; } else if (tmp_inst->fId->fIDType == ODk_IID_DEC_FLOAT) { float_val = ODC_FloatValue::narrow(tmp_inst->fId->fInstID.dec_float); value = (tUInt4) float_val->fValue; } } if (int_val == NULL && float_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.actions._buffer[0] = value; // next step id mem = inst->fMembers->FindMember("next_step"); if (mem == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); objref_val = ODC_ObjRefValue::narrow(mem->fValue); if (objref_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (objref_val->fType != NULL) tmp_id = objref_val->fId->fInstID.uns_int->fValue.uint; else tmp_id = 0; step.actions._buffer[1] = tmp_id; break; } case GAk_GlifSync: { tUInt4 tmp_id; // first id in actions is next_step step.actions._buffer = NULL; step.actions._length = 1; step.actions._buffer = (tUInt4*) CU_Malloc(1 * sizeof(tUInt4)); if (step.actions._buffer == NULL) MEMORY_EXCEPTION(ev); // next step id mem = inst->fMembers->FindMember("next_step"); if (mem == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); objref_val = ODC_ObjRefValue::narrow(mem->fValue); if (objref_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); tmp_id = objref_val->fId->fInstID.uns_int->fValue.uint; step.actions._buffer[0] = tmp_id; // continuation mem = inst->fMembers->FindMember("continuation"); if (!strcmp(mem->fName->fStr, "continuation")) { enum_val = ODC_EnumValue::narrow(mem->fValue); if (enum_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); step.cont = GA_StringToGSContinue(enum_val->fIdent->fStr); } break; } } } } // Add step to data structures if (step.node_type == GAk_Geode) node.type = FVk_RoundRect; else if (step.node_type == GAk_GlifBranch) node.type = FVk_Diamond; else if (step.node_type == GAk_GlifCond) node.type = FVk_Hex; else if (step.node_type == GAk_GlifSync) node.type = FVk_Oval; else if (step.node_type == GAk_GlifAction) node.type = FVk_Rect; // Read extra menu items UnpackGeodeMenu(ev, &node, inst); CHECK_EXCEPTION(ev); // Create a step if not geode node with minor id != 0 if (step.node_type != GAk_Geode) CreateStep(ev, &node, &step); else if (minor_id == 0) CreateStep(ev, &node, &step); CHECK_EXCEPTION(ev); // Clean up for next composite step CORBA_ClearType(_tc_GAt_Step, &step); CORBA_ClearType(_tc_FVt_IDLNode, &node); // Next step instance if (binst != NULL) { inst = binst; binst = bstep_class->FindNextInstance(); step_type = GAk_GlifBranch; } else if (cinst != NULL) { inst = cinst; cinst = cstep_class->FindNextInstance(); step_type = GAk_GlifCond; } else if (ainst != NULL) { inst = ainst; ainst = astep_class->FindNextInstance(); step_type = GAk_GlifAction; } else if (sinst != NULL) { inst = sinst; sinst = sstep_class->FindNextInstance(); step_type = GAk_GlifSync; } else inst = NULL; } // Success return; // Failure exception: CORBA_ClearType(_tc_GAt_Step, &step); CORBA_ClearType(_tc_FVt_IDLNode, &node); return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::UnpackTransitions() * * DESCRIPTION: * * Unpack all guideline transitions from the given parse tree. * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_ParseTree * -- Parse tree. * * RETURNS: * * void. * * EXCEPTIONS: * * None. * * NOTES: * * See PackSteps() for details of mapping from high-level (Geode) steps * to GLIF steps. * */ void _i_GAC_Auth::UnpackTransitions(CORBA_Environment *ev, ODC_ParseTree *parse) { FVt_Transition trans; ODC_Class *bstep_class = NULL; ODC_Class *astep_class = NULL; ODC_Class *cstep_class = NULL; ODC_Instance *inst = NULL; ODC_Member *mem; ODC_StringValue *str_val; ODC_ObjRefValue *obj_val; ODC_IntValue *int_val; ODC_SeqValue *seq_val; char tmp_str[64]; CUt_UInt4Seq steps; GAt_Step* step = NULL; GAt_Step* tmp_step = NULL; tUInt4 i; tUInt4 j; GOODMEM(ev); GOODMEM(parse); // Set up CORBA_InitType(_tc_FVt_Transition, &trans); // Look up class; if none, then no conditionals in file bstep_class = parse->FindClassByName("Branch_Step"); // Find first entry if (bstep_class != NULL) inst = bstep_class->FindFirstInstance(); cstep_class = parse->FindClassByName("Conditional_Step"); astep_class = parse->FindClassByName("Action_Step"); // Read each entry while (inst != NULL) { // Process only geode-level nodes mem = inst->fMembers->FindMember("geode"); if (mem != NULL) { tUInt4 minor_id; tBoolean skip_node; // Get ID if (inst->fId->fIDType != ODk_IID_IDENTIFIER) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (sscanf(inst->fId->fInstID.ident->fStr, "GS%d_%d", &trans.source, &minor_id) != 2) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Eliminate leading branch nodes that have actions skip_node = FALSE; if ((astep_class != NULL) && (minor_id == 0)) { sprintf(tmp_str, "GS%d_%d", trans.source, 1); if (astep_class->FindInstance(tmp_str) != NULL) skip_node = TRUE; } if (!skip_node) { // Find branches in node, if any mem = inst->fMembers->FindMember("branches"); if (mem != NULL) { tUInt4 i; // Find sequence of branches seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Process each conditional node in order from the branch node // (this preserves node ordering) for (i = 1; i <= seq_val->fItems->fMembers._length; i++) { // Find conditional node obj_val = ODC_ObjRefValue::narrow(seq_val->fItems->NthMember(i)->fValue); if (obj_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (obj_val->fId->fIDType != ODk_IID_IDENTIFIER) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); str_val = ODC_StringValue::narrow(obj_val->fId->fInstID.ident); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (!str_val->fStr) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); inst = cstep_class->FindInstance(str_val->fStr); if (inst == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Set transition dest/source from conditional node mem = inst->fMembers->FindMember("destination"); if (mem == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); obj_val = ODC_ObjRefValue::narrow(mem->fValue); if (obj_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (obj_val->fId->fIDType != ODk_IID_IDENTIFIER) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); if (sscanf(obj_val->fId->fInstID.ident->fStr, "GS%d_%d", &trans.dest, &minor_id) != 2) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Set transition names from condition member mem = inst->fMembers->FindMember("condition"); if (mem != NULL) { ODC_Instance *cond_inst; // Find conditional instance cond_inst = ODC_Instance::narrow(mem->fValue); if (cond_inst == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Get name mem = cond_inst->fMembers->FindMember("spec"); if (mem != NULL) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &trans.long_name, &str_val->fStr); CHECK_EXCEPTION(ev); } // Get short name : Not GLIF mem = cond_inst->fMembers->FindMember("short_spec"); if (mem != NULL) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &trans.short_name, &str_val->fStr); CHECK_EXCEPTION(ev); } // Use spec for short_name if short_spec doesn't exist else if ( trans.long_name != NULL ) { CORBA_CopyType(ev, _tc_String, &trans.short_name, &trans.long_name); CHECK_EXCEPTION(ev); } } // Add transition InsertTransition(ev, &trans, FALSE); CHECK_EXCEPTION(ev); } } } } // Next branch step instance CORBA_ClearType(_tc_FVt_Transition, &trans); inst = bstep_class->FindNextInstance(); } // Process GLIF nodes steps = AllConstructIDs(ev, GAk_CTStep, FALSE); for (i = 0; i < steps._length; i++) { // Process only Glif-level nodes step = FindStepPtrByID(ev, steps._buffer[i]); CHECK_EXCEPTION(ev); GOODMEM(step); CORBA_ClearType(_tc_FVt_Transition, &trans); if (step->node_type != GAk_Geode) { switch (step->node_type) { case GAk_GlifBranch: { trans.source = steps._buffer[i]; for (j = 0; j < step->actions._length; j++) { trans.dest = step->actions._buffer[j]; InsertTransition(ev, &trans, FALSE); CHECK_EXCEPTION(ev); } break; } case GAk_GlifCond: { trans.source = steps._buffer[i]; trans.dest = step->actions._buffer[1]; trans.long_name = strdup("Yes"); CORBA_CopyType(ev, _tc_String, &trans.short_name, &trans.long_name); CHECK_EXCEPTION(ev); InsertTransition(ev, &trans, FALSE); CHECK_EXCEPTION(ev); trans.dest = step->actions._buffer[2]; if (trans.dest != 0) { trans.long_name = strdup("Otherwise"); CORBA_CopyType(ev, _tc_String, &trans.short_name, &trans.long_name); CHECK_EXCEPTION(ev); InsertTransition(ev, &trans, FALSE); CHECK_EXCEPTION(ev); } break; } case GAk_GlifAction: { trans.source = steps._buffer[i]; trans.dest = step->actions._buffer[1]; if (trans.dest != 0) { InsertTransition(ev, &trans, FALSE); CHECK_EXCEPTION(ev); } break; } case GAk_GlifSync: { trans.source = steps._buffer[i]; trans.dest = step->actions._buffer[0]; InsertTransition(ev, &trans, FALSE); CHECK_EXCEPTION(ev); break; } } } } // Success return; // Failure exception: CORBA_ClearType(_tc_FVt_Transition, &trans); return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::UnpackGuidelineObj() * * DESCRIPTION: * * Unpack main guideline object from given parse tree. * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_ParseTree * -- Parse tree to unpack from. * * RETURNS: * * void. * * EXCEPTIONS: * * None. * */ void _i_GAC_Auth::UnpackGuidelineObj(CORBA_Environment *ev, ODC_ParseTree *parse) { ODC_Class *g_class; ODC_Class *b_class; ODC_Instance *g_inst; ODC_Instance *tmp_inst; ODC_Member *mem; ODC_StringValue *str_val; ODC_SeqValue *seq_val; ODC_ObjRefValue *objref_val; tUInt4 minor_id; tUInt4 num_items; tUInt4 i; GOODMEM(ev); GOODMEM(parse); // Look up guideline class // "Guideline_Object" is old, retained to support old guidelines g_class = parse->FindClassByName("Guideline"); b_class = parse->FindClassByName("Branch_Step"); if (g_class == NULL) { g_class = parse->FindClassByName("Guideline_Object"); if (g_class == NULL) return; } // Find guideline entry g_inst = g_class->FindFirstInstance(); if (g_inst != NULL) { // Name mem = g_inst->fMembers->FindMember("name"); if (mem != NULL) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); fFV->Set_fName(ev, str_val->fStr); CHECK_EXCEPTION(ev); } // Authors mem = g_inst->fMembers->FindMember("authors"); if (mem != NULL) { seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); fGuideInfo.authors._buffer = NULL; num_items = seq_val->fItems->fMembers._length; if (num_items > 0) { fGuideInfo.authors._length = num_items; fGuideInfo.authors._buffer = (char**) CU_Malloc(num_items * sizeof(char*)); if (fGuideInfo.authors._buffer == NULL) MEMORY_EXCEPTION(ev); for (i = 1; i <= num_items; i++) { str_val = ODC_StringValue::narrow(seq_val->fItems->NthMember(i)->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &fGuideInfo.authors._buffer[i-1], &str_val->fStr); CHECK_EXCEPTION(ev); } } } // Eligibility criteria mem = g_inst->fMembers->FindMember("eligibility_criteria"); if (mem != NULL) { UNFINISHED; } // Intention mem = g_inst->fMembers->FindMember("intention"); if (mem != NULL) { str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); CORBA_CopyType(ev, _tc_String, &fGuideInfo.intention, &str_val->fStr); CHECK_EXCEPTION(ev); } // Steps mem = g_inst->fMembers->FindMember("steps"); if (mem != NULL) { seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Ignore for now: Later, use this to drive guideline loading and // to allow multiple guidelines per file! } // First step mem = g_inst->fMembers->FindMember("first_step"); if (mem != NULL) { tUInt4 major_id, minor_id; // Narrow to objref objref_val = ODC_ObjRefValue::narrow(mem->fValue); if (objref_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); tmp_inst = NULL; // Find object instance for ref to check if GEODE step if (objref_val->fId->fIDType == ODk_IID_IDENTIFIER) tmp_inst = b_class->FindInstance(objref_val->fId->fInstID.ident->fStr); else if (objref_val->fId->fIDType == ODk_IID_UNSIGNED_INT) tmp_inst = b_class->FindInstance(objref_val->fId->fInstID.uns_int->fValue.uint); if (tmp_inst != NULL) mem = tmp_inst->fMembers->FindMember("geode"); else mem = NULL; // Get identifier to use if (mem != NULL) { if (sscanf(objref_val->fId->fInstID.ident->fStr, "GS%d_%d", &major_id, &minor_id) != 2) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); } else major_id = objref_val->fId->fInstID.uns_int->fValue.uint; // Set root node in guideline fFV->Set_fRootNodeID(ev, major_id); CHECK_EXCEPTION(ev); } // Didactics mem = g_inst->fMembers->FindMember("didactics"); if (mem != NULL) { seq_val = ODC_SeqValue::narrow(mem->fValue); if (seq_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); UNFINISHED; } } // Redraw whole guideline, including summary; ignore exceptions fFV->RedrawAll(ev); UpdateListWindow(ev, GAk_CTStep); UpdateListWindow(ev, GAk_CTAction); UpdateListWindow(ev, GAk_CTPatientData); CHECK_EXCEPTION(ev); // Check that only one guideline object exists in the file (for now) g_inst = g_class->FindNextInstance(); if (g_inst != NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Success return; // Failure exception: return; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::UnpackStringFromSequence() * * DESCRIPTION: * * Unpack a string from the given sequence, treating each sequence element * as a line of text (\n-seperated). * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_SeqValue * -- The sequence * * RETURNS: * * char * -- The string. * * EXCEPTIONS: * * ex_CORBA_BAD_PARAM -- Parse error encountered during unpack. * */ char *_i_GAC_Auth::UnpackStringFromSequence(CORBA_Environment *ev, ODC_SeqValue *seq) { CUt_Text tmp_text; char *retval = NULL; tUInt4 i; tBoolean first; GOODMEM(ev); GOODMEM(seq); GOODMEM(seq->fItems); CU_TXInit(&tmp_text); // Unpack sequence first = TRUE; for (i = 0; i < seq->fItems->fMembers._length; i++) { ODC_Member *mem; ODC_StringValue *str_val; // Find string mem = seq->fItems->fMembers._buffer[i]; str_val = ODC_StringValue::narrow(mem->fValue); if (str_val == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); // Append to text structure if (!first) { if (CU_TXAppendCString(&tmp_text, "\n") != kNoError) MEMORY_EXCEPTION(ev); } if (CU_TXAppendCString(&tmp_text, str_val->fStr) != kNoError) MEMORY_EXCEPTION(ev); first = FALSE; } // Copy to return value if (CU_TXTextToCString(&tmp_text, &retval) != kNoError) MEMORY_EXCEPTION(ev); // Success CU_TXClear(&tmp_text); return retval; // Failure exception: CU_TXClear(&tmp_text); return NULL; } /**************************************************************************** * FUNCTION: * * _i_GAC_Auth::UnpackDidactics() * * DESCRIPTION: * * Unpack didactics information. * * PARAMETERS: * * CORBA_Environment * -- The environment. * ODC_SeqValue * -- The sequence * * RETURNS: * * GSt_MaterialSeq * * EXCEPTIONS: * * ex_CORBA_BAD_PARAM -- Parse error encountered during unpack. * */ GSt_MaterialSeq _i_GAC_Auth::UnpackDidactics(CORBA_Environment *ev, ODC_SeqValue *seq) { char *str_val; tUInt4 i; tUInt4 num_items; GSt_MaterialSeq ret_val; GSt_Supplemental_Material* material; GOODMEM(ev); GOODMEM(seq); GOODMEM(seq->fItems); // Set up CORBA_InitType(_tc_GSt_MaterialSeq, &ret_val); // Unpack sequence num_items = seq->fItems->fMembers._length; ret_val._length = num_items; if (num_items > 0) ret_val._buffer = (GSt_Supplemental_Material*) CU_Malloc(num_items * sizeof(GSt_Supplemental_Material)); for (i = 0; i < num_items; i++) { ODC_Member *mem; ODC_StringValue *str_val; ODC_Instance *inst; material = NULL; material = new GSt_Supplemental_Material; if (material == NULL) MEMORY_EXCEPTION(ev); mem = seq->fItems->fMembers._buffer[i]; inst = ODC_Instance::narrow(mem->fValue); // get label string mem = inst->fMembers->FindMember("label"); if (!strcmp(mem->fName->fStr, "label")) { str_val = ODC_StringValue::narrow(mem->fValue); CORBA_CopyType(ev, _tc_String, &material->label, &str_val->fStr); CHECK_EXCEPTION(ev); if ( material->label == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); } // get label string mem = inst->fMembers->FindMember("MIME_type"); if (!strcmp(mem->fName->fStr, "MIME_type")) { str_val = ODC_StringValue::narrow(mem->fValue); CORBA_CopyType(ev, _tc_String, &material->MIME_type, &str_val->fStr); CHECK_EXCEPTION(ev); if ( material->MIME_type == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); } // get material string mem = inst->fMembers->FindMember("material"); if (!strcmp(mem->fName->fStr, "material")) { str_val = ODC_StringValue::narrow(mem->fValue); CORBA_CopyType(ev, _tc_String, &material->data._u.material, &str_val->fStr); CHECK_EXCEPTION(ev); if ( material->data._u.material == NULL) USER_EXCEPTION(ev, ex_CORBA_BAD_PARAM); } ret_val._buffer[i] = *material; } // Success return ret_val; // Failure exception: return ret_val; }