Conversation
|
@balhoff - would be great if you could take a look soon. Thanks! |
|
Thanks! I'll try to get it done. Awesome to get a contribution! |
| def replaced(text: String, vars: Option[List[String]], bindings: Option[Map[String, SingleValue]], quote: Boolean): Option[String] = { | ||
| def replaced(text: Option[String], vars: Option[List[String]], multi_clause: Option[MultiClausePrintf], bindings: Option[Map[String, SingleValue]], quote: Boolean): Option[String] = { | ||
| if(text.isDefined) { | ||
| return replace_text(text, vars, bindings, quote) |
There was a problem hiding this comment.
There was a problem hiding this comment.
All returns removed from code.
| None | ||
| } | ||
|
|
||
| private def replace_text(text: Option[String], vars: Option[List[String]], bindings: Option[Map[String, SingleValue]], quote: Boolean) = { |
There was a problem hiding this comment.
It seems like text should be String, not Option[String] (handle missing text outside of this method). Also, I like to add type signatures to method definitions.
There was a problem hiding this comment.
Based on the new schema text or multi_clause can be used to define printf formats.
oneOf:
- required: [ text, vars ]
- required: [ multi_clause ]Text is not a mandatory field now, we can use multi_clause instead of text.
| if(text.isDefined) { | ||
| return replace_text(text, vars, bindings, quote) | ||
| } else if (multi_clause.isDefined) { | ||
| val replaced_texts = for { | ||
| multi_clauses <- multi_clause.toSeq | ||
| printf_clauses <- multi_clauses.clauses.toSeq | ||
| printf_clause <- printf_clauses | ||
| printf_clause_text <- replaced(Some(printf_clause.text), printf_clause.vars, None, bindings, quote) | ||
| sub_clauses = printf_clause.sub_clauses.getOrElse(List.empty[MultiClausePrintf]) | ||
| sub_clauses_texts = sub_clauses.flatMap(mc => replaced(None, None, Some(mc), bindings, quote)) | ||
| clause_text = (printf_clause_text :: sub_clauses_texts).mkString(multi_clauses.sep.getOrElse(" ")) | ||
| } yield clause_text | ||
| val result = replaced_texts.filter(_.nonEmpty).mkString(multi_clause.get.sep.getOrElse(" ")) | ||
| val trimmed = result.trim | ||
| if (trimmed.isEmpty) return None else return Some(trimmed) | ||
| } | ||
| None | ||
| } |
There was a problem hiding this comment.
Maybe the optionality of text should be handled outside of this method, and you could break this into two separate methods? I would not use isDefined (they should remove it from the Option type); I prefer an expression-oriented style.
There was a problem hiding this comment.
replaceMultiClause method extracted. isDefined bassed logic replaced with flatMap and list operations.
| annotations: Option[List[Annotations]], | ||
| axiom_type: AxiomType, | ||
| text: String, | ||
| text: Option[String], |
There was a problem hiding this comment.
Was this changed in the spec? Just want to make sure!
There was a problem hiding this comment.
Now, the printf format can be given through text or a multi_clause. Updated spec is here: https://github.com/INCATools/dead_simple_owl_design_patterns/blob/e5d69a6f3e17ec464e6942ccf0f05991694cd671/spec/DOSDP_schema_full.yaml#L135
| val internalVarBindings = (for { | ||
| internalVars <- dosdp.internal_vars.toSeq | ||
| internalVar <- internalVars | ||
| function <- internalVar.apply.toSeq | ||
| value = function.apply(Some(dataListBindings.getOrElse(internalVar.input, listVarBindings.getOrElse(internalVar.input, MultiValue(Set.empty[String]))))) | ||
| if value.isDefined | ||
| } yield internalVar.var_name -> SingleValue(value.get) ).toMap |
There was a problem hiding this comment.
Instead, avoid isDefined and get (I didn't test this):
val internalVarBindings = (for {
internalVars <- dosdp.internal_vars.toSeq
internalVar <- internalVars
function <- internalVar.apply.toSeq
value <- function.apply(Some(dataListBindings.getOrElse(internalVar.input, listVarBindings.getOrElse(internalVar.input, MultiValue(Set.empty[String])))))
} yield internalVar.var_name -> SingleValue(value) ).toMapThere was a problem hiding this comment.
Recommended logic worked perfectly, changed accordingly.
|
|
||
| final case class JoinFunction(join: Join) extends Function { | ||
| override def apply(input_var:Option[Binding]): Option[String] = { | ||
| val joined_values = input_var.getOrElse(MultiValue(Set.empty[String])).asInstanceOf[MultiValue].value.mkString(join.sep) |
There was a problem hiding this comment.
Can this be written without casting (asInstanceOf)?
There was a problem hiding this comment.
asInstanceOf based logic re-implemented with collect { case a: MultiValue => a }
|
|
||
| final case class RegexFunction(regex: RegexSub) extends Function { | ||
| override def apply(input_var:Option[Binding]): Option[String] = { | ||
| val applied_value = input_var.getOrElse(SingleValue("")).asInstanceOf[SingleValue].value |
There was a problem hiding this comment.
Can this be written without casting (asInstanceOf)?
There was a problem hiding this comment.
asInstanceOf based logic re-implemented with collect { case a: SingleValue => a }
|
Looks great, thank you for also writing tests! |
In relation with the issue: INCATools/dead_simple_owl_design_patterns#71
and relatedly updated ontology schema, implementations to add multi-clause printf and internal_vars.
With this implementation:
Backing usecase is obophenotype/brain_data_standards_ontologies#98