You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by dp...@apache.org on 2017/06/28 18:17:39 UTC
[16/20] lucene-solr:master: SOLR-10123: Upgraded the Analytics
Component to version 2.0
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongField.java
new file mode 100644
index 0000000..ac4da2e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongField.java
@@ -0,0 +1,107 @@
+/*
+ * 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.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.NumericDocValues;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.value.LongValue.CastingLongValue;
+import org.apache.solr.schema.LongPointField;
+import org.apache.solr.schema.TrieLongField;
+
+/**
+ * An analytics wrapper for a single-valued {@link TrieLongField} or {@link LongPointField} with DocValues enabled.
+ */
+public class LongField extends AnalyticsField implements CastingLongValue {
+ private NumericDocValues docValues;
+ private long value;
+ private boolean exists;
+
+ public LongField(String fieldName) {
+ super(fieldName);
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getNumeric(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ exists = docValues.advanceExact(doc);
+ if (exists) {
+ value = docValues.longValue();
+ }
+ }
+
+ @Override
+ public long getLong() {
+ return value;
+ }
+ @Override
+ public double getDouble() {
+ return (double)value;
+ }
+ @Override
+ public String getString() {
+ return exists ? Long.toString(value) : null;
+ }
+ @Override
+ public Object getObject() {
+ return exists ? value : null;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public void streamLongs(LongConsumer cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ if (exists) {
+ cons.accept((double)value);
+ }
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ if (exists) {
+ cons.accept(Long.toString(value));
+ }
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+
+ @Override
+ public ExpressionComparator<Long> getObjectComparator(String expression) {
+ return new ExpressionComparator<>(expression);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiField.java
new file mode 100644
index 0000000..dc2a953
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiField.java
@@ -0,0 +1,89 @@
+/*
+ * 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.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.solr.analytics.value.LongValueStream.CastingLongValueStream;
+import org.apache.solr.legacy.LegacyNumericUtils;
+import org.apache.solr.schema.TrieLongField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link TrieLongField} with DocValues enabled.
+ */
+public class LongMultiField extends AnalyticsField implements CastingLongValueStream {
+ private SortedSetDocValues docValues;
+ private int count;
+ private long[] values;
+
+ public LongMultiField(String fieldName) {
+ super(fieldName);
+ count = 0;
+ values = new long[initialArrayLength];
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSortedSet(context.reader(), fieldName);
+ }
+ @Override
+ public void collect(int doc) throws IOException {
+ count = 0;
+ if (docValues.advanceExact(doc)) {
+ int term;
+ while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+ if (count == values.length) {
+ resizeValues();
+ }
+ values[count++] = LegacyNumericUtils.prefixCodedToLong(docValues.lookupOrd(term));
+ }
+ }
+ }
+
+ private void resizeValues() {
+ long[] newValues = new long[values.length*2];
+ for (int i = 0; i < count; ++i) {
+ newValues[i] = values[i];
+ }
+ values = newValues;
+ }
+
+ @Override
+ public void streamLongs(LongConsumer cons) {
+ for (int i = 0; i < count; ++i) {
+ cons.accept(values[i]);
+ }
+ }
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ streamLongs(value -> cons.accept((double)value));
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamLongs(value -> cons.accept(Long.toString(value)));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamLongs(value -> cons.accept(value));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiPointField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiPointField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiPointField.java
new file mode 100644
index 0000000..31d14ae
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/LongMultiPointField.java
@@ -0,0 +1,86 @@
+/*
+ * 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.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+import java.util.function.DoubleConsumer;
+import java.util.function.LongConsumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedNumericDocValues;
+import org.apache.solr.analytics.value.LongValueStream.CastingLongValueStream;
+import org.apache.solr.schema.LongPointField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link LongPointField} with DocValues enabled.
+ */
+public class LongMultiPointField extends AnalyticsField implements CastingLongValueStream {
+ private SortedNumericDocValues docValues;
+ private int count;
+ private long[] values;
+
+ public LongMultiPointField(String fieldName) {
+ super(fieldName);
+ count = 0;
+ values = new long[initialArrayLength];
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSortedNumeric(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ if (docValues.advanceExact(doc)) {
+ count = docValues.docValueCount();
+ resizeEmptyValues(count);
+ for (int i = 0; i < count; ++i) {
+ values[i] = docValues.nextValue();
+ }
+ } else {
+ count = 0;
+ }
+ }
+
+ private void resizeEmptyValues(int count) {
+ if (count > values.length) {
+ values = new long[count];
+ }
+ }
+
+ @Override
+ public void streamLongs(LongConsumer cons) {
+ for (int i = 0; i < count; ++i) {
+ cons.accept(values[i]);
+ }
+ }
+ @Override
+ public void streamDoubles(DoubleConsumer cons) {
+ streamLongs(value -> cons.accept((double)value));
+ }
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ streamLongs(value -> cons.accept(Long.toString(value)));
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ streamLongs(value -> cons.accept(value));
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringField.java
new file mode 100644
index 0000000..207a95a
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringField.java
@@ -0,0 +1,85 @@
+/*
+ * 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.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.function.Consumer;
+
+import org.apache.lucene.index.BinaryDocValues;
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.solr.analytics.facet.compare.ExpressionComparator;
+import org.apache.solr.analytics.value.StringValue.CastingStringValue;
+import org.apache.solr.schema.StrField;
+
+/**
+ * An analytics wrapper for a single-valued {@link StrField} with DocValues enabled.
+ */
+public class StringField extends AnalyticsField implements CastingStringValue {
+ private BinaryDocValues docValues;
+ String value;
+ boolean exists;
+
+ public StringField(String fieldName) {
+ super(fieldName);
+ exists = false;
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getBinary(context.reader(), fieldName);
+ }
+
+ @Override
+ public void collect(int doc) throws IOException {
+ exists = docValues.advanceExact(doc);
+ if (exists) {
+ value = docValues.binaryValue().utf8ToString();
+ }
+ }
+
+ @Override
+ public String getString() {
+ return exists ? value : null;
+ }
+ @Override
+ public Object getObject() {
+ return exists ? value : null;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ if (exists) {
+ cons.accept(value);
+ }
+ }
+
+ @Override
+ public ExpressionComparator<String> getObjectComparator(String expression) {
+ return new ExpressionComparator<>(expression);
+ }
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringMultiField.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringMultiField.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringMultiField.java
new file mode 100644
index 0000000..39c60f0
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/StringMultiField.java
@@ -0,0 +1,66 @@
+/*
+ * 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.solr.analytics.function.field;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+import org.apache.lucene.index.DocValues;
+import org.apache.lucene.index.LeafReaderContext;
+import org.apache.lucene.index.SortedSetDocValues;
+import org.apache.solr.analytics.value.StringValueStream.CastingStringValueStream;
+import org.apache.solr.schema.StrField;
+
+/**
+ * An analytics wrapper for a multi-valued {@link StrField} with DocValues enabled.
+ */
+public class StringMultiField extends AnalyticsField implements CastingStringValueStream {
+ private SortedSetDocValues docValues;
+ private ArrayList<String> values;
+
+ public StringMultiField(String fieldName) {
+ super(fieldName);
+ values = new ArrayList<>(initialArrayLength);
+ }
+
+ @Override
+ public void doSetNextReader(LeafReaderContext context) throws IOException {
+ docValues = DocValues.getSortedSet(context.reader(), fieldName);
+ }
+ @Override
+ public void collect(int doc) throws IOException {
+ values.clear();
+ if (docValues.advanceExact(doc)) {
+ int term;
+ while ((term = (int)docValues.nextOrd()) != SortedSetDocValues.NO_MORE_ORDS) {
+ values.add(docValues.lookupOrd(term).utf8ToString());
+ }
+ }
+ }
+
+ @Override
+ public void streamStrings(Consumer<String> cons) {
+ values.forEach(value -> cons.accept(value));
+ }
+
+ @Override
+ public void streamObjects(Consumer<Object> cons) {
+ values.forEach(value -> cons.accept(value));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/package-info.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/package-info.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/package-info.java
new file mode 100644
index 0000000..a0e5421
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/field/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * Fields to use for analytics expressions.
+ */
+package org.apache.solr.analytics.function.field;
+
+
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AbsoluteValueFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AbsoluteValueFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AbsoluteValueFunction.java
new file mode 100644
index 0000000..d52810f
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AbsoluteValueFunction.java
@@ -0,0 +1,54 @@
+/*
+ * 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.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * An absolute value mapping function.
+ * <p>
+ * Takes a numeric ValueStream or Value and returns a ValueStream or Value of the same numeric type.
+ */
+public class AbsoluteValueFunction {
+ public static final String name = "abs";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 1) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramaters, " + params.length + " found.");
+ }
+ AnalyticsValueStream param = params[0];
+ if (param instanceof IntValueStream) {
+ return LambdaFunction.createIntLambdaFunction(name, x -> (x<0)? x*-1:x, (IntValueStream)param);
+ }
+ if (param instanceof LongValueStream) {
+ return LambdaFunction.createLongLambdaFunction(name, x -> (x<0)? x*-1:x, (LongValueStream)param);
+ }
+ if (param instanceof FloatValueStream) {
+ return LambdaFunction.createFloatLambdaFunction(name, x -> (x<0)? x*-1:x, (FloatValueStream)param);
+ }
+ if (param instanceof DoubleValueStream) {
+ return LambdaFunction.createDoubleLambdaFunction(name, x -> (x<0)? x*-1:x, (DoubleValueStream)param);
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a numeric parameter, "+param.getExpressionStr()+" found.");
+ });
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AddFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AddFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AddFunction.java
new file mode 100644
index 0000000..d66f84e
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/AddFunction.java
@@ -0,0 +1,68 @@
+/*
+ * 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.solr.analytics.function.mapping;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+
+/**
+ * An addition mapping function.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If a single numeric ValueStream is passed in, a {@link DoubleValue} representing the sum of the values for each document is returned.
+ * <li>If a numeric ValueStream and a numeric Value are passed in, a {@link DoubleValueStream} representing the sum of
+ * the Value and each of the values of the ValueStream for a document is returned.
+ * (Or the other way, since the Value and ValueStream can be used in either order)
+ * <li>If multiple numeric Values are passed in, a {@link DoubleValue} representing the sum of all values is returned.
+ * </ul>
+ */
+public class AddFunction {
+ public static final String name = "add";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length == 0) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires parameters.");
+ }
+ else if (params.length == 1) {
+ if (params[0] instanceof DoubleValueStream) {
+ return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a+b, (DoubleValueStream)params[0]);
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters. Incorrect param: "+params[0].getExpressionStr());
+ }
+ else if (params.length == 2) {
+ AnalyticsValueStream param1 = params[0];
+ AnalyticsValueStream param2 = params[1];
+ if (param1 instanceof DoubleValueStream && param2 instanceof DoubleValueStream) {
+ return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a+b, (DoubleValueStream)param1, (DoubleValueStream)param2);
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters.");
+ }
+ DoubleValue[] castedParams = new DoubleValue[params.length];
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof DoubleValue) {
+ castedParams[i] = (DoubleValue) params[i];
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that all parameters be single-valued if more than 2 are given.");
+ }
+ }
+ return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a+b, castedParams);
+ });
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/BottomFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/BottomFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/BottomFunction.java
new file mode 100644
index 0000000..f896da4
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/BottomFunction.java
@@ -0,0 +1,163 @@
+/*
+ * 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.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.FloatValue;
+import org.apache.solr.analytics.value.FloatValueStream;
+import org.apache.solr.analytics.value.IntValue;
+import org.apache.solr.analytics.value.IntValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A bottom mapping function, returning the lowest value found.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If a single comparable ValueStream is passed in, a Value (of the same type) representing the minimum of the values for each document is returned.
+ * <li>If multiple comparable Values are passed in, a Value (of the same type) representing the minimum of all values is returned.
+ * </ul>
+ */
+public class BottomFunction {
+ public static final String name = "bottom";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length == 0) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires paramaters.");
+ }
+ AnalyticsValueStream param = params[0];
+ if (param instanceof DateValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createDateLambdaFunction(name, (a,b) -> (a<b)? a:b, (DateValueStream)param);
+ }
+ DateValue[] castedParams = new DateValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof DateValue) {
+ castedParams[i] = (DateValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createDateLambdaFunction(name, (a,b) -> (a<b)? a:b, castedParams, false);
+ }
+ }
+ if (param instanceof IntValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createIntLambdaFunction(name, (a,b) -> (a<b)? a:b, (IntValueStream)param);
+ }
+ IntValue[] castedParams = new IntValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof IntValue) {
+ castedParams[i] = (IntValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createIntLambdaFunction(name, (a,b) -> (a<b)? a:b, castedParams, false);
+ }
+ }
+ if (param instanceof LongValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createLongLambdaFunction(name, (a,b) -> (a<b)? a:b, (LongValueStream)param);
+ }
+ LongValue[] castedParams = new LongValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof LongValue) {
+ castedParams[i] = (LongValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createLongLambdaFunction(name, (a,b) -> (a<b)? a:b, castedParams, false);
+ }
+ }
+ if (param instanceof FloatValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createFloatLambdaFunction(name, (a,b) -> (a<b)? a:b, (FloatValueStream)param);
+ }
+ FloatValue[] castedParams = new FloatValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof FloatValue) {
+ castedParams[i] = (FloatValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createFloatLambdaFunction(name, (a,b) -> (a<b)? a:b, castedParams, false);
+ }
+ }
+ if (param instanceof DoubleValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> (a<b)? a:b, (DoubleValueStream)param);
+ }
+ DoubleValue[] castedParams = new DoubleValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof DoubleValue) {
+ castedParams[i] = (DoubleValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> (a<b)? a:b, castedParams, false);
+ }
+ }
+ if (param instanceof StringValueStream) {
+ if (params.length == 1) {
+ return LambdaFunction.createStringLambdaFunction(name, (a,b) -> (a.compareTo(b)<=0)? a:b, (StringValueStream)param);
+ }
+ StringValue[] castedParams = new StringValue[params.length];
+ boolean tryNextType = false;
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof StringValue) {
+ castedParams[i] = (StringValue) params[i];
+ } else {
+ tryNextType = true;
+ break;
+ }
+ }
+ if (!tryNextType) {
+ return LambdaFunction.createStringLambdaFunction(name, (a,b) -> (a.compareTo(b)<=0)? a:b, castedParams, false);
+ }
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a comparable parameter. " +
+ "Incorrect parameter: "+params[0].getExpressionStr());
+ });
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/CompareFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/CompareFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/CompareFunction.java
new file mode 100644
index 0000000..a06f7b8
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/CompareFunction.java
@@ -0,0 +1,614 @@
+/*
+ * 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.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.util.function.BooleanConsumer;
+import org.apache.solr.analytics.value.AnalyticsValue;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.BooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.BooleanValue.AbstractBooleanValue;
+import org.apache.solr.analytics.value.BooleanValueStream.AbstractBooleanValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * Contains all comparable functions. Comparable functions accept two parameters and return a BooleanValueStream.
+ * The two parameters must be able to be cast to the same type.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If a two comparable {@link AnalyticsValue}s are passed in, a {@link BooleanValue} representing the comparison of the two values for each document is returned.
+ * <li>If a comparable {@link AnalyticsValue} and a comparable {@link AnalyticsValueStream} are passed in,
+ * a {@link BooleanValueStream} representing the comparison of the Value and each of the values of the ValueStream for the document is returned.
+ * </ul>
+ */
+public class CompareFunction {
+
+ private static BooleanValueStream createCompareFunction(String name, CompResultFunction comp, AnalyticsValueStream... params) {
+ if (params.length != 2) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramaters, " + params.length + " found.");
+ }
+ AnalyticsValueStream paramA = params[0];
+ AnalyticsValueStream paramB = params[1];
+ if (paramA instanceof DateValueStream && paramB instanceof DateValueStream) {
+ if (paramA instanceof DateValue) {
+ if (paramB instanceof DateValue) {
+ return new CompareDateValueFunction(name,(DateValue)paramA,(DateValue)paramB,comp);
+ }
+ return new CompareDateStreamFunction(name,(DateValue)paramA,(DateValueStream)paramB,comp);
+ }
+ if (paramB instanceof DateValue) {
+ return new CompareDateStreamFunction(name,(DateValue)paramB,(DateValueStream)paramA,reverse(comp));
+ }
+ } else if (paramA instanceof DoubleValueStream && paramB instanceof DoubleValueStream) {
+ if (paramA instanceof DoubleValue) {
+ if (paramB instanceof DoubleValue) {
+ return new CompareDoubleValueFunction(name,(DoubleValue)paramA,(DoubleValue)paramB,comp);
+ }
+ return new CompareDoubleStreamFunction(name,(DoubleValue)paramA,(DoubleValueStream)paramB,comp);
+ }
+ if (paramB instanceof DoubleValue) {
+ return new CompareDoubleStreamFunction(name,(DoubleValue)paramB,(DoubleValueStream)paramA,reverse(comp));
+ }
+ } else if (paramA instanceof StringValueStream && paramB instanceof StringValueStream) {
+ if (paramA instanceof StringValue) {
+ if (paramB instanceof StringValue) {
+ return new CompareStringValueFunction(name,(StringValue)paramA,(StringValue)paramB,comp);
+ }
+ return new CompareStringStreamFunction(name,(StringValue)paramA,(StringValueStream)paramB,comp);
+ }
+ if (paramB instanceof StringValue) {
+ return new CompareStringStreamFunction(name,(StringValue)paramB,(StringValueStream)paramA,reverse(comp));
+ }
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires comparable parameters.");
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that at least 1 parameter be single-valued.");
+ }
+
+ /**
+ * A comparison function that tests equality.
+ */
+ public static class EqualFunction {
+ public static final String name = "equal";
+ public static final CreatorFunction creatorFunction = (params -> {
+ try {
+ return CompareFunction.createCompareFunction(name, val -> {
+ return val == 0;
+ }, params);
+ } catch (SolrException e) {
+ if (params.length != 2) {
+ throw e;
+ }
+
+ AnalyticsValueStream paramA = params[0];
+ AnalyticsValueStream paramB = params[1];
+
+ // Booleans aren't really comparable, so just enable the equal function
+ if (paramA instanceof BooleanValueStream && paramB instanceof BooleanValueStream) {
+ if (paramA instanceof BooleanValue) {
+ if (paramB instanceof BooleanValue) {
+ return new BooleanValueEqualFunction((BooleanValue)paramA,(BooleanValue)paramB);
+ }
+ return new BooleanStreamEqualFunction((BooleanValue)paramA,(BooleanValueStream)paramB);
+ } else if (paramB instanceof BooleanValue) {
+ return new BooleanStreamEqualFunction((BooleanValue)paramB,(BooleanValueStream)paramA);
+ }
+ }
+
+ // This means that the Objects created by the AnalyticsValueStreams are not comparable, so use the .equals() method instead
+ else if (paramA instanceof AnalyticsValue) {
+ if (paramB instanceof AnalyticsValue) {
+ return new ValueEqualFunction((AnalyticsValue)paramA,(AnalyticsValue)paramB);
+ }
+ return new StreamEqualFunction((AnalyticsValue)paramA,paramB);
+ }
+ if (paramB instanceof AnalyticsValue) {
+ return new StreamEqualFunction((AnalyticsValue)paramB,paramA);
+ }
+ }
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that at least 1 parameter be single-valued.");
+ });
+ }
+
+ /**
+ * A comparison function that tests whether the first parameter is greater than the second parameter
+ */
+ public static class GTFunction {
+ public static final String name = "gt";
+ public static final CreatorFunction creatorFunction = (params -> {
+ return CompareFunction.createCompareFunction(name, val -> {
+ return val > 0;
+ }, params);
+ });
+ }
+
+ /**
+ * A comparison function that tests whether the first parameter is greater than or equal to the second parameter
+ */
+ public static class GTEFunction {
+ public static final String name = "gte";
+ public static final CreatorFunction creatorFunction = (params -> {
+ return CompareFunction.createCompareFunction(name, val -> {
+ return val >= 0;
+ }, params);
+ });
+ }
+
+ /**
+ * A comparison function that tests whether the first parameter is less than the second parameter
+ */
+ public static class LTFunction {
+ public static final String name = "lt";
+ public static final CreatorFunction creatorFunction = (params -> {
+ return CompareFunction.createCompareFunction(name, val -> {
+ return val < 0;
+ }, params);
+ });
+ }
+
+ /**
+ * A comparison function that tests whether the first parameter is less than or equal to the second parameter
+ */
+ public static class LTEFunction {
+ public static final String name = "lte";
+ public static final CreatorFunction creatorFunction = (params -> {
+ return CompareFunction.createCompareFunction(name, val -> {
+ return val <= 0;
+ }, params);
+ });
+ }
+
+ private static CompResultFunction reverse(CompResultFunction original) {
+ return val -> original.apply(val*-1);
+ }
+}
+@FunctionalInterface
+interface CompResultFunction {
+ public boolean apply(int compResult);
+}
+/**
+ * A comparison function for two {@link DoubleValue}s.
+ */
+class CompareDoubleValueFunction extends AbstractBooleanValue {
+ private final DoubleValue exprA;
+ private final DoubleValue exprB;
+ private final CompResultFunction comp;
+ private final String name;
+ private final String funcStr;
+ private final ExpressionType funcType;
+
+ public CompareDoubleValueFunction(String name, DoubleValue exprA, DoubleValue exprB, CompResultFunction comp) {
+ this.name = name;
+ this.exprA = exprA;
+ this.exprB = exprB;
+ this.comp = comp;
+ this.funcStr = AnalyticsValueStream.createExpressionString(name,exprA,exprB);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,exprA,exprB);
+ }
+
+ private boolean exists = false;
+ @Override
+ public boolean getBoolean() {
+ double valueA = exprA.getDouble();
+ double valueB = exprB.getDouble();
+ exists = exprA.exists() && exprB.exists();
+ return exists ? comp.apply(Double.compare(valueA,valueB)) : false;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return funcStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+/**
+ * A comparison function for a {@link DoubleValue} and a {@link DoubleValueStream}.
+ */
+class CompareDoubleStreamFunction extends AbstractBooleanValueStream {
+ private final DoubleValue baseExpr;
+ private final DoubleValueStream compExpr;
+ private final CompResultFunction comp;
+ private final String name;
+ private final String funcStr;
+ private final ExpressionType funcType;
+
+ public CompareDoubleStreamFunction(String name, DoubleValue baseExpr, DoubleValueStream compExpr, CompResultFunction comp) throws SolrException {
+ this.name = name;
+ this.baseExpr = baseExpr;
+ this.compExpr = compExpr;
+ this.comp = comp;
+ this.funcStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,baseExpr,compExpr);
+ }
+
+ @Override
+ public void streamBooleans(BooleanConsumer cons) {
+ double baseValue = baseExpr.getDouble();
+ if (baseExpr.exists()) {
+ compExpr.streamDoubles(compValue -> cons.accept(comp.apply(Double.compare(baseValue,compValue))));
+ }
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return funcStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+/**
+ * A comparison function for two {@link DateValue}s.
+ */
+class CompareDateValueFunction extends AbstractBooleanValue {
+ private final DateValue exprA;
+ private final DateValue exprB;
+ private final CompResultFunction comp;
+ private final String name;
+ private final String funcStr;
+ private final ExpressionType funcType;
+
+ public CompareDateValueFunction(String name, DateValue exprA, DateValue exprB, CompResultFunction comp) {
+ this.name = name;
+ this.exprA = exprA;
+ this.exprB = exprB;
+ this.comp = comp;
+ this.funcStr = AnalyticsValueStream.createExpressionString(name,exprA,exprB);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,exprA,exprB);
+ }
+
+ private boolean exists = false;
+ @Override
+ public boolean getBoolean() {
+ long valueA = exprA.getLong();
+ long valueB = exprB.getLong();
+ exists = exprA.exists() && exprB.exists();
+ return exists ? comp.apply(Long.compare(valueA,valueB)) : false;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return funcStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+/**
+ * A comparison function for a {@link DateValue} and a {@link DateValueStream}.
+ */
+class CompareDateStreamFunction extends AbstractBooleanValueStream {
+ private final DateValue baseExpr;
+ private final DateValueStream compExpr;
+ private final CompResultFunction comp;
+ private final String name;
+ private final String funcStr;
+ private final ExpressionType funcType;
+
+ public CompareDateStreamFunction(String name, DateValue baseExpr, DateValueStream compExpr, CompResultFunction comp) throws SolrException {
+ this.name = name;
+ this.baseExpr = baseExpr;
+ this.compExpr = compExpr;
+ this.comp = comp;
+ this.funcStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,baseExpr,compExpr);
+ }
+
+ @Override
+ public void streamBooleans(BooleanConsumer cons) {
+ long baseValue = baseExpr.getLong();
+ if (baseExpr.exists()) {
+ compExpr.streamLongs(compValue -> cons.accept(comp.apply(Long.compare(baseValue,compValue))));
+ }
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return funcStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+/**
+ * A comparison function for two {@link StringValue}s.
+ */
+class CompareStringValueFunction extends AbstractBooleanValue {
+ private final StringValue exprA;
+ private final StringValue exprB;
+ private final CompResultFunction comp;
+ private final String name;
+ private final String funcStr;
+ private final ExpressionType funcType;
+
+ public CompareStringValueFunction(String name, StringValue exprA, StringValue exprB, CompResultFunction comp) {
+ this.name = name;
+ this.exprA = exprA;
+ this.exprB = exprB;
+ this.comp = comp;
+ this.funcStr = AnalyticsValueStream.createExpressionString(name,exprA,exprB);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,exprA,exprB);
+ }
+
+ private boolean exists = false;
+ @Override
+ public boolean getBoolean() {
+ String valueA = exprA.toString();
+ String valueB = exprB.toString();
+ exists = exprA.exists() && exprB.exists();
+ return exists ? comp.apply(valueA.compareTo(valueB)) : false;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return funcStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+/**
+ * A comparison function for a {@link StringValue} and a {@link StringValueStream}.
+ */
+class CompareStringStreamFunction extends AbstractBooleanValueStream {
+ private final StringValue baseExpr;
+ private final StringValueStream compExpr;
+ private final CompResultFunction comp;
+ private final String name;
+ private final String funcStr;
+ private final ExpressionType funcType;
+
+ public CompareStringStreamFunction(String name, StringValue baseExpr, StringValueStream compExpr, CompResultFunction comp) throws SolrException {
+ this.name = name;
+ this.baseExpr = baseExpr;
+ this.compExpr = compExpr;
+ this.comp = comp;
+ this.funcStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,baseExpr,compExpr);
+ }
+
+ @Override
+ public void streamBooleans(BooleanConsumer cons) {
+ String baseValue = baseExpr.toString();
+ if (baseExpr.exists()) {
+ compExpr.streamStrings(compValue -> cons.accept(comp.apply(baseValue.compareTo(compValue))));
+ }
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return funcStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+/**
+ * An equal function for two {@link BooleanValue}s.
+ */
+class BooleanValueEqualFunction extends AbstractBooleanValue {
+ private final BooleanValue exprA;
+ private final BooleanValue exprB;
+ public static final String name = CompareFunction.EqualFunction.name;
+ private final String funcStr;
+ private final ExpressionType funcType;
+
+ public BooleanValueEqualFunction(BooleanValue exprA, BooleanValue exprB) {
+ this.exprA = exprA;
+ this.exprB = exprB;
+ this.funcStr = AnalyticsValueStream.createExpressionString(name,exprA,exprB);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,exprA,exprB);
+ }
+
+ private boolean exists = false;
+ @Override
+ public boolean getBoolean() {
+ boolean valueA = exprA.getBoolean();
+ boolean valueB = exprB.getBoolean();
+ exists = exprA.exists() && exprB.exists();
+ return exists ? valueA == valueB : false;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return funcStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+/**
+ * An equal function for a {@link BooleanValue} and a {@link BooleanValueStream}.
+ */
+class BooleanStreamEqualFunction extends AbstractBooleanValueStream {
+ private final BooleanValue baseExpr;
+ private final BooleanValueStream compExpr;
+ public static final String name = CompareFunction.EqualFunction.name;
+ private final String funcStr;
+ private final ExpressionType funcType;
+
+ public BooleanStreamEqualFunction(BooleanValue baseExpr, BooleanValueStream compExpr) throws SolrException {
+ this.baseExpr = baseExpr;
+ this.compExpr = compExpr;
+ this.funcStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,baseExpr,compExpr);
+ }
+
+ @Override
+ public void streamBooleans(BooleanConsumer cons) {
+ boolean baseValue = baseExpr.getBoolean();
+ if (baseExpr.exists()) {
+ compExpr.streamBooleans(compValue -> cons.accept(baseValue == compValue));
+ }
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return funcStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+/**
+ * A catch-all equal function for two {@link AnalyticsValue}s.
+ */
+class ValueEqualFunction extends AbstractBooleanValue {
+ private final AnalyticsValue exprA;
+ private final AnalyticsValue exprB;
+ public static final String name = CompareFunction.EqualFunction.name;
+ private final String funcStr;
+ private final ExpressionType funcType;
+
+ public ValueEqualFunction(AnalyticsValue exprA, AnalyticsValue exprB) {
+ this.exprA = exprA;
+ this.exprB = exprB;
+ this.funcStr = AnalyticsValueStream.createExpressionString(name,exprA,exprB);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,exprA,exprB);
+ }
+
+ private boolean exists = false;
+ @Override
+ public boolean getBoolean() {
+ Object valueA = exprA.getObject();
+ Object valueB = exprB.getObject();
+ exists = exprA.exists() && exprB.exists();
+ return exists ? valueA.equals(valueB) : false;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return funcStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+/**
+ * A catch-all equal function for an {@link AnalyticsValue} and an {@link AnalyticsValueStream}.
+ */
+class StreamEqualFunction extends AbstractBooleanValueStream {
+ private final AnalyticsValue baseExpr;
+ private final AnalyticsValueStream compExpr;
+ public static final String name = CompareFunction.EqualFunction.name;
+ private final String funcStr;
+ private final ExpressionType funcType;
+
+ public StreamEqualFunction(AnalyticsValue baseExpr, AnalyticsValueStream compExpr) throws SolrException {
+ this.baseExpr = baseExpr;
+ this.compExpr = compExpr;
+ this.funcStr = AnalyticsValueStream.createExpressionString(name,baseExpr,compExpr);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(funcStr,baseExpr,compExpr);
+ }
+
+ @Override
+ public void streamBooleans(BooleanConsumer cons) {
+ Object baseValue = baseExpr.getObject();
+ if (baseExpr.exists()) {
+ compExpr.streamObjects(compValue -> cons.accept(baseValue.equals(compValue)));
+ }
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return funcStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ConcatFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ConcatFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ConcatFunction.java
new file mode 100644
index 0000000..e54e8c5
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/ConcatFunction.java
@@ -0,0 +1,78 @@
+/*
+ * 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.solr.analytics.function.mapping;
+
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.constant.ConstantStringValue;
+
+/**
+ * A concatenation mapping function, combining the string values of the given parameters. (At least 1 parameter is required)
+ * <p>
+ * Multiple comparable {@link StringValue}s are passed in and a {@link StringValue} representing the concatenation of all values is returned.
+ */
+public class ConcatFunction {
+ public static final String name = "concat";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length == 0) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires parameters.");
+ }
+ else if (params.length == 1 && params[0] instanceof StringValue) {
+ return params[0];
+ }
+ StringValue[] castedParams = new StringValue[params.length];
+ for (int i = 0; i < params.length; i++) {
+ if (params[i] instanceof StringValue) {
+ castedParams[i] = (StringValue) params[i];
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that all parameters be single-valued and convertible to string values.");
+ }
+ }
+ return LambdaFunction.createStringLambdaFunction(name, (a,b) -> a+b, castedParams, false);
+ });
+
+ /**
+ * A concatenation mapping function, combining the string values of the given parameters with a given separating string.
+ * <br>
+ * Multiple comparable {@link StringValue}s are passed in and a {@link StringValue} representing the separated concatenation of all values is returned.
+ * <p>
+ * The first parameter must be a constant string (e.g. ",").
+ * The remaining parameters are the {@link StringValue} expressions to concatenate. (At least 1 expression is required)
+ */
+ public static class ConcatSeparatedFunction {
+ public static final String name = "concatsep";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length < 2) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 2 parameters.");
+ } else if (!(params[0] instanceof ConstantStringValue)) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that the first parameter to be a constant string.");
+ }
+ final String sep = ((ConstantStringValue)params[0]).getString();
+ StringValue[] castedParams = new StringValue[params.length - 1];
+ for (int i = 0; i < castedParams.length; i++) {
+ if (params[i + 1] instanceof StringValue) {
+ castedParams[i] = (StringValue) params[i + 1];
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires that all non-separator parameters be single-valued and convertible to string values.");
+ }
+ }
+ return LambdaFunction.createStringLambdaFunction(name, (a,b) -> a + sep + b, castedParams, false);
+ });
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateMathFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateMathFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateMathFunction.java
new file mode 100644
index 0000000..9901625
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateMathFunction.java
@@ -0,0 +1,156 @@
+/*
+ * 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.solr.analytics.function.mapping;
+
+import java.util.Date;
+import java.util.function.Consumer;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DateValueStream.AbstractDateValueStream;
+import org.apache.solr.analytics.value.constant.ConstantStringValue;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.util.DateMathParser;
+
+/**
+ * A mapping function that computes date math.
+ * <p>
+ * The first parameter is the {@link DateValue} or {@link DateValueStream} to compute date math on. (Required)
+ * <br>
+ * The trailing parameters must be constant date math strings (e.g. "+1DAY"). (At least 1 required)
+ */
+public class DateMathFunction {
+ public static final String name = "date_math";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length < 2) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires at least 2 paramaters, " + params.length + " found.");
+ }
+ StringBuilder mathParam = new StringBuilder();
+ for (int i = 1; i < params.length; ++i) {
+ if (params[i] instanceof ConstantStringValue) {
+ mathParam.append(((ConstantStringValue) params[i]).getString());
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires all math parameters to be a constant strings.");
+ }
+ }
+ if (params[0] instanceof DateValue) {
+ return new DateMathValueFunction((DateValue)params[0], new ConstantStringValue(mathParam.toString()));
+ } else if (params[0] instanceof DateValueStream) {
+ return new DateMathStreamFunction((DateValueStream)params[0], new ConstantStringValue(mathParam.toString()));
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a date as the first parameter.");
+ }
+ });
+}
+/**
+ * DateMath function that supports {@link DateValue}s.
+ */
+class DateMathValueFunction extends AbstractDateValue {
+ private final DateValue dateParam;
+ private final String mathParam;
+ DateMathParser parser = new DateMathParser();
+ public static final String name = DateMathFunction.name;
+ private final String exprStr;
+ private final ExpressionType funcType;
+
+ public DateMathValueFunction(DateValue dateParam, ConstantStringValue mathParam) throws SolrException {
+ this.dateParam = dateParam;
+ this.mathParam = "NOW" + mathParam.getString();
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,dateParam,mathParam);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,dateParam);
+ }
+
+ private boolean exists = false;
+
+ @Override
+ public long getLong() {
+ Date date = getDate();
+ return (date == null) ? 0 : date.getTime();
+ }
+ @Override
+ public Date getDate() {
+ Date date = dateParam.getDate();
+ if (dateParam.exists()) {
+ exists = true;
+ return DateMathParser.parseMath(date,mathParam);
+ } else {
+ exists = false;
+ return null;
+ }
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+/**
+ * DateMath function that supports {@link DateValueStream}s.
+ */
+class DateMathStreamFunction extends AbstractDateValueStream {
+ private final DateValueStream dateParam;
+ private final String mathParam;
+ public static final String name = DateMathFunction.name;
+ private final String exprStr;
+ private final ExpressionType funcType;
+
+ public DateMathStreamFunction(DateValueStream dateParam, ConstantStringValue mathParam) throws SolrException {
+ this.dateParam = dateParam;
+ this.mathParam = "NOW" + mathParam.getString();
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,dateParam,mathParam);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,dateParam);
+ }
+
+ @Override
+ public void streamLongs(LongConsumer cons) {
+ streamDates(value -> cons.accept(value.getTime()));
+ }
+ @Override
+ public void streamDates(Consumer<Date> cons) {
+ dateParam.streamDates(value -> cons.accept(DateMathParser.parseMath(value, mathParam)));
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateParseFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateParseFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateParseFunction.java
new file mode 100644
index 0000000..5929b88
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DateParseFunction.java
@@ -0,0 +1,210 @@
+/*
+ * 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.solr.analytics.function.mapping;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+import java.util.function.LongConsumer;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DateValue;
+import org.apache.solr.analytics.value.DateValueStream;
+import org.apache.solr.analytics.value.LongValue;
+import org.apache.solr.analytics.value.LongValueStream;
+import org.apache.solr.analytics.value.StringValue;
+import org.apache.solr.analytics.value.StringValueStream;
+import org.apache.solr.analytics.value.DateValue.AbstractDateValue;
+import org.apache.solr.analytics.value.DateValueStream.AbstractDateValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A mapping function that converts long or string representations of dates to actual date objects.
+ * <p>
+ * The only parameter is the {@link LongValue}, {@link LongValueStream}, {@link DateValue}, or {@link DateValueStream} to convert. (Required)
+ */
+public class DateParseFunction {
+ public static final String name = "date";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 1) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 1 paramater, " + params.length + " found.");
+ }
+ if (params[0] instanceof LongValue) {
+ return new LongToDateParseFunction((LongValue)params[0]);
+ }
+ else if (params[0] instanceof LongValueStream) {
+ return new LongStreamToDateParseFunction((LongValueStream)params[0]);
+ }
+ else if (params[0] instanceof StringValue) {
+ return new StringToDateParseFunction((StringValue)params[0]);
+ }
+ else if (params[0] instanceof StringValueStream) {
+ return new StringStreamToDateParseFunction((StringValueStream)params[0]);
+ }
+ else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires a string or long parameter. " +
+ "Incorrect parameter: "+params[0].getExpressionStr());
+ }
+ });
+}
+class LongToDateParseFunction extends AbstractDateValue {
+ private final LongValue param;
+ public static final String name = DateParseFunction.name;
+ private final String exprStr;
+ private final ExpressionType funcType;
+
+ public LongToDateParseFunction(LongValue param) throws SolrException {
+ this.param = param;
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+ }
+
+ @Override
+ public long getLong() {
+ return param.getLong();
+ }
+ @Override
+ public boolean exists() {
+ return param.exists();
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+class LongStreamToDateParseFunction extends AbstractDateValueStream {
+ private final LongValueStream param;
+ public static final String name = DateParseFunction.name;
+ private final String exprStr;
+ private final ExpressionType funcType;
+ public static final DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS", Locale.ROOT);
+
+ public LongStreamToDateParseFunction(LongValueStream param) throws SolrException {
+ this.param = param;
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+ }
+
+ @Override
+ public void streamLongs(LongConsumer cons) {
+ param.streamLongs(cons);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+class StringToDateParseFunction extends AbstractDateValue {
+ private final StringValue param;
+ public static final String name = DateParseFunction.name;
+ private final String exprStr;
+ private final ExpressionType funcType;
+ public static final DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS", Locale.ROOT);
+
+ public StringToDateParseFunction(StringValue param) throws SolrException {
+ this.param = param;
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+ }
+
+ private boolean exists = false;
+ @Override
+ public long getLong() {
+ long value = 0;
+ try {
+ value = formatter.parse(param.toString()).getTime();
+ exists = param.exists();
+ } catch (ParseException e) {
+ exists = false;
+ }
+ return value;
+ }
+ @Override
+ public boolean exists() {
+ return exists;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
+class StringStreamToDateParseFunction extends AbstractDateValueStream {
+ private final StringValueStream param;
+ public static final String name = DateParseFunction.name;
+ private final String exprStr;
+ private final ExpressionType funcType;
+ public static final DateFormat formatter = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss.SSS", Locale.ROOT);
+
+ public StringStreamToDateParseFunction(StringValueStream param) throws SolrException {
+ this.param = param;
+ this.exprStr = AnalyticsValueStream.createExpressionString(name,param);
+ this.funcType = AnalyticsValueStream.determineMappingPhase(exprStr,param);
+ }
+
+ @Override
+ public void streamLongs(LongConsumer cons) {
+ param.streamStrings(value -> {
+ try {
+ cons.accept(formatter.parse(value).getTime());
+ } catch (ParseException e) {
+ }
+ });
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+ @Override
+ public String getExpressionStr() {
+ return exprStr;
+ }
+ @Override
+ public ExpressionType getExpressionType() {
+ return funcType;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/d5963beb/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DivideFunction.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DivideFunction.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DivideFunction.java
new file mode 100644
index 0000000..e644812
--- /dev/null
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/function/mapping/DivideFunction.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.solr.analytics.function.mapping;
+
+import org.apache.solr.analytics.ExpressionFactory.CreatorFunction;
+import org.apache.solr.analytics.value.AnalyticsValueStream;
+import org.apache.solr.analytics.value.DoubleValue;
+import org.apache.solr.analytics.value.DoubleValueStream;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
+
+/**
+ * A division mapping function. No checking on divisor value is done. An error will occur if a zero divisor is used.
+ * <p>
+ * Uses:
+ * <ul>
+ * <li>If two numeric Values are passed in, a {@link DoubleValue} representing the divison of the two values is returned.
+ * <li>If a numeric ValueStream and a numeric Value are passed in, a {@link DoubleValueStream} representing the division of
+ * the Value and each of the values of the ValueStream for a document is returned.
+ * (Or the other way, since the Value and ValueStream can be used in either order)
+ * </ul>
+ */
+public class DivideFunction {
+ public static final String name = "div";
+ public static final CreatorFunction creatorFunction = (params -> {
+ if (params.length != 2) {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires 2 paramaters, " + params.length + " found.");
+ }
+ AnalyticsValueStream param1 = params[0];
+ AnalyticsValueStream param2 = params[1];
+ if (param1 instanceof DoubleValueStream && param2 instanceof DoubleValueStream) {
+ return LambdaFunction.createDoubleLambdaFunction(name, (a,b) -> a/b, (DoubleValueStream)param1, (DoubleValueStream)param2);
+ } else {
+ throw new SolrException(ErrorCode.BAD_REQUEST,"The "+name+" function requires numeric parameters.");
+ }
+ });
+}
\ No newline at end of file