public override bool contains(String value, Dictionary<String, String> context) { // make null values match the same as if they were blank if (value == null) value = ""; if (_usesContext) return (matchesAll() || (DecisionEngineFuncs.translateValue(_low, context).CompareTo(value) <= 0 && DecisionEngineFuncs.translateValue(_high, context).CompareTo(value) >= 0)); else return (matchesAll() || (_low.CompareTo(value) <= 0 && _high.CompareTo(value) >= 0)); }
// Parses a string in having lists of ranges into a List of Range objects // @param values String representing sets value ranges // @return a parsed list of string Range objects public static List <Range> splitValues(String values) { List <Range> convertedRanges = new List <Range>(); if (values != null) { // if the value of the string is "*", then consider it as matching anything if (values == "*") { convertedRanges.Add(_MATCH_ALL_ENDPOINT); } else { // split the string; the "9999" makes sure to not discard empty strings String[] ranges = values.Split(",".ToCharArray(), 9999); foreach (String range in ranges) { // Not sure if this is the best way to handle this, but I ran into a problem when I converted the CS data. One of the tables had // a value of "N0(mol-)". This fails since it considers it a range and we require our ranges to have the same size on both sides. // The only thing I can think of is for cases like this, assume it is not a range and use the whole string as a non-range value. // The problem is that if something is entered incorrectly and was supposed to be a range, we will not process it correctly. We // may need to revisit this issue later. String[] parts = range.Split("-".ToCharArray()); if (parts.Length == 2) { String low = parts[0].Trim(); String high = parts[1].Trim(); // check if both sides of the range are numeric values; if so the length does not have to match bool isNumericRange = StagingRange.isNumeric(low) && StagingRange.isNumeric(high); // if same length, a numeric range, or one of the parts is a context variable, use the low and high as range. Otherwise consier // a single value (i.e. low = high) if (low.Length == high.Length || isNumericRange || DecisionEngineFuncs.isReferenceVariable(low) || DecisionEngineFuncs.isReferenceVariable(high)) { convertedRanges.Add(new StagingRange(low, high)); } else { convertedRanges.Add(new StagingRange(range.Trim(), range.Trim())); } } else { convertedRanges.Add(new StagingRange(range.Trim(), range.Trim())); } } } } return(convertedRanges); }
// For a given table, return the index of the row that matches supplied context. // @param tableId table identifier // @param context context of input key/values to use to match // @return the index of the matching table row or null if no match was found public int findMatchingTableRow(String tableId, Dictionary <String, String> context) { int rowIndex = -1; // add the context keys addContextKeys(context); ITable table = getTable(tableId); if (table != null) { rowIndex = DecisionEngineFuncs.findMatchingTableRow(table, context); } return(rowIndex); }
// Check the validity of a single field of a schema based on the supplied context. The value of this key should be in the context as well // as any other properties needed to evaluation validity. If the schema or field do no exist, false will be returned. // @param schemaId schema identifier // @param key input key // @param context Map of keys/values to validate against // @return a boolean indicating whether the code exists for the the passed schema field public bool isContextValid(String schemaId, String key, Dictionary <String, String> context) { // first get the algorithm StagingSchema schema = getSchema(schemaId); if (schema == null) { return(false); } // get the table id from the schema IInput input = null; if (!schema.getInputMap().TryGetValue(key, out input)) { input = null; } if (input == null) { return(false); } // missing context will always return false if (context == null || context.Count == 0) { return(false); } // all context input needs to be trimmed Dictionary <String, String> testContext = new Dictionary <String, String>(20, StringComparer.Ordinal); foreach (KeyValuePair <String, String> entry in context) { testContext[entry.Key] = (entry.Value != null ? entry.Value.Trim() : ""); } // if the input specifies a table for validation, test against it if (input.getTable() != null) { ITable table = getTable(input.getTable()); return(table != null && (DecisionEngineFuncs.matchTable(table, testContext) != null)); } return(true); }
// Look up a schema based on site, histology and an optional discriminator. // @param lookup schema lookup input // @return a list of StagingSchemaInfo objects private List <StagingSchema> getSchemas(SchemaLookup lookup) { List <StagingSchema> matchedSchemas = new List <StagingSchema>(5); String site = lookup.getInput(StagingData.PRIMARY_SITE_KEY); String histology = lookup.getInput(StagingData.HISTOLOGY_KEY); bool hasDiscriminator = lookup.hasDiscriminator(); // site or histology must be supplied and they must be valid; I am assuming that all algorithms must have tables that validate // both site and histology if ((site != null && !isValidSite(site)) || (histology != null && !isValidHistology(histology))) { return(matchedSchemas); } // searching on a discriminator is only supported if also searching on site and histology; if ssf25 supplied without either // of those fields, return no results if (hasDiscriminator && (site == null || (site.Length == 0) || histology == null || (histology.Length == 0))) { return(matchedSchemas); } // site or histology must be supplied if (site != null || histology != null) { HashSet <String> lstSchemaIds = getSchemaIds(); // loop over selection table and match using only the supplied keys foreach (String schemaId in lstSchemaIds) { StagingSchema schema = (StagingSchema)(getDefinition(schemaId)); if (schema.getSchemaSelectionTable() != null) { StagingTable table = (StagingTable)(getTable(schema.getSchemaSelectionTable())); if (table != null && DecisionEngineFuncs.matchTable(table, lookup.getInputs(), lookup.getKeys()) != null) { matchedSchemas.Add(schema); } } } } return(matchedSchemas); }
/** * Initialize a table. * @param table a BasicTable */ public void initTable(BasicTable table) { HashSet <String> extraInputs = new HashSet <String>(); if (table.getRawRows() != null) { foreach (List <String> row in table.getRawRows()) { BasicTableRow tableRowEntity = new BasicTableRow(); // make sure the number of cells in the row matches the number of columns defined if (table.getColumnDefinitions().Count != row.Count) { throw new InvalidOperationException("Table '" + table.getId() + "' has a row with " + row.Count + " values but should have " + table.getColumnDefinitions().Count + ": " + row); } // loop over the column definitions in order since the data needs to retrieved by array position for (int i = 0; i < table.getColumnDefinitions().Count; i++) { IColumnDefinition col = table.getColumnDefinitions()[i]; String cellValue = row[i]; switch (col.getType()) { case ColumnType.INPUT: // if there are no ranges in the list, that means the cell was "blank" and is not needed in the table row List <BasicRange> ranges = splitValues(cellValue); if (!(ranges.Count == 0)) { tableRowEntity.addInput(col.getKey(), ranges); // if there are key references used (values that reference other inputs) like {{key}}, then add them to the extra inputs list foreach (BasicRange range in ranges) { if (DecisionEngineFuncs.isReferenceVariable(range.getLow())) { extraInputs.Add(DecisionEngineFuncs.trimBraces(range.getLow())); } if (DecisionEngineFuncs.isReferenceVariable(range.getHigh())) { extraInputs.Add(DecisionEngineFuncs.trimBraces(range.getHigh())); } } } break; case ColumnType.ENDPOINT: BasicEndpoint endpoint = parseEndpoint(cellValue); endpoint.setResultKey(col.getKey()); tableRowEntity.addEndpoint(endpoint); // if there are key references used (values that reference other inputs) like {{key}}, then add them to the extra inputs list if (EndpointType.VALUE == endpoint.getType() && DecisionEngineFuncs.isReferenceVariable(endpoint.getValue())) { extraInputs.Add(DecisionEngineFuncs.trimBraces(endpoint.getValue())); } break; case ColumnType.DESCRIPTION: // do nothing break; default: throw new InvalidOperationException("Table '" + table.getId() + " has an unknown column type: '" + col.getType() + "'"); } } table.getTableRows().Add(tableRowEntity); } } // add extra inputs, if any; do not include context variables since they are not user input foreach (String s in TNMStagingCSharp.Src.Staging.Staging.CONTEXT_KEYS) { extraInputs.Remove(s); } table.GenerateInputColumnDefinitions(); table.setExtraInput(extraInputs.Count == 0 ? null : extraInputs); }