diff --git a/ruta-core/src/main/antlr3/org/apache/uima/ruta/parser/RutaParser.g b/ruta-core/src/main/antlr3/org/apache/uima/ruta/parser/RutaParser.g index 4627ba17d..9bc7782f3 100644 --- a/ruta-core/src/main/antlr3/org/apache/uima/ruta/parser/RutaParser.g +++ b/ruta-core/src/main/antlr3/org/apache/uima/ruta/parser/RutaParser.g @@ -2431,7 +2431,7 @@ options { | match = dottedIdWithIndex2 (comp = LESS | comp = GREATER | comp = GREATEREQUAL | comp = LESSEQUAL |comp = EQUAL | comp = NOTEQUAL) arg = argument {MatchReference mr = expressionFactory.createMatchReference(match, comp, arg); expr = expressionFactory.createAnnotationTypeExpression(mr);} - | (complexStringExpression) => cse = complexStringExpression {expr = cse;} + | (genericComposedExpression) => gce = genericComposedExpression {expr = gce;} | (featureExpression)=> fe = featureExpression {expr = expressionFactory.createGenericFeatureExpression(fe);} | a2 = booleanExpression {expr = a2;} | a3 = numberExpression {expr = a3;} @@ -2720,6 +2720,14 @@ numberVariable returns [Token ref = null] ; +complexNumberExpression returns [INumberExpression expr = null] +@init{List exprs = new ArrayList(); + List ops = new ArrayList();} + : + e = multiplicativeExpression{exprs.add(e);} ((PLUS | MINUS)=> op = (PLUS | MINUS){ops.add(op);} e = multiplicativeExpression{exprs.add(e);} )+ + {expr = expressionFactory.createComposedNumberExpression(exprs,ops);} + ; + additiveExpression returns [INumberExpression expr = null] @init{List exprs = new ArrayList(); List ops = new ArrayList();} @@ -2778,7 +2786,7 @@ List exprs = new ArrayList(); |(e = stringFunction)=> e = stringFunction{expr = e;} ; -complexStringExpression returns [IStringExpression expr = null] +genericComposedExpression returns [IRutaExpression expr = null] options { backtrack = true; } @@ -2786,7 +2794,7 @@ options { : a1 = simpleArgument {list.add(a1);} ((PLUS)=>PLUS an = simpleArgument {list.add(an);})+ - {expr = expressionFactory.createGenericComposedStringExpression(list);} + {expr = expressionFactory.createGenericComposedExpression(list);} ; diff --git a/ruta-core/src/main/java/org/apache/uima/ruta/condition/ConditionFactory.java b/ruta-core/src/main/java/org/apache/uima/ruta/condition/ConditionFactory.java index 3cde11fef..e61c24730 100644 --- a/ruta-core/src/main/java/org/apache/uima/ruta/condition/ConditionFactory.java +++ b/ruta-core/src/main/java/org/apache/uima/ruta/condition/ConditionFactory.java @@ -6,9 +6,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/ruta-core/src/main/java/org/apache/uima/ruta/expression/ExpressionFactory.java b/ruta-core/src/main/java/org/apache/uima/ruta/expression/ExpressionFactory.java index cf752cfc3..e990b7545 100644 --- a/ruta-core/src/main/java/org/apache/uima/ruta/expression/ExpressionFactory.java +++ b/ruta-core/src/main/java/org/apache/uima/ruta/expression/ExpressionFactory.java @@ -181,13 +181,15 @@ public IStringExpression createGenericComposedStringExpression( for (IRutaExpression each : expressions) { if (each instanceof IStringExpression) { stringExpression.add((IStringExpression) each); - } else { - System.out.println(); } } return new ComposedStringExpression(stringExpression); } + public IRutaExpression createGenericComposedExpression(List list) { + return new GenericComposedExpression(list); + } + public AbstractStringExpression createReferenceStringExpression(Token var) { return new StringVariableExpression(var.getText()); } diff --git a/ruta-core/src/main/java/org/apache/uima/ruta/expression/GenericComposedExpression.java b/ruta-core/src/main/java/org/apache/uima/ruta/expression/GenericComposedExpression.java new file mode 100644 index 000000000..d9c007a2e --- /dev/null +++ b/ruta-core/src/main/java/org/apache/uima/ruta/expression/GenericComposedExpression.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.uima.ruta.expression; + +import java.util.List; + +import org.apache.uima.ruta.RutaStream; +import org.apache.uima.ruta.expression.number.INumberExpression; +import org.apache.uima.ruta.expression.string.IStringExpression; +import org.apache.uima.ruta.rule.MatchContext; + +public class GenericComposedExpression extends RutaExpression implements INumberExpression { + + private final List expressions; + + public GenericComposedExpression(List expressions) { + super(); + this.expressions = expressions; + } + + @Override + public String getStringValue(MatchContext context, RutaStream stream) { + if (expressions == null) { + return null; + } + if (expressions.size() == 1) { + IRutaExpression first = expressions.get(0); + if (first instanceof IStringExpression) { + return ((IStringExpression) first).getStringValue(context, stream); + } + return null; + } + StringBuilder result = new StringBuilder(); + for (IRutaExpression each : expressions) { + if (each instanceof IStringExpression) { + result.append(((IStringExpression) each).getStringValue(context, stream)); + } + } + return result.toString(); + } + + @Override + public int getIntegerValue(MatchContext context, RutaStream stream) { + return (int) getDoubleValue(context, stream); + } + + @Override + public double getDoubleValue(MatchContext context, RutaStream stream) { + double result = 0; + for (IRutaExpression each : expressions) { + if (each instanceof INumberExpression) { + result += ((INumberExpression) each).getDoubleValue(context, stream); + } + } + return result; + } + + @Override + public float getFloatValue(MatchContext context, RutaStream stream) { + return (float) getDoubleValue(context, stream); + } + + public List getExpressions() { + return expressions; + } +} diff --git a/ruta-core/src/main/java/org/apache/uima/ruta/utils/UIMAUtils.java b/ruta-core/src/main/java/org/apache/uima/ruta/utils/UIMAUtils.java index cac0a9a64..5a3bcccee 100644 --- a/ruta-core/src/main/java/org/apache/uima/ruta/utils/UIMAUtils.java +++ b/ruta-core/src/main/java/org/apache/uima/ruta/utils/UIMAUtils.java @@ -6,9 +6,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -33,7 +33,7 @@ public class UIMAUtils { public static FSArray toFSArray(JCas jCas, List fsList) { - FSArray fsArray = new FSArray(jCas, fsList.size()); + FSArray fsArray = new FSArray<>(jCas, fsList.size()); fsArray.copyFromArray(fsList.toArray(new FeatureStructure[fsList.size()]), 0, 0, fsList.size()); return fsArray; } @@ -58,7 +58,7 @@ public static IntegerArray toIntegerArray(JCas jCas, int[] sArray) { public static List toList(FSArray fsArray, Class cls) { - List list = new ArrayList(); + List list = new ArrayList<>(); if (fsArray == null) { return list; } diff --git a/ruta-core/src/main/java/org/apache/uima/ruta/verbalize/ExpressionVerbalizer.java b/ruta-core/src/main/java/org/apache/uima/ruta/verbalize/ExpressionVerbalizer.java index 2e8cba7ff..c4b3a947b 100644 --- a/ruta-core/src/main/java/org/apache/uima/ruta/verbalize/ExpressionVerbalizer.java +++ b/ruta-core/src/main/java/org/apache/uima/ruta/verbalize/ExpressionVerbalizer.java @@ -6,9 +6,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,10 +20,13 @@ package org.apache.uima.ruta.verbalize; import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.apache.uima.cas.CAS; import org.apache.uima.ruta.expression.AnnotationTypeExpression; +import org.apache.uima.ruta.expression.GenericComposedExpression; import org.apache.uima.ruta.expression.IRutaExpression; import org.apache.uima.ruta.expression.MatchReference; import org.apache.uima.ruta.expression.NullExpression; @@ -83,6 +86,8 @@ public ExpressionVerbalizer(RutaVerbalizer verbalizer) { public String verbalize(IRutaExpression expression) { if (expression instanceof NullExpression) { return "null"; + } else if (expression instanceof GenericComposedExpression) { + return verbalize((GenericComposedExpression) expression); } else if (expression instanceof GenericFeatureExpression) { return verbalize(((GenericFeatureExpression) expression).getFeatureExpression()); } else if (expression instanceof AnnotationTypeExpression) { @@ -336,4 +341,9 @@ public String verbalize(FeatureMatchExpression expression) { + verbalize(expression.getArg()); } + public String verbalize(GenericComposedExpression expression) { + GenericComposedExpression gce = expression; + List expressions = gce.getExpressions(); + return expressions.stream().map(e -> verbalize(e)).collect(Collectors.joining("+")); + } } diff --git a/ruta-core/src/test/java/org/apache/uima/ruta/expression/number/ComposedNumberExpressionTest.java b/ruta-core/src/test/java/org/apache/uima/ruta/expression/number/ComposedNumberExpressionTest.java index 7c8f79e4e..73e93d006 100644 --- a/ruta-core/src/test/java/org/apache/uima/ruta/expression/number/ComposedNumberExpressionTest.java +++ b/ruta-core/src/test/java/org/apache/uima/ruta/expression/number/ComposedNumberExpressionTest.java @@ -6,9 +6,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -31,7 +31,7 @@ public class ComposedNumberExpressionTest { public void testGetStringValueWithInteger() { List list = new ArrayList<>(); list.add(new SimpleNumberExpression(Integer.valueOf(1))); - ComposedNumberExpression expr = new ComposedNumberExpression(list, new ArrayList()); + ComposedNumberExpression expr = new ComposedNumberExpression(list, new ArrayList<>()); String string = expr.getStringValue(null, null); assertThat(string).isEqualTo("1"); } diff --git a/ruta-core/src/test/java/org/apache/uima/ruta/expression/number/NumberExpressionTest.java b/ruta-core/src/test/java/org/apache/uima/ruta/expression/number/NumberExpressionTest.java new file mode 100644 index 000000000..76c385506 --- /dev/null +++ b/ruta-core/src/test/java/org/apache/uima/ruta/expression/number/NumberExpressionTest.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.uima.ruta.expression.number; + +import org.apache.uima.cas.CAS; +import org.apache.uima.ruta.engine.Ruta; +import org.apache.uima.ruta.engine.RutaTestUtils; +import org.junit.jupiter.api.Test; + +public class NumberExpressionTest { + + @Test + public void testComposedAssignment() throws Exception { + String script = "INT i = 1;"; + script += "Document{i==2 -> T1};"; + script += "Document{-> i = i + 1};"; + script += "Document{i==2 -> T2};"; + script += "Document{-> i = 1 + 1 + 1};"; + script += "Document{i==3 -> T3};"; + script += "Document{i== 1+1+1 -> T4};"; + script += "Document{i== 1+i-1 -> T5};"; + script += "Document{-> i = (1 + 1 * 3) / 2};"; + script += "Document{i== 8 / 4 -> T6};"; + CAS cas = RutaTestUtils.getCAS("This is a test."); + Ruta.apply(cas, script); + + RutaTestUtils.assertAnnotationsEquals(cas, 1, 0); + RutaTestUtils.assertAnnotationsEquals(cas, 2, 1, "This is a test."); + RutaTestUtils.assertAnnotationsEquals(cas, 3, 1, "This is a test."); + RutaTestUtils.assertAnnotationsEquals(cas, 4, 1, "This is a test."); + RutaTestUtils.assertAnnotationsEquals(cas, 5, 1, "This is a test."); + RutaTestUtils.assertAnnotationsEquals(cas, 6, 1, "This is a test."); + } + +} diff --git a/ruta-core/src/test/java/org/apache/uima/ruta/verbalizer/ExpressionVerbalizerTest.java b/ruta-core/src/test/java/org/apache/uima/ruta/verbalizer/ExpressionVerbalizerTest.java index 6e8c541ca..8ad868194 100644 --- a/ruta-core/src/test/java/org/apache/uima/ruta/verbalizer/ExpressionVerbalizerTest.java +++ b/ruta-core/src/test/java/org/apache/uima/ruta/verbalizer/ExpressionVerbalizerTest.java @@ -6,9 +6,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -22,8 +22,10 @@ import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import org.apache.uima.ruta.expression.GenericComposedExpression; import org.apache.uima.ruta.expression.MatchReference; import org.apache.uima.ruta.expression.annotation.AnnotationLabelExpression; import org.apache.uima.ruta.expression.annotation.AnnotationVariableExpression; @@ -67,49 +69,16 @@ public class ExpressionVerbalizerTest { @Test public void test() { RutaVerbalizer v = new RutaVerbalizer(); - // List typeExprList = new ArrayList(); - // List stringExprList = new ArrayList(); - // List exprList = new ArrayList(); - // List indexes = new ArrayList(); - - // - // // typeExprList.add(typeExpr1); - // // typeExprList.add(typeExpr2); - // - // - // StringExpression stringExpr = new SimpleStringExpression("string"); - // stringExprList.add(stringExpr); - // // exprList.add(typeExpr1); - // WordTableExpression wordTableExpr = new ReferenceWordTableExpression(var); - // WordListExpression wordListExpr = new ReferenceWordListExpression(var); - // TypeListExpression typeListExpr = new SimpleTypeListExpression(typeExprList); - // StringListExpression stringListExpr = new SimpleStringListExpression(stringExprList); - // Map stringExprMap = new HashMap(); - // Map stringExprNumExprMap = new HashMap(); - // Map stringExprTypeExprMap = new HashMap(); - // @SuppressWarnings("rawtypes") - // ListExpression listExpr = new SimpleTypeListExpression(typeExprList); - // @SuppressWarnings("rawtypes") - // List listExprList = new ArrayList(); - // listExprList.add(listExpr); - // stringExprMap.put(stringExpr, stringExpr); - // // stringExprNumExprMap.put(stringExpr, numExpr1); - // // stringExprTypeExprMap.put(stringExpr, typeExpr1); - // // indexes.add(numExpr1); - // // indexes.add(numExpr2); String s = null; String var = "anyVar"; ITypeExpression typeExpr1 = new SimpleTypeExpression("Type1"); ITypeExpression typeExpr2 = new TypeVariableExpression("typeVar"); - List numExprList1 = new ArrayList(); - List numExprList2 = new ArrayList(); - List opList1 = new ArrayList(); - List opList2 = new ArrayList(); + List numExprList1 = new ArrayList<>(); + List numExprList2 = new ArrayList<>(); + List opList1 = new ArrayList<>(); + List opList2 = new ArrayList<>(); INumberExpression numExpr1 = new SimpleNumberExpression(4); INumberExpression numExpr2 = new NumberVariableExpression("numVar"); INumberExpression numExpr3 = new NumberVariableExpression("4.9"); @@ -171,7 +140,7 @@ public void test() { s = v.verbalize(boolExpr11); assertThat(s).isEqualTo("Type1 != typeVar"); - List stringExprList = new ArrayList(); + List stringExprList = new ArrayList<>(); AbstractStringExpression stringExpr1 = new SimpleStringExpression("string"); AbstractStringExpression stringExpr2 = new StringVariableExpression(var); stringExprList.add(stringExpr1); @@ -192,7 +161,7 @@ public void test() { s = v.verbalize(sle2); assertThat(s).isEqualTo("anyVar"); - List boolExprList = new ArrayList(); + List boolExprList = new ArrayList<>(); boolExprList.add(boolExpr1); boolExprList.add(boolExpr3); AbstractBooleanListExpression ble1 = new SimpleBooleanListExpression(boolExprList); @@ -202,7 +171,7 @@ public void test() { s = v.verbalize(ble2); assertThat(s).isEqualTo("anyVar"); - List numExprList = new ArrayList(); + List numExprList = new ArrayList<>(); numExprList.add(numExpr1); numExprList.add(numExpr3); AbstractNumberListExpression nle1 = new SimpleNumberListExpression(numExprList); @@ -212,7 +181,7 @@ public void test() { s = v.verbalize(nle2); assertThat(s).isEqualTo("anyVar"); - List typeExprList = new ArrayList(); + List typeExprList = new ArrayList<>(); typeExprList.add(typeExpr1); typeExprList.add(typeExpr2); AbstractTypeListExpression tle1 = new SimpleTypeListExpression(typeExprList); @@ -243,4 +212,22 @@ public void testGenericFeatureExpression() { assertThat(v.verbalize(new GenericFeatureExpression(null))).isEqualTo(""); } + @Test + public void testGenericComposedExpression() { + RutaVerbalizer v = new RutaVerbalizer(); + assertThat(v.verbalize(new GenericComposedExpression( + Arrays.asList(new SimpleStringExpression("a"), new SimpleStringExpression("b"))))) + .isEqualTo("\"a\"+\"b\""); + assertThat(v.verbalize(new GenericComposedExpression( + Arrays.asList(new SimpleNumberExpression(1), new SimpleNumberExpression(2))))) + .isEqualTo("1+2"); + assertThat(v.verbalize(new GenericComposedExpression( + Arrays.asList(new SimpleStringExpression("a"), new SimpleNumberExpression(2))))) + .isEqualTo("\"a\"+2"); + assertThat(v.verbalize(new GenericComposedExpression( + Arrays.asList(new SimpleFeatureExpression(new MatchReference("abc.d")), + new AnnotationVariableExpression("l"))))).isEqualTo("abc.d+l"); + assertThat(v.verbalize(new GenericFeatureExpression(null))).isEqualTo(""); + } + }