    001    /*
    002     * Copyright (c) 2007-2014 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.filter;
    022
    023    import java.beans.ConstructorProperties;
    024
    025    import cascading.flow.FlowProcess;
    026    import cascading.operation.Filter;
    027    import cascading.operation.FilterCall;
    028    import cascading.tuple.Fields;
    029    import cascading.tuple.TupleEntry;
    030
    031    /**
    032     * Class Xor is a {@link Filter} class that will logically 'xor' (exclusive or) the results of the
    033     * constructor provided Filter instances.
    034     * <p/>
    035     * Logically, if {@link Filter#isRemove(cascading.flow.FlowProcess, cascading.operation.FilterCall)} returns {@code true} for all given instances,
    036     * or returns {@code false} for all given instances, this filter will return {@code false}.
    037     * <p/>
    038     * Note that Xor can only be applied to two values.
    039     *
    040     * @see And
    041     * @see Or
    042     * @see Not
    043     */
    044    public class Xor extends Logic
    045      {
    046      /**
    047       * Constructor Xor creates a new Xor instance where all Filter instances receive all arguments.
    048       *
    049       * @param filters of type Filter...
    050       */
    051      @ConstructorProperties({"filters"})
    052      public Xor( Filter... filters )
    053        {
    054        super( filters );
    055        }
    056
    057      /**
    058       * Constructor Xor creates a new Xor instance.
    059       *
    060       * @param lhsArgumentSelector of type Fields
    061       * @param lhsFilter           of type Filter
    062       * @param rhsArgumentSelector of type Fields
    063       * @param rhsFilter           of type Filter
    064       */
    065      @ConstructorProperties({"lhsArgumentsSelector", "lhsFilter", "rhsArgumentSelector", "rhsFilter"})
    066      public Xor( Fields lhsArgumentSelector, Filter lhsFilter, Fields rhsArgumentSelector, Filter rhsFilter )
    067        {
    068        super( lhsArgumentSelector, lhsFilter, rhsArgumentSelector, rhsFilter );
    069        }
    070
    071      @Override
    072      public boolean isRemove( FlowProcess flowProcess, FilterCall filterCall )
    073        {
    074        Context context = (Logic.Context) filterCall.getContext();
    075
    076        TupleEntry lhsEntry = context.argumentEntries[ 0 ];
    077        TupleEntry rhsEntry = context.argumentEntries[ 1 ];
    078
    079        lhsEntry.setTuple( filterCall.getArguments().selectTuple( argumentSelectors[ 0 ] ) );
    080        rhsEntry.setTuple( filterCall.getArguments().selectTuple( argumentSelectors[ 1 ] ) );
    081
    082        boolean lhsResult = filters[ 0 ].isRemove( flowProcess, context.calls[ 0 ] );
    083        boolean rhsResult = filters[ 1 ].isRemove( flowProcess, context.calls[ 1 ] );
    084
    085        return lhsResult != rhsResult;
    086        }
    087      }