001 /* 002 * Copyright (c) 2007-2015 Concurrent, Inc. All Rights Reserved. 003 * 004 * Project and contact information: http://www.cascading.org/ 005 * 006 * This file is part of the Cascading project. 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020 021 package cascading.operation.xml; 022 023 import javax.xml.parsers.DocumentBuilder; 024 import javax.xml.xpath.XPathConstants; 025 import javax.xml.xpath.XPathExpression; 026 import javax.xml.xpath.XPathExpressionException; 027 028 import cascading.flow.FlowProcess; 029 import cascading.operation.Filter; 030 import cascading.operation.FilterCall; 031 import cascading.operation.OperationException; 032 import cascading.tuple.Tuple; 033 import cascading.util.Pair; 034 import org.slf4j.Logger; 035 import org.slf4j.LoggerFactory; 036 import org.w3c.dom.Document; 037 038 /** 039 * XPathFilter will filter out a Tuple if the given XPath expression returns false. Set removeMatch to true 040 * if the filter should be reversed. 041 */ 042 public class XPathFilter extends XPathOperation implements Filter<Pair<DocumentBuilder, Tuple>> 043 { 044 /** Field LOG */ 045 private static final Logger LOG = LoggerFactory.getLogger( XPathFilter.class ); 046 047 /** Field removeMatch */ 048 private boolean removeMatch = false; 049 050 /** 051 * Constructor XPathFilter creates a new XPathFilter instance. 052 * 053 * @param namespaces of type String[][] 054 * @param path of type String 055 */ 056 public XPathFilter( String[][] namespaces, String path ) 057 { 058 super( 1, namespaces, path ); 059 } 060 061 /** 062 * Constructor XPathFilter creates a new XPathFilter instance. 063 * 064 * @param removeMatch of type boolean 065 * @param namespaces of type String[][] 066 * @param path of type String 067 */ 068 public XPathFilter( boolean removeMatch, String[][] namespaces, String path ) 069 { 070 super( 1, namespaces, path ); 071 this.removeMatch = removeMatch; 072 } 073 074 @Override 075 public boolean isRemove( FlowProcess flowProcess, FilterCall<Pair<DocumentBuilder, Tuple>> filterCall ) 076 { 077 String argument = filterCall.getArguments().getString( 0 ); 078 Document document = parseDocument( filterCall.getContext().getLhs(), argument ); 079 XPathExpression expression = getExpressions().get( 0 ); 080 081 try 082 { 083 boolean value = (Boolean) expression.evaluate( document, XPathConstants.BOOLEAN ); 084 085 LOG.debug( "xpath: {} matches: {}", paths[ 0 ], value ); 086 087 return value == removeMatch; 088 } 089 catch( XPathExpressionException exception ) 090 { 091 throw new OperationException( "could not evaluate xpath expression: " + paths[ 0 ], exception ); 092 } 093 } 094 }