/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */
#if !defined(FUNCTIONHASSAMENODES_HEADER_GUARD_1357924680)
#define FUNCTIONHASSAMENODES_HEADER_GUARD_1357924680



// Base header file.  Must be first.
#include <xalanc/XalanExtensions/XalanExtensionsDefinitions.hpp>



// Base class header file...
#include <xalanc/XPath/Function.hpp>



namespace XALAN_CPP_NAMESPACE {



/**
 * XPath implementation of "has-same-nodes" function for NodeSets.
 */
class XALAN_XALANEXTENSIONS_EXPORT FunctionHasSameNodes : public Function
{
public:

    typedef Function    ParentType;

    FunctionHasSameNodes();

    virtual
    ~FunctionHasSameNodes();

    // These methods are inherited from Function ...

    virtual XObjectPtr
    execute(
            XPathExecutionContext&          executionContext,
            XalanNode*                      context,
            const XObjectArgVectorType&     args,
            const Locator*                  locator) const;

    using ParentType::execute;

    virtual FunctionHasSameNodes*
    clone(MemoryManager& theManager) const;

protected:

    virtual const XalanDOMString&
    getError(XalanDOMString& theResult) const;

private:

    // Not implemented...
    FunctionHasSameNodes&
    operator=(const FunctionHasSameNodes&);

    bool
    operator==(const FunctionHasSameNodes&) const;
};



}



#endif  // FUNCTIONHASSAMENODES_HEADER_GUARD_1357924680
