package org.exist.xquery.functions.inspect;
import org.exist.dom.QName;
import org.exist.dom.memtree.MemTreeBuilder;
import org.exist.xquery.*;
import org.exist.xquery.value.*;
import org.exist.xquery.xqdoc.XQDocHelper;
import org.xml.sax.helpers.AttributesImpl;
import java.util.Map;
public class InspectModule extends BasicFunction {
public final static FunctionSignature FNS_INSPECT_MODULE = new FunctionSignature(
new QName("inspect-module", InspectionModule.NAMESPACE_URI, InspectionModule.PREFIX),
"Compiles a library module from source (without importing it) and returns an XML fragment describing the " +
"module and the functions/variables contained in it.",
new SequenceType[]{
new FunctionParameterSequenceType("location", Type.ANY_URI, Cardinality.EXACTLY_ONE,
"The location URI of the module to inspect"),
},
new FunctionReturnSequenceType(Type.ELEMENT, Cardinality.ZERO_OR_ONE,
"An XML fragment describing the module and all functions contained in it.")
);
public final static FunctionSignature FNS_INSPECT_MODULE_URI = new FunctionSignature(
new QName("inspect-module-uri", InspectionModule.NAMESPACE_URI, InspectionModule.PREFIX),
"Returns an XML fragment describing the " +
"library module identified by the given namespace URI and the functions/variables contained in it.",
new SequenceType[]{
new FunctionParameterSequenceType("uri", Type.ANY_URI, Cardinality.EXACTLY_ONE,
"The namespace URI of the module to inspect"),
},
new FunctionReturnSequenceType(Type.ELEMENT, Cardinality.ZERO_OR_ONE,
"An XML fragment describing the module and all functions contained in it.")
);
private static final QName MODULE_QNAME = new QName("module");
private static final QName VARIABLE_QNAME = new QName("variable");
public InspectModule(final XQueryContext context, final FunctionSignature signature) {
super(context, signature);
}
@Override
public Sequence eval(final Sequence[] args, final Sequence contextSequence) throws XPathException {
final XQueryContext tempContext = new XQueryContext(context.getBroker().getBrokerPool());
tempContext.setModuleLoadPath(context.getModuleLoadPath());
final Module module;
if (isCalledAs("inspect-module")) {
module = tempContext.importModule(null, null, args[0].getStringValue());
} else {
module = tempContext.importModule(args[0].getStringValue(), null, null);
}
if (module == null) {
return Sequence.EMPTY_SEQUENCE;
}
final MemTreeBuilder builder = context.getDocumentBuilder();
final AttributesImpl attribs = new AttributesImpl();
attribs.addAttribute("", "uri", "uri", "CDATA", module.getNamespaceURI());
attribs.addAttribute("", "prefix", "prefix", "CDATA", module.getDefaultPrefix());
if (module.isInternalModule()) {
attribs.addAttribute("", "location", "location", "CDATA", "java:" + module.getClass().getName());
} else if (isCalledAs("inspect-module")) {
attribs.addAttribute("", "location", "location", "CDATA", args[0].getStringValue());
}
final int nodeNr = builder.startElement(MODULE_QNAME, attribs);
if (!module.isInternalModule()) {
XQDocHelper.parse((ExternalModule) module);
}
if (module.getDescription() != null) {
builder.startElement(InspectFunction.DESCRIPTION_QNAME, null);
builder.characters(module.getDescription());
builder.endElement();
}
if (!module.isInternalModule()) {
final ExternalModule externalModule = (ExternalModule) module;
if (externalModule.getMetadata() != null) {
for (final Map.Entry<String, String> entry : externalModule.getMetadata().entrySet()) {
builder.startElement(new QName(entry.getKey()), null);
builder.characters(entry.getValue());
builder.endElement();
}
}
// variables
for (final VariableDeclaration var : externalModule.getVariableDeclarations()) {
attribs.clear();
attribs.addAttribute("", "name", "name", "CDATA", var.getName().toString());
final SequenceType type = var.getSequenceType();
if (type != null) {
attribs.addAttribute("", "type", "type", "CDATA", Type.getTypeName(type.getPrimaryType()));
attribs.addAttribute("", "cardinality", "cardinality", "CDATA", Cardinality.getDescription(type.getCardinality()));
}
builder.startElement(VARIABLE_QNAME, attribs);
builder.endElement();
}
}
// functions
for (final FunctionSignature sig : module.listFunctions()) {
if (!sig.isPrivate()) {
UserDefinedFunction func = null;
if (!module.isInternalModule()) {
func = ((ExternalModule) module).getFunction(sig.getName(), sig.getArgumentCount(), null);
}
InspectFunction.generateDocs(sig, func, builder);
}
}
builder.endElement();
return builder.getDocument().getNode(nodeNr);
}
}