/* * Copyright (C) 2015 Stratio (http://stratio.com) * * 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.stratio.morphlines.commons; import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.Collections; import org.kitesdk.morphline.api.Command; import org.kitesdk.morphline.api.CommandBuilder; import org.kitesdk.morphline.api.MorphlineContext; import org.kitesdk.morphline.api.Record; import org.kitesdk.morphline.base.AbstractCommand; import com.typesafe.config.Config; //@formatter:off /** * <p>The relationalFilter command discard records that are not accomplish a relational condition. <p> * <ul> * <li><em>field</em>: Name of field which value will be compared.</li> * <li><em>operator</em>: Operator. Possible values: <, <=, >, >=, ==, <>.</li> * <li><em>reference</em>: Number to compare to.</li> * <li><em>class</em>: Class to cast reference number.</li> * </ul> * <code> * Example: * { * relationalFilter { field : field1 operator : > reference : 100.0 class : java.lang.Double } * } * </code> * */ //@formatter:on public class RelationalFilterBuilder implements CommandBuilder { private static final String COMMAND_NAME = "relationalFilter"; private static final String CONF_CLASS = "class"; private static final String CONF_FIELD = "field"; private static final String CONF_REFERENCE= "reference"; private static final String CONF_OPERATOR = "operator"; private static final String DEFAULT_CLASS = "java.lang.Integer"; private static final String DEFAULT_OPERATOR = "+"; public Collection<String> getNames() { return Collections.singleton(COMMAND_NAME); } public Command build(Config config, Command parent, Command child, MorphlineContext context) { return new RelationalFilter(this, config, parent, child, context); } private static final class RelationalFilter extends AbstractCommand { private String classname; private String field; private String reference; private String operator; protected RelationalFilter(CommandBuilder builder, Config config, Command parent, Command child, MorphlineContext context) { super(builder, config, parent, child, context); classname = getConfigs().getString(config, CONF_CLASS, DEFAULT_CLASS); field = getConfigs().getString(config, CONF_FIELD); reference = getConfigs().getString(config, CONF_REFERENCE); operator = getConfigs().getString(config, CONF_OPERATOR, DEFAULT_OPERATOR); } @Override protected boolean doProcess(Record record) { Object current = record.getFirstValue(field); Object refObject = null; try { refObject = Class.forName(classname).getConstructor(String.class).newInstance(reference); } catch (InstantiationException e) { //TODO: Use proper logging e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } boolean result = checkCondition(current, refObject); return (result) ? super.doProcess(record) : true; } @SuppressWarnings({ "unchecked", "rawtypes" }) private boolean checkCondition(Object current, Object refObject){ boolean result = false; int comparationResult = compare(current, refObject); if (">".equals(operator)) { result = comparationResult > 0; } else if (">=".equals(operator)) { result = comparationResult >= 0; } else if ("<".equals(operator)) { result = comparationResult < 0; } else if ("<=".equals(operator)) { result = comparationResult <= 0; } else if ("==".equals(operator)) { result = comparationResult == 0; } else if ("<>".equals(operator)) { result = comparationResult != 0; } else { //TODO: Use proper logging } return result; } private int compare(Object current, Object ref){ return new Double(String.valueOf(current)).compareTo(new Double(String.valueOf(ref))); } } }