/*! ****************************************************************************** * * Pentaho Data Integration * * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.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 org.pentaho.di.trans.steps.fileinput.text; import org.pentaho.di.core.variables.VariableSpace; /** * Processor of Filters. Kind of inversion principle, and to make unit testing easier. * * @author Sven Boden */ public class TextFileFilterProcessor { /** The filters to process */ private TextFileFilter[] filters; private String[] filtersString; private boolean stopProcessing; /** * @param filters * The filters to process */ public TextFileFilterProcessor( TextFileFilter[] filters, VariableSpace space ) { this.filters = filters; this.stopProcessing = false; if ( filters.length == 0 ) { // This makes processing faster in case there are no filters. filters = null; } else { filtersString = new String[filters.length]; for ( int f = 0; f < filters.length; f++ ) { filtersString[f] = space.environmentSubstitute( filters[f].getFilterString() ); } } } public boolean doFilters( String line ) { if ( filters == null ) { return true; } boolean filterOK = true; // if false: skip this row boolean positiveMode = false; boolean positiveMatchFound = false; // If we have at least one positive filter, we enter positiveMode // Negative filters will always take precedence, meaning that the line // is skipped if one of them is found for ( int f = 0; f < filters.length && filterOK; f++ ) { TextFileFilter filter = filters[f]; String filterString = filtersString[f]; if ( filter.isFilterPositive() ) { positiveMode = true; } if ( filterString != null && filterString.length() > 0 ) { int from = filter.getFilterPosition(); if ( from >= 0 ) { int to = from + filterString.length(); if ( line.length() >= from && line.length() >= to ) { String sub = line.substring( filter.getFilterPosition(), to ); if ( sub.equalsIgnoreCase( filterString ) ) { if ( filter.isFilterPositive() ) { positiveMatchFound = true; } else { filterOK = false; // skip this one! } } } } else { // anywhere on the line int idx = line.indexOf( filterString ); if ( idx >= 0 ) { if ( filter.isFilterPositive() ) { positiveMatchFound = true; } else { filterOK = false; // skip this one! } } } if ( !filterOK ) { boolean isFilterLastLine = filter.isFilterLastLine(); if ( isFilterLastLine ) { stopProcessing = true; } } } } // Positive mode and no match found? Discard the line if ( filterOK && positiveMode && !positiveMatchFound ) { filterOK = false; } return filterOK; } /** * Was processing requested to be stopped. Can only be true when doFilters was false. * * @return == true: processing should stop, == false: processing should continue. */ public boolean isStopProcessing() { return stopProcessing; } }