From 99f85ff47540810acd44af6fcbe68d3c0851aa90 Mon Sep 17 00:00:00 2001 From: Roel van Dijk Date: Thu, 30 Aug 2018 19:33:38 +0200 Subject: [PATCH] #246 Refactor Count/First/Last/FoldCat to OneToOneValueExpressions. --- .../metal/expression/value/FoldCat.java | 36 ++------- .../value/OneToManyValueExpression.java | 3 +- .../value/OneToOneValueExpression.java | 77 +++++++++++++++++++ .../expression/value/reference/Count.java | 32 ++------ .../expression/value/reference/First.java | 31 ++------ .../expression/value/reference/Last.java | 32 ++------ 6 files changed, 101 insertions(+), 110 deletions(-) create mode 100644 core/src/main/java/io/parsingdata/metal/expression/value/OneToOneValueExpression.java diff --git a/core/src/main/java/io/parsingdata/metal/expression/value/FoldCat.java b/core/src/main/java/io/parsingdata/metal/expression/value/FoldCat.java index defc5806..ab911baa 100644 --- a/core/src/main/java/io/parsingdata/metal/expression/value/FoldCat.java +++ b/core/src/main/java/io/parsingdata/metal/expression/value/FoldCat.java @@ -16,14 +16,11 @@ package io.parsingdata.metal.expression.value; -import static java.math.BigInteger.ZERO; - import static io.parsingdata.metal.data.Slice.createFromSource; +import static java.math.BigInteger.ZERO; -import java.util.Objects; import java.util.Optional; -import io.parsingdata.metal.Util; import io.parsingdata.metal.data.ConcatenatedValueSource; import io.parsingdata.metal.data.ImmutableList; import io.parsingdata.metal.data.ParseState; @@ -36,36 +33,17 @@ * @see FoldLeft * @see Cat */ -public class FoldCat implements ValueExpression { - - public final ValueExpression operand; +public class FoldCat extends OneToOneValueExpression { public FoldCat(final ValueExpression operand) { - this.operand = operand; - } - - @Override - public ImmutableList> eval(final ParseState parseState, final Encoding encoding) { - return ConcatenatedValueSource.create(operand.eval(parseState, encoding)) - .flatMap(source -> createFromSource(source, ZERO, source.length)) - .map(slice -> new ImmutableList>().add(Optional.of(new Value(slice, encoding)))) - .orElseGet(() -> ImmutableList.create(Optional.empty())); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "(" + operand + ")"; - } - - @Override - public boolean equals(final Object obj) { - return Util.notNullAndSameClass(this, obj) - && Objects.equals(operand, ((FoldCat)obj).operand); + super(operand); } @Override - public int hashCode() { - return Objects.hash(getClass(), operand); + public Optional eval(final ImmutableList> list, final ParseState parseState, final Encoding encoding) { + return ConcatenatedValueSource.create(list) + .flatMap(source -> createFromSource(source, ZERO, source.length)) + .map(slice -> new Value(slice, encoding)); } } diff --git a/core/src/main/java/io/parsingdata/metal/expression/value/OneToManyValueExpression.java b/core/src/main/java/io/parsingdata/metal/expression/value/OneToManyValueExpression.java index 18fe2097..f3552397 100644 --- a/core/src/main/java/io/parsingdata/metal/expression/value/OneToManyValueExpression.java +++ b/core/src/main/java/io/parsingdata/metal/expression/value/OneToManyValueExpression.java @@ -31,7 +31,8 @@ import io.parsingdata.metal.encoding.Encoding; /** - * Base class for {@link ValueExpression}s with one operand. + * Base class for {@link ValueExpression}s with one operand that evaluates + * to multiple values. *

* A OneToManyValueExpression implements a ValueExpression that has one * operand (a {@link ValueExpression}). The operand is first diff --git a/core/src/main/java/io/parsingdata/metal/expression/value/OneToOneValueExpression.java b/core/src/main/java/io/parsingdata/metal/expression/value/OneToOneValueExpression.java new file mode 100644 index 00000000..56208d4b --- /dev/null +++ b/core/src/main/java/io/parsingdata/metal/expression/value/OneToOneValueExpression.java @@ -0,0 +1,77 @@ +/* + * Copyright 2013-2016 Netherlands Forensic Institute + * + * Licensed 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 io.parsingdata.metal.expression.value; + +import static io.parsingdata.metal.Util.checkNotNull; + +import java.util.Objects; +import java.util.Optional; + +import io.parsingdata.metal.Util; +import io.parsingdata.metal.data.ImmutableList; +import io.parsingdata.metal.data.ParseState; +import io.parsingdata.metal.encoding.Encoding; + +/** + * Base class for {@link ValueExpression}s with one operand that evaluates + * to a single value. + *

+ * A OneToOneValueExpression implements a ValueExpression that has one + * operand (a {@link ValueExpression}). The operand is first + * evaluated. If it evaluates to {@link Optional#empty()}, the result of the + * ValueExpression itself will be that as well. + *

+ * To implement a OneToOneValueExpression, only the + * {@link #eval(ImmutableList, ParseState, Encoding)} must + * be implemented, handling the case of evaluating a list of values. This + * base class takes care of evaluating the operand and handling list + * semantics. + * + * @see BinaryValueExpression + */ +public abstract class OneToOneValueExpression implements ValueExpression { + + public final ValueExpression operand; + + public OneToOneValueExpression(final ValueExpression operand) { + this.operand = checkNotNull(operand, "operand"); + } + + @Override + public ImmutableList> eval(final ParseState parseState, final Encoding encoding) { + return ImmutableList.create(eval(operand.eval(parseState, encoding), parseState, encoding)); + } + + public abstract Optional eval(final ImmutableList> list, final ParseState parseState, final Encoding encoding); + + @Override + public String toString() { + return getClass().getSimpleName() + "(" + operand + ")"; + } + + @Override + public boolean equals(final Object obj) { + return Util.notNullAndSameClass(this, obj) + && Objects.equals(operand, ((OneToOneValueExpression)obj).operand); + } + + @Override + public int hashCode() { + return Objects.hash(getClass(), operand); + } + +} diff --git a/core/src/main/java/io/parsingdata/metal/expression/value/reference/Count.java b/core/src/main/java/io/parsingdata/metal/expression/value/reference/Count.java index 19c8adf7..9d0ee29b 100644 --- a/core/src/main/java/io/parsingdata/metal/expression/value/reference/Count.java +++ b/core/src/main/java/io/parsingdata/metal/expression/value/reference/Count.java @@ -16,17 +16,14 @@ package io.parsingdata.metal.expression.value.reference; -import static io.parsingdata.metal.Util.checkNotNull; - -import java.util.Objects; import java.util.Optional; -import io.parsingdata.metal.Util; import io.parsingdata.metal.data.ImmutableList; import io.parsingdata.metal.data.ParseState; import io.parsingdata.metal.encoding.Encoding; import io.parsingdata.metal.encoding.Sign; import io.parsingdata.metal.expression.value.ConstantFactory; +import io.parsingdata.metal.expression.value.OneToOneValueExpression; import io.parsingdata.metal.expression.value.Value; import io.parsingdata.metal.expression.value.ValueExpression; @@ -34,38 +31,19 @@ * A {@link ValueExpression} that represents the amount of {@link Value}s * returned by evaluating its operand. */ -public class Count implements ValueExpression { - - public final ValueExpression operand; +public class Count extends OneToOneValueExpression { public Count(final ValueExpression operand) { - this.operand = checkNotNull(operand, "operand"); + super(operand); } @Override - public ImmutableList> eval(final ParseState parseState, final Encoding encoding) { - final ImmutableList> values = operand.eval(parseState, encoding); - return ImmutableList.create(Optional.of(fromNumeric(values.size))); + public Optional eval(final ImmutableList> list, final ParseState parseState, final Encoding encoding) { + return Optional.of(fromNumeric(list.size)); } private static Value fromNumeric(final long length) { return ConstantFactory.createFromNumeric(length, new Encoding(Sign.SIGNED)); } - @Override - public String toString() { - return getClass().getSimpleName() + "(" + operand + ")"; - } - - @Override - public boolean equals(final Object obj) { - return Util.notNullAndSameClass(this, obj) - && Objects.equals(operand, ((Count)obj).operand); - } - - @Override - public int hashCode() { - return Objects.hash(getClass(), operand); - } - } diff --git a/core/src/main/java/io/parsingdata/metal/expression/value/reference/First.java b/core/src/main/java/io/parsingdata/metal/expression/value/reference/First.java index c3031f92..abbbdffc 100644 --- a/core/src/main/java/io/parsingdata/metal/expression/value/reference/First.java +++ b/core/src/main/java/io/parsingdata/metal/expression/value/reference/First.java @@ -18,16 +18,14 @@ import static io.parsingdata.metal.Trampoline.complete; import static io.parsingdata.metal.Trampoline.intermediate; -import static io.parsingdata.metal.Util.checkNotNull; -import java.util.Objects; import java.util.Optional; import io.parsingdata.metal.Trampoline; -import io.parsingdata.metal.Util; import io.parsingdata.metal.data.ImmutableList; import io.parsingdata.metal.data.ParseState; import io.parsingdata.metal.encoding.Encoding; +import io.parsingdata.metal.expression.value.OneToOneValueExpression; import io.parsingdata.metal.expression.value.Value; import io.parsingdata.metal.expression.value.ValueExpression; @@ -35,38 +33,19 @@ * A {@link ValueExpression} that represents the first {@link Value} returned * by evaluating its operand. */ -public class First implements ValueExpression { - - public final ValueExpression operand; +public class First extends OneToOneValueExpression { public First(final ValueExpression operand) { - this.operand = checkNotNull(operand, "operand"); + super(operand); } @Override - public ImmutableList> eval(final ParseState parseState, final Encoding encoding) { - final ImmutableList> list = operand.eval(parseState, encoding); - return list.isEmpty() ? list : ImmutableList.create(getFirst(list).computeResult()); + public Optional eval(final ImmutableList> list, final ParseState parseState, final Encoding encoding) { + return list.isEmpty() ? Optional.empty() : getFirst(list).computeResult(); } private Trampoline> getFirst(final ImmutableList> values) { return values.tail.isEmpty() ? complete(() -> values.head) : intermediate(() -> getFirst(values.tail)); } - @Override - public String toString() { - return getClass().getSimpleName() + "(" + operand + ")"; - } - - @Override - public boolean equals(final Object obj) { - return Util.notNullAndSameClass(this, obj) - && Objects.equals(operand, ((First)obj).operand); - } - - @Override - public int hashCode() { - return Objects.hash(getClass(), operand); - } - } diff --git a/core/src/main/java/io/parsingdata/metal/expression/value/reference/Last.java b/core/src/main/java/io/parsingdata/metal/expression/value/reference/Last.java index 6d023051..f11e2f1c 100644 --- a/core/src/main/java/io/parsingdata/metal/expression/value/reference/Last.java +++ b/core/src/main/java/io/parsingdata/metal/expression/value/reference/Last.java @@ -16,15 +16,12 @@ package io.parsingdata.metal.expression.value.reference; -import static io.parsingdata.metal.Util.checkNotNull; - -import java.util.Objects; import java.util.Optional; -import io.parsingdata.metal.Util; import io.parsingdata.metal.data.ImmutableList; import io.parsingdata.metal.data.ParseState; import io.parsingdata.metal.encoding.Encoding; +import io.parsingdata.metal.expression.value.OneToOneValueExpression; import io.parsingdata.metal.expression.value.Value; import io.parsingdata.metal.expression.value.ValueExpression; @@ -32,34 +29,15 @@ * A {@link ValueExpression} that represents the last {@link Value} returned * by evaluating its operand. */ -public class Last implements ValueExpression { - - public final ValueExpression operand; +public class Last extends OneToOneValueExpression { public Last(final ValueExpression operand) { - this.operand = checkNotNull(operand, "operand"); - } - - @Override - public ImmutableList> eval(final ParseState parseState, final Encoding encoding) { - final ImmutableList> list = operand.eval(parseState, encoding); - return list.isEmpty() ? list : ImmutableList.create(list.head); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "(" + operand + ")"; - } - - @Override - public boolean equals(final Object obj) { - return Util.notNullAndSameClass(this, obj) - && Objects.equals(operand, ((Last)obj).operand); + super(operand); } @Override - public int hashCode() { - return Objects.hash(getClass(), operand); + public Optional eval(final ImmutableList> list, final ParseState parseState, final Encoding encoding) { + return list.isEmpty() ? Optional.empty() : list.head; } }