blob: 5b758ca703ae264cc4a449fa40aa1f176a111f44 [file] [log] [blame]
/*
* 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.
*/
#include <xalanc/Include/PlatformDefinitions.hpp>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <xercesc/util/PlatformUtils.hpp>
#include <xalanc/XalanTransformer/XalanTransformer.hpp>
#include <xalanc/XPath/Function.hpp>
#include <xalanc/XPath/XObjectFactory.hpp>
using xalanc::Function;
using xalanc::Locator;
using xalanc::XPathExecutionContext;
using xalanc::XalanDOMString;
using xalanc::XalanNode;
using xalanc::XObjectPtr;
using xalanc::MemoryManager;
using xalanc::XalanCopyConstruct;
// This class defines a function that will return the square root
// of its argument.
class FunctionSquareRoot : public Function
{
public:
/**
* Execute an XPath function object. The function must return a valid
* object. Extension functions should override this version of execute(),
* rather than one of the other calls designed for a specific number of
* arguments.
*
* @param executionContext executing context
* @param context current context node
* @param args vector of pointers to XObject arguments
* @param locator Locator for the XPath expression that contains the function call
* @return pointer to the result XObject
*/
virtual XObjectPtr
execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
XPathExecutionContext::GetAndReleaseCachedString theGuard(executionContext);
generalError(executionContext, context, locator);
}
assert(args[0].null() == false);
using std::sqrt;
#endif
return executionContext.getXObjectFactory().createNumber(sqrt(args[0]->num(executionContext)));
}
using Function::execute;
/**
* Create a copy of the function object.
*
* @return pointer to the new object
*/
virtual FunctionSquareRoot*
clone(MemoryManager& theManager) const
{
return XalanCopyConstruct(theManager, *this);
}
protected:
/**
* Get the error message to report when
* the function is called with the wrong
* number of arguments.
*
* @return function error message
*/
const XalanDOMString&
getError(XalanDOMString& theResult) const
{
theResult.assign("The square-root() function accepts one argument!");
return theResult;
}
private:
// Not implemented...
FunctionSquareRoot&
operator=(const FunctionSquareRoot&);
bool
operator==(const FunctionSquareRoot&) const;
};
// This class defines a function that will return the cube
// of its argument.
class FunctionCube : public Function
{
public:
/**
* Execute an XPath function object. The function must return a valid
* object. Extension functions should override this version of execute(),
* rather than one of the other calls designed for a specific number of
* arguments.
*
* @param executionContext executing context
* @param context current context node
* @param args vector of pointers to XObject arguments
* @param locator Locator for the XPath expression that contains the function call
* @return pointer to the result XObject
*/
virtual XObjectPtr
execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.size() != 1)
{
XPathExecutionContext::GetAndReleaseCachedString theGuard(executionContext);
generalError(executionContext, context, locator);
}
assert(args[0].null() == false);
using std::pow;
return executionContext.getXObjectFactory().createNumber(pow(args[0]->num(executionContext), 3));
}
using Function::execute;
/**
* Create a copy of the function object.
*
* @return pointer to the new object
*/
virtual FunctionCube*
clone(MemoryManager& theManager) const
{
return XalanCopyConstruct(theManager, *this);
}
protected:
/**
* Get the error message to report when
* the function is called with the wrong
* number of arguments.
*
* @return function error message
*/
const XalanDOMString&
getError(XalanDOMString& theResult) const
{
theResult.assign("The cube() function accepts one argument!");
return theResult;
}
private:
// Not implemented...
FunctionCube&
operator=(const FunctionCube&);
bool
operator==(const FunctionCube&) const;
};
// This class defines a function that runs the C function
// asctime() using the current system time.
class FunctionAsctime : public Function
{
public:
/**
* Execute an XPath function object. The function must return a valid
* object. Extension functions should override this version of execute(),
* rather than one of the other calls designed for a specific number of
* arguments.
*
* @param executionContext executing context
* @param context current context node
* @param args vector of pointers to XObject arguments
* @param locator Locator for the XPath expression that contains the function call
* @return pointer to the result XObject
*/
virtual XObjectPtr
execute(
XPathExecutionContext& executionContext,
XalanNode* context,
const XObjectArgVectorType& args,
const Locator* locator) const
{
if (args.empty() == false)
{
generalError(executionContext, context, locator);
}
using std::time;
using std::time_t;
using std::localtime;
using std::asctime;
using std::strlen;
time_t theTime;
time(&theTime);
char* const theTimeString = asctime(localtime(&theTime));
assert(theTimeString != 0);
// The resulting string has a newline character at the end,
// so get rid of it.
theTimeString[strlen(theTimeString) - 1] = '\0';
return executionContext.getXObjectFactory().createString(XalanDOMString(theTimeString));
}
using Function::execute;
/**
* Create a copy of the function object.
*
* @return pointer to the new object
*/
virtual FunctionAsctime*
clone(MemoryManager& theManager) const
{
return XalanCopyConstruct(theManager, *this);
}
protected:
/**
* Get the error message to report when
* the function is called with the wrong
* number of arguments.
*
* @return function error message
*/
const XalanDOMString&
getError(XalanDOMString& theResult) const
{
theResult.assign("The asctime() function accepts one argument!");
return theResult;
}
private:
// Not implemented...
FunctionAsctime&
operator=(const FunctionAsctime&);
bool
operator==(const FunctionAsctime&) const;
};
int
main(
int argc,
char* /* argv */[])
{
using std::cerr;
using std::endl;
int theResult = 0;
if (argc != 1)
{
cerr << "Usage: ExternalFunction"
<< endl
<< endl;
}
else
{
using xercesc::XMLPlatformUtils;
using xercesc::XMLException;
using xalanc::XalanTransformer;
// Call the static initializer for Xerces.
try
{
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch)
{
cerr << "Error during Xerces initialization. Error code was "
<< toCatch.getCode()
<< "."
<< endl;
theResult = -1;
}
if (theResult == 0)
{
// Initialize Xalan.
XalanTransformer::initialize();
{
// Create a XalanTransformer.
XalanTransformer theXalanTransformer;
// The namespace for our functions...
const XalanDOMString theNamespace("http://ExternalFunction.xalan-c++.xml.apache.org");
// Install the functions in the local space. They will only
// be installed in this instance, so no other instances
// will know about them...
theXalanTransformer.installExternalFunction(
theNamespace,
XalanDOMString("asctime"),
FunctionAsctime());
theXalanTransformer.installExternalFunction(
theNamespace,
XalanDOMString("square-root"),
FunctionSquareRoot());
theXalanTransformer.installExternalFunction(
theNamespace,
XalanDOMString("cube"),
FunctionCube());
// Do the transform.
theResult = theXalanTransformer.transform("foo.xml", "foo.xsl", "foo.out");
if(theResult != 0)
{
cerr << "ExternalFunction Error: \n" << theXalanTransformer.getLastError()
<< endl
<< endl;
}
}
// Terminate Xalan...
XalanTransformer::terminate();
}
// Terminate Xerces...
XMLPlatformUtils::Terminate();
// Clean up the ICU, if it's integrated...
XalanTransformer::ICUCleanUp();
}
return theResult;
}