/* * Copyright 2015 by Thomas Lottermann * * 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 notaql.evaluation; import notaql.NotaQL; import notaql.datamodel.ComplexValue; import notaql.datamodel.ObjectValue; import notaql.datamodel.Step; import notaql.datamodel.Value; import notaql.datamodel.fixation.Fixation; import notaql.model.Transformation; import notaql.model.path.IgnoredIdStep; import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.java.JavaRDD; import org.apache.spark.api.java.JavaSparkContext; import scala.Tuple2; import java.io.Serializable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.logging.Logger; /** * This is the generic transformation framework for NotaQL. * * It builds on Spark. */ public class SparkTransformationEvaluator implements Serializable { private static final long serialVersionUID = 1118170317689014276L; private Transformation transformation; private final static Logger logger = Logger.getLogger(SparkTransformationEvaluator.class.getName()); public SparkTransformationEvaluator(Transformation transformation) { this.transformation = transformation; } /** * The starting point of the evaluation of a NotaQL transformation. * * @param values * @return */ public JavaRDD<ObjectValue> process(JavaRDD<Value> values) { // map final JavaRDD<ValueEvaluationResult> evaluated = values .flatMap(v -> EvaluatorService.getInstance() .evaluate(transformation.getExpression(), new Fixation((ObjectValue) v))); // Aggregate - recursively go down the tree described by the transformation final JavaPairRDD<String, Value> reduced = evaluated.mapToPair(r -> new Tuple2<>(r.getValue().groupKey(), r.getValue())) .aggregateByKey( EvaluatorService.getInstance().createIdentity(transformation.getExpression()), (a, b) -> EvaluatorService.getInstance().reduce(transformation.getExpression(), a, b), (a, b) -> EvaluatorService.getInstance().reduce(transformation.getExpression(), a, b) ); // finalize all values return reduced.map(t -> (ObjectValue) EvaluatorService.getInstance().finalize(transformation.getExpression(), t._2)); } /** * Drops ignored values (i.e. OUT._) * @param c * @param <T> * @return */ @SuppressWarnings("unchecked") private <T extends ComplexValue> T clearIgnored(T c) { for (Iterator<Map.Entry<Step, Value>> iterator = c.toMap().entrySet().iterator(); iterator.hasNext(); ) { final Map.Entry<Step, Value> next = iterator.next(); if (next.getKey() instanceof IgnoredIdStep.IgnoredStep) iterator.remove(); if (next.getValue() instanceof ComplexValue<?>) clearIgnored((ComplexValue<?>) next.getValue()); } return c; } public static class SparkFactory { private static JavaSparkContext sc = null; private SparkFactory() { } public static JavaSparkContext getSparkContext() { if (sc != null) return sc; sc = new JavaSparkContext(NotaQL.prop.getProperty("spark_master", "local"), "NotaQL"); return sc; } } }