Package org.exist.xquery.functions.util

Source Code of org.exist.xquery.functions.util.DescribeFunction

/*
*  eXist Open Source Native XML Database
*  Copyright (C) 2001-09 Wolfgang M. Meier
*  wolfgang@exist-db.org
*  http://exist.sourceforge.net
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*  $Id$
*/
package org.exist.xquery.functions.util;

import java.util.Iterator;

import org.apache.log4j.Logger;
import org.exist.dom.QName;
import org.exist.memtree.DocumentImpl;
import org.exist.memtree.MemTreeBuilder;
import org.exist.xquery.Annotation;
import org.exist.xquery.Cardinality;
import org.exist.xquery.Function;
import org.exist.xquery.FunctionSignature;
import org.exist.xquery.LiteralValue;
import org.exist.xquery.Module;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQueryContext;
import org.exist.xquery.functions.inspect.InspectFunction;
import org.exist.xquery.value.FunctionParameterSequenceType;
import org.exist.xquery.value.FunctionReturnSequenceType;
import org.exist.xquery.value.Item;
import org.exist.xquery.value.Sequence;
import org.exist.xquery.value.SequenceType;
import org.exist.xquery.value.Type;
import org.xml.sax.helpers.AttributesImpl;

/**
* Describe a built-in function identified by its QName.
*
* @author wolf
*/
public class DescribeFunction extends Function {
 
  protected static final Logger logger = Logger.getLogger(DescribeFunction.class);

  public final static FunctionSignature signature =
    new FunctionSignature(
      new QName("describe-function", UtilModule.NAMESPACE_URI, UtilModule.PREFIX),
      "Describes a built-in function. Returns an element describing the " +
      "function signature.",
      new SequenceType[] {
        new FunctionParameterSequenceType("function-name", Type.QNAME, Cardinality.EXACTLY_ONE, "The name of the function to get the signature of"),
      },
      new FunctionReturnSequenceType(Type.NODE, Cardinality.EXACTLY_ONE, "the signature of the function"),
            InspectFunction.SIGNATURE);
 
  private final static QName ANNOTATION_QNAME = new QName("annotation");
  private final static QName ANNOTATION_VALUE_QNAME = new QName("value");
 
  public DescribeFunction(XQueryContext context) {
    super(context, signature);
  }
 
  /* (non-Javadoc)
   * @see org.exist.xquery.Expression#eval(org.exist.dom.DocumentSet, org.exist.xquery.value.Sequence, org.exist.xquery.value.Item)
   */
  public Sequence eval(
    Sequence contextSequence,
    Item contextItem)
    throws XPathException {
   
    final String fname = getArgument(0).eval(contextSequence, contextItem).getStringValue();
    final QName qname = QName.parse(context, fname, context.getDefaultFunctionNamespace());
    final String uri = qname.getNamespaceURI();
   
    final MemTreeBuilder builder = context.getDocumentBuilder();
    final AttributesImpl attribs = new AttributesImpl();
    attribs.addAttribute("", "name", "name", "CDATA", qname.getStringValue());
    attribs.addAttribute("", "module", "module", "CDATA", uri);
    final int nodeNr = builder.startElement("", "function", "function", attribs);
   
    FunctionSignature signature;
    final Module module = context.getModule(uri);
    if(module != null) {
      final Iterator<FunctionSignature> i = module.getSignaturesForFunction(qname);
      while(i.hasNext()) {
        signature = i.next();
        writeSignature(signature, builder);
      }
    } else {
      final Iterator<FunctionSignature> i = context.getSignaturesForFunction(qname);
      while(i.hasNext()) {
        signature = i.next();
        writeSignature(signature, builder);
      }
    }
    builder.endElement();
    return ((DocumentImpl)builder.getDocument()).getNode(nodeNr);
  }

  /**
   * @param signature
   * @param builder
   * @param attribs
   * @throws XPathException if an internal error occurs
   */
  private void writeSignature(FunctionSignature signature, MemTreeBuilder builder) throws XPathException {
    final AttributesImpl attribs = new AttributesImpl();
    attribs.addAttribute("", "arguments", "arguments", "CDATA", Integer.toString(signature.getArgumentCount()));
    builder.startElement("", "prototype", "prototype", attribs);
    attribs.clear();
    builder.startElement("", "signature", "signature", attribs);
    builder.characters(signature.toString());
    builder.endElement();
   
    writeAnnotations(signature, builder);
   
    if(signature.getDescription() != null) {
      builder.startElement("", "description", "description", attribs);

            final StringBuilder description = new StringBuilder();
            description.append(signature.getDescription());

            description.append("\n\n");
           
            final SequenceType argumentTypes[] = signature.getArgumentTypes();
           
            if(argumentTypes != null && argumentTypes.length>0){

                final StringBuilder args = new StringBuilder();
                int noArgs=0;
               
                for (final SequenceType argumentType : argumentTypes) {
                    if (argumentType instanceof FunctionParameterSequenceType) {
                        noArgs++;
                        final FunctionParameterSequenceType fp
                                = (FunctionParameterSequenceType) argumentType;
                        args.append("$");
                        args.append(fp.getAttributeName());
                        args.append(" : ");
                        args.append(fp.getDescription());
                        args.append("\n");
                    }
                }

                // only add if there were good arguments
                if(noArgs>0){
                    description.append("Parameters:\n");
                    description.append(args);
                }
            }

            final SequenceType returnType = signature.getReturnType();
            if(returnType != null){            
                if (returnType instanceof FunctionReturnSequenceType) {
                    description.append("\n");
                    description.append("Returns ");
                    final FunctionReturnSequenceType fp
                                = (FunctionReturnSequenceType) returnType;
                        description.append(fp.getDescription());
                        description.append("\n");
                }

            }
           
            builder.characters(description.toString());
      builder.endElement();
    }
       
    if (signature.getDeprecated() != null) {
      builder.startElement("", "deprecated", "deprecated", attribs);
      builder.characters(signature.getDeprecated());
      builder.endElement();
    }
       
    builder.endElement();
  }

  private void writeAnnotations(FunctionSignature signature, MemTreeBuilder builder) throws XPathException {
    final AttributesImpl attribs = new AttributesImpl();
    final Annotation[] annots = signature.getAnnotations();
    if (annots != null) {
      for (final Annotation annot : annots) {
        attribs.clear();
        attribs.addAttribute(null, "name", "name", "CDATA", annot.getName().toString());
        attribs.addAttribute(null, "namespace", "namespace", "CDATA", annot.getName().getNamespaceURI());
        builder.startElement(ANNOTATION_QNAME, attribs);
        final LiteralValue[] value = annot.getValue();
        if (value != null) {
          for (final LiteralValue literal : value) {
            builder.startElement(ANNOTATION_VALUE_QNAME, null);
            builder.characters(literal.getValue().getStringValue());
            builder.endElement();
          }
        }
        builder.endElement();
      }
    }
  }
}
TOP

Related Classes of org.exist.xquery.functions.util.DescribeFunction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.