com.cloudera.data.filesystem.PartitionExpression.java Source code

Java tutorial

Introduction

Here is the source code for com.cloudera.data.filesystem.PartitionExpression.java

Source

/**
 * Copyright 2013 Cloudera Inc.
 *
 * 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 com.cloudera.data.filesystem;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.jexl2.Expression;
import org.apache.commons.jexl2.JexlEngine;

import com.cloudera.data.FieldPartitioner;
import com.cloudera.data.PartitionStrategy;
import com.cloudera.data.partition.HashFieldPartitioner;
import com.cloudera.data.partition.IdentityFieldPartitioner;
import com.cloudera.data.partition.PartitionFunctions;
import com.cloudera.data.partition.RangeFieldPartitioner;
import com.google.common.base.Objects;

class PartitionExpression {

    private JexlEngine engine;
    private Expression expression;
    private boolean isStrict;

    public PartitionExpression(String expression, boolean isStrict) {
        this.engine = new JexlEngine();
        Map<String, Object> fns = new HashMap<String, Object>();
        fns.put(null, PartitionFunctions.class);
        this.engine.setFunctions(fns);
        this.engine.setStrict(true);
        this.engine.setSilent(false);
        this.engine.setCache(10);
        this.expression = engine.createExpression(expression);
        this.isStrict = isStrict;
    }

    public PartitionStrategy evaluate() {
        Object object = expression.evaluate(null);
        if (object instanceof FieldPartitioner) {
            return new PartitionStrategy((FieldPartitioner) object);
        } else if (object instanceof Object[]) {
            /*
             * JEXL doesn't recognize that [hash(...), range(...)] is an array of
             * FieldPartitioner. Instead, it thinks it's Object[].
             */
            return new PartitionStrategy((FieldPartitioner[]) object);
        } else {
            throw new IllegalArgumentException(
                    "Partition expression did not produce FieldPartitioner result (or array) for value:" + object);
        }
    }

    /**
     * Convert a PartitionStrategy into a serialized expression. This can be used
     * to set a PartitionStrategy in an Avro property if the PartitionStrategy is
     * passed as an object.
     */
    public static String toExpression(PartitionStrategy partitionStrategy) {
        List<FieldPartitioner> fieldPartitioners = partitionStrategy.getFieldPartitioners();
        if (fieldPartitioners.size() == 1) {
            return toExpression(fieldPartitioners.get(0));
        }
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (FieldPartitioner fieldPartitioner : fieldPartitioners) {
            if (sb.length() > 1) {
                sb.append(", ");
            }
            sb.append(toExpression(fieldPartitioner));
        }
        sb.append("]");
        return sb.toString();
    }

    private static String toExpression(FieldPartitioner fieldPartitioner) {
        // TODO: add other strategies
        if (fieldPartitioner instanceof HashFieldPartitioner) {
            return String.format("hash(\"%s\", %s)", fieldPartitioner.getName(), fieldPartitioner.getCardinality());
        } else if (fieldPartitioner instanceof IdentityFieldPartitioner) {
            return String.format("identity(\"%s\", %s)", fieldPartitioner.getName(),
                    fieldPartitioner.getCardinality());
        } else if (fieldPartitioner instanceof RangeFieldPartitioner) {
            List<Comparable<?>> upperBounds = ((RangeFieldPartitioner) fieldPartitioner).getUpperBounds();

            StringBuilder builder = new StringBuilder();

            for (Comparable<?> bound : upperBounds) {
                if (builder.length() > 0) {
                    builder.append(", ");
                }

                if (bound instanceof String) {
                    builder.append("\"").append(bound).append("\"");
                } else {
                    builder.append(bound);
                }
            }

            return String.format("range(\"%s\", %s", fieldPartitioner.getName(), builder.toString());
        }

        throw new IllegalArgumentException("Unrecognized PartitionStrategy: " + fieldPartitioner);
    }

    @Override
    public String toString() {
        return Objects.toStringHelper(this).add("expression", expression).add("isStrict", isStrict)
                .add("engine", engine).toString();
    }

}