Search in sources :

Example 1 with KeywordException

use of com.dexels.navajo.mapping.compiler.meta.KeywordException in project navajo by Dexels.

the class TslCompiler method includeNode.

/**
 * Resolve include nodes in the script: <include
 * script="[name of script to be included]"/>
 *
 * @param scriptPath
 * @param n
 * @param parent
 * @param deps
 * @throws MetaCompileException
 * @throws IOException
 * @throws KeywordException
 * @throws ClassNotFoundException
 * @throws Exception
 */
private final void includeNode(String scriptPath, Node n, Document parent, String tenant, List<Dependency> deps) throws UserException, ClassNotFoundException, KeywordException, IOException, MetaCompileException {
    included++;
    if (included > 1000) {
        throw new UserException(-1, "Too many included scripts!!!");
    }
    String script = ((Element) n).getAttribute("script");
    if (script == null || script.equals("")) {
        throw new UserException(-1, "No script name found in include tag (" + "missing or empty script attribute): " + n);
    }
    // Construct scriptName:
    // First try if applicationGroup specific script exists.
    String fileName = script + "_" + tenant;
    Document includeDoc = null;
    String includeFileName = fetchScriptFileName(scriptPath + "/" + fileName);
    File includedFile = null;
    if (includeFileName != null) {
        includedFile = new File(includeFileName);
        includeDoc = XMLDocumentUtils.createDocument(new FileInputStream(includeFileName), false);
    } else {
        // no tenant specific include found. Try non-tenant include instead.
        fileName = script;
        includeFileName = fetchScriptFileName(scriptPath + "/" + fileName);
        if (includeFileName != null) {
            includedFile = new File(includeFileName);
            if (includeFileName.endsWith(".ns")) {
                // It's an NS3 based script
                NS3ToNSXML nstoxml = new NS3ToNSXML();
                nstoxml.initialize();
                try {
                    String content = nstoxml.read(includeFileName);
                    String tslResult = MapMetaData.getInstance().parse(scriptPath + "/" + fileName + ".ns", nstoxml.parseNavascript(content));
                    includeDoc = XMLDocumentUtils.createDocument(new ByteArrayInputStream(tslResult.getBytes()), false);
                } catch (Exception e) {
                    throw new UserException(e.getLocalizedMessage(), e);
                }
            } else {
                // It's an XML based script
                includeDoc = XMLDocumentUtils.createDocument(new FileInputStream(includedFile), false);
            }
        }
    }
    if (includedFile == null) {
        logger.error("Could not file include file: {}", script);
        throw new UserException("Could not find include file for script: " + script);
    }
    // Add dependency.
    addDependency("dependentObjects.add( new IncludeDependency( Long.valueOf(\"" + IncludeDependency.getFileTimeStamp(includedFile) + "\"), \"" + fileName + "\"));\n", "INCLUDE" + script);
    deps.add(new IncludeDependency(IncludeDependency.getFileTimeStamp(includedFile), fileName, fileName));
    if (includeDoc.getElementsByTagName("tsl").item(0) == null) {
        // Maybe
        // it is
        // navascript??
        String tslResult = MapMetaData.getInstance().parse(scriptPath + "/" + fileName + ".xml");
        includeDoc = XMLDocumentUtils.createDocument(new ByteArrayInputStream(tslResult.getBytes()), false);
    }
    NodeList content = includeDoc.getElementsByTagName("tsl").item(0).getChildNodes();
    Node nextNode = n.getNextSibling();
    while (nextNode != null && !(nextNode instanceof Element)) {
        nextNode = nextNode.getNextSibling();
    }
    if (nextNode == null || !(nextNode instanceof Element)) {
        nextNode = n;
    }
    Node parentNode = nextNode.getParentNode();
    for (int i = 0; i < content.getLength(); i++) {
        Node child = content.item(i);
        Node imported = parent.importNode(child.cloneNode(true), true);
        parentNode.insertBefore(imported, nextNode);
    }
    parentNode.removeChild(n);
}
Also used : Element(org.w3c.dom.Element) NodeList(org.w3c.dom.NodeList) Node(org.w3c.dom.Node) Document(org.w3c.dom.Document) FileInputStream(java.io.FileInputStream) UserException(com.dexels.navajo.script.api.UserException) TransformerException(javax.xml.transform.TransformerException) MappingException(com.dexels.navajo.script.api.MappingException) TMLExpressionException(com.dexels.navajo.expression.api.TMLExpressionException) ParseException(com.dexels.navajo.parser.compiled.ParseException) KeywordException(com.dexels.navajo.mapping.compiler.meta.KeywordException) MetaCompileException(com.dexels.navajo.mapping.compiler.meta.MetaCompileException) IOException(java.io.IOException) SystemException(com.dexels.navajo.script.api.SystemException) CompilationException(com.dexels.navajo.script.api.CompilationException) ByteArrayInputStream(java.io.ByteArrayInputStream) IncludeDependency(com.dexels.navajo.mapping.compiler.meta.IncludeDependency) NS3ToNSXML(com.dexels.navajo.mapping.compiler.navascript.NS3ToNSXML) UserException(com.dexels.navajo.script.api.UserException) File(java.io.File)

Example 2 with KeywordException

use of com.dexels.navajo.mapping.compiler.meta.KeywordException in project navajo by Dexels.

the class TslCompiler method fieldNode.

@SuppressWarnings("unchecked")
public String fieldNode(int ident, Element n, String className, String objectName, List<Dependency> dependencies, String tenant) throws UserException, MappingException, ClassNotFoundException, KeywordException, IOException, MetaCompileException, ParseException {
    StringBuilder result = new StringBuilder();
    String attributeOriginal = n.getAttribute("name");
    String condition = n.getAttribute("condition");
    String attribute = null;
    String mapPath = null;
    if (attributeOriginal.indexOf('/') != -1) {
        attribute = attributeOriginal.substring(attributeOriginal.lastIndexOf('/') + 1, attributeOriginal.length());
        mapPath = attributeOriginal.substring(0, attributeOriginal.lastIndexOf('/'));
    } else {
        attribute = attributeOriginal;
    }
    if (attribute == null || attribute.equals(""))
        throw new UserException("Name attribute is required for field tags");
    condition = (condition == null) ? "" : condition;
    String totalMethodName = "set" + (attribute.charAt(0) + "").toUpperCase() + attribute.substring(1, attribute.length());
    String methodName = null;
    if (totalMethodName.indexOf('/') != -1) {
        methodName = totalMethodName.substring(totalMethodName.lastIndexOf('/') + 1, totalMethodName.length());
    } else {
        methodName = totalMethodName;
    }
    NodeList children = n.getChildNodes();
    if (!condition.equals("")) {
        result.append(printIdent(ident) + "if (Condition.evaluate(" + replaceQuotes(condition) + ", access.getInDoc(), currentMap, currentInMsg, currentParamMsg,access)) { \n");
    } else {
        result.append(printIdent(ident) + "if (true) {\n");
    }
    // Expression nodes.
    boolean isMapped = false;
    Element mapNode = null;
    int exprCount = countNodes(children, "expression");
    List<String> exprValues = new ArrayList<>();
    for (int i = 0; i < children.getLength(); i++) {
        // Has condition
        if (children.item(i).getNodeName().equals("expression")) {
            result.append(expressionNode(ident + 2, (Element) children.item(i), --exprCount, className, objectName));
            Boolean b = false;
            exprValues.add((String) getExpressionValue(((Element) children.item(i)), b)[0]);
        } else if (children.item(i).getNodeName().equals("map")) {
            isMapped = true;
            mapNode = (Element) children.item(i);
        }
    }
    if (!isMapped) {
        String castedValue = "";
        boolean isDomainObjectMapper = false;
        try {
            Class localContextClass = null;
            try {
                if (mapPath != null) {
                    localContextClass = locateContextClass(mapPath, 0);
                } else {
                    if (Version.osgiActive()) {
                        localContextClass = resolveClassUsingService(className);
                    } else {
                        localContextClass = Class.forName(className, false, loader);
                    }
                }
            } catch (Exception e) {
                throw new UserException("Could not find adapter: " + className, e);
            }
            addDependency("dependentObjects.add( new JavaDependency( -1, \"" + className + "\"));\n", "JAVA" + className);
            dependencies.add(new JavaDependency(-1, className));
            String type = null;
            try {
                type = MappingUtils.getFieldType(localContextClass, attribute);
                checkDependentFieldResource(localContextClass, attribute, exprValues, dependencies);
            } catch (Exception e) {
                isDomainObjectMapper = localContextClass.isAssignableFrom(DomainObjectMapper.class);
                if (isDomainObjectMapper) {
                    type = "java.lang.Object";
                } else {
                    throw new UserException("Could not find field: " + attribute + " in adapter " + localContextClass.getName(), e);
                }
            }
            if (type.equals("java.lang.String")) {
                castedValue = "(String) sValue";
            } else if (type.equals("com.dexels.navajo.document.types.ClockTime")) {
                castedValue = "(com.dexels.navajo.document.types.ClockTime) sValue";
            } else if (type.equals("int")) {
                castedValue = "((Integer) sValue).intValue()";
            } else if (type.equals("double")) {
                castedValue = "((Double) sValue).doubleValue()";
            } else if (type.equals("java.util.Date")) {
                castedValue = "((java.util.Date) sValue)";
            } else if (type.equals("boolean")) {
                castedValue = "((Boolean) sValue).booleanValue()";
            } else if (type.equals("float")) {
                // sValue is never float,
                // internally always Double!
                castedValue = "(new Float(sValue+\"\")).floatValue()";
            } else if (type.equals("com.dexels.navajo.document.types.Binary")) {
                castedValue = "((com.dexels.navajo.document.types.Binary) sValue)";
            } else if (type.equals("com.dexels.navajo.document.types.Money")) {
                castedValue = "((com.dexels.navajo.document.types.Money) sValue)";
            } else if (type.equals("com.dexels.navajo.document.types.Percentage")) {
                castedValue = "((com.dexels.navajo.document.types.Percentage) sValue)";
            } else if (type.equals("java.lang.Integer")) {
                castedValue = "((Integer) sValue)";
            } else if (type.equals("java.lang.Long")) {
                castedValue = "((Long) sValue)";
            } else if (type.equals("java.lang.Float")) {
                // sValue is never
                // float,
                // internally
                // always
                // Double!
                castedValue = "new Float(sValue+\"\")";
            } else if (type.equals("java.lang.Double")) {
                castedValue = "((Double) sValue)";
            } else if (type.equals("java.lang.Boolean")) {
                castedValue = "((Boolean) sValue)";
            } else if (type.equals("java.util.List")) {
                castedValue = "((List<Object>) sValue)";
            } else {
                castedValue = "sValue";
            }
        } catch (UserException e) {
            throw new UserException(-1, "Error in script: could not find mappable object: " + className, e);
        }
        if (mapPath != null) {
            if (!isDomainObjectMapper) {
                result.append(printIdent(ident + 2) + "((" + locateContextClass(mapPath, 0).getName() + ")findMapByPath(\"" + mapPath + "\"))." + methodName + "(" + castedValue + ");\n");
            } else {
                result.append(printIdent(ident + 2) + "((" + locateContextClass(mapPath, 0).getName() + ")findMapByPath(\"" + mapPath + "\")).setDomainObjectAttribute(\"" + attribute + "\"," + castedValue + ");\n");
            }
        } else {
            if (!isDomainObjectMapper) {
                result.append(printIdent(ident + 2) + objectName + "." + methodName + "(" + castedValue + ");\n");
            } else {
                // set attribute in excluded fields.
                // USE INTROSPECTION METHOD TO CALL METHOD ON PROXIED
                // DOMAIN OBJECT...
                result.append(printIdent(ident + 2) + objectName + ".setDomainObjectAttribute(\"" + attribute + "\"," + castedValue + ");\n");
            }
        }
    } else {
        // Mappable)
        if (mapNode == null) {
            throw new IllegalStateException("Unexpected null mapNode");
        }
        String ref = mapNode.getAttribute("ref");
        boolean isParam = false;
        if (ref.indexOf("[") != -1) {
            // remove square brackets...
            ref = ref.replace('[', ' ');
            ref = ref.replace(']', ' ');
            ref = ref.trim();
        }
        if (ref.startsWith("/@")) {
            // replace @ with __parms__ 'parameter'
            // message indication.
            ref = ref.replaceAll("@", "__parms__/");
            isParam = true;
        }
        String filter = mapNode.getAttribute("filter");
        filter = (filter == null) ? "" : filter;
        result.append(printIdent(ident + 2) + "// And by the way, my filter is " + filter + "\n");
        result.append(printIdent(ident + 2) + "// Map message(s) to field\n");
        String messageListName = "messages" + ident;
        result.append(printIdent(ident + 2) + "List " + messageListName + " = null;\n");
        result.append(printIdent(ident + 2) + "inSelectionRef = MappingUtils.isSelection(currentInMsg, access.getInDoc(), \"" + ref + "\");\n");
        result.append(printIdent(ident + 2) + "if (!inSelectionRef)\n");
        result.append(printIdent(ident + 4) + messageListName + " = MappingUtils.getMessageList(currentInMsg, access.getInDoc(), \"" + ref + "\", \"" + "" + "\", currentMap, currentParamMsg,access);\n");
        result.append(printIdent(ident + 2) + "else\n");
        result.append(printIdent(ident + 4) + messageListName + " = MappingUtils.getSelectedItems(currentInMsg, access.getInDoc(), \"" + ref + "\");\n");
        contextClassStack.push(contextClass);
        Class localContextClass = null;
        try {
            if (mapPath != null) {
                localContextClass = locateContextClass(mapPath, 1);
            } else {
                localContextClass = contextClass;
            }
        } catch (Exception e) {
            throw new UserException("Could not find adapter: " + className, e);
        }
        String type = null;
        try {
            type = MappingUtils.getFieldType(localContextClass, attribute);
        } catch (Exception e) {
            throw new UserException("Could not find field: " + attribute + " in adapter " + localContextClass.getName() + ", mappath = " + mapPath);
        }
        /**
         * END.
         */
        boolean isArray = MappingUtils.isArrayAttribute(localContextClass, attribute);
        try {
            contextClass = Class.forName(type, false, loader);
        } catch (Exception e) {
            throw new UserException("Could not find adapter: " + type);
        }
        addDependency("dependentObjects.add( new JavaDependency( -1, \"" + type + "\"));\n", "JAVA" + type);
        if (isArray) {
            String subObjectsName = "subObject" + subObjectCounter;
            String loopCounterName = "j" + subObjectCounter;
            subObjectCounter++;
            String objectDefinition = type + " [] " + subObjectsName + " = null;\n";
            variableClipboard.add(objectDefinition);
            variableClipboard.add("int " + loopCounterName + ";\n");
            result.append(printIdent(ident + 2) + subObjectsName + " = new " + type + "[" + messageListName + ".size()];\n");
            result.append(printIdent(ident + 2) + "for (" + loopCounterName + " = 0; " + loopCounterName + " < " + messageListName + ".size(); " + loopCounterName + "++) {\n if (!kill){\n");
            // currentInMsg, inMsgStack
            ident += 4;
            result.append(printIdent(ident) + "inMsgStack.push(currentInMsg);\n");
            if (isParam) {
                result.append(printIdent(ident) + "paramMsgStack.push(currentParamMsg);\n");
            }
            result.append(printIdent(ident) + "inSelectionRefStack.push(new Boolean(inSelectionRef));\n");
            if (isParam) {
                result.append(printIdent(ident) + "if (!inSelectionRef)\n");
                result.append(printIdent(ident + 2) + "currentParamMsg = (Message) " + messageListName + ".get(" + loopCounterName + ");\n");
            }
            result.append(printIdent(ident) + "if (!inSelectionRef)\n");
            result.append(printIdent(ident + 2) + "currentInMsg = (Message) " + messageListName + ".get(" + loopCounterName + ");\n");
            result.append(printIdent(ident) + "else\n");
            // currentSelection.
            result.append(printIdent(ident + 2) + "currentSelection = (Selection) " + messageListName + ".get(" + loopCounterName + ");\n");
            if (!filter.equals("")) {
                result.append(printIdent(ident + 4) + "if (inSelectionRef || Condition.evaluate(" + replaceQuotes(filter) + ", access.getInDoc(), currentMap, currentInMsg, currentParamMsg,access)) {\n");
                ident += 2;
            }
            result.append(printIdent(ident) + "treeNodeStack.push(currentMap);\n");
            result.append(printIdent(ident) + "currentMap = new MappableTreeNode(access, currentMap, classLoader.getClass(\"" + type + "\").newInstance(), false);\n");
            result.append(printIdent(ident + 4) + "currentMap.setNavajoLineNr(" + n.getAttribute("linenr") + ");\n");
            result.append(printIdent(ident) + "if ( currentMap.myObject instanceof Mappable ) {  ((Mappable) currentMap.myObject).load(access);}\n");
            result.append(printIdent(ident) + subObjectsName + "[" + loopCounterName + "] = (" + type + ") currentMap.myObject;\n");
            result.append(printIdent(ident) + "try {\n");
            ident = ident + 2;
            children = mapNode.getChildNodes();
            for (int i = 0; i < children.getLength(); i++) {
                result.append(compile(ident + 2, children.item(i), type, subObjectsName + "[" + loopCounterName + "]", dependencies, tenant));
            }
            ident = ident - 2;
            result.append(printIdent(ident) + "} catch (Exception e" + ident + ") {\n");
            result.append(printIdent(ident + 2) + "MappingUtils.callKillOrStoreMethod( " + subObjectsName + "[" + loopCounterName + "], e" + ident + ");\n");
            result.append(printIdent(ident + 2) + "throw e" + ident + ";\n");
            result.append(printIdent(ident) + "}\n");
            result.append(printIdent(ident) + "MappingUtils.callStoreMethod(" + subObjectsName + "[" + loopCounterName + "]);\n");
            result.append(printIdent(ident) + "currentMap.setEndtime();\ncurrentMap = (MappableTreeNode) treeNodeStack.pop();\n");
            if (!filter.equals("")) {
                ident -= 2;
                result.append(printIdent(ident + 4) + "}\n");
            }
            result.append(printIdent(ident) + "currentInMsg = (Message) inMsgStack.pop();\n");
            if (isParam) {
                result.append(printIdent(ident) + "currentParamMsg = (Message) paramMsgStack.pop();\n");
            }
            result.append(printIdent(ident) + "inSelectionRef = ((Boolean) inSelectionRefStack.pop()).booleanValue();\n");
            result.append(printIdent(ident) + "currentSelection = null;\n");
            ident -= 4;
            result.append(printIdent(ident + 2) + "}\n} // FOR loop for " + loopCounterName + "\n");
            if (mapPath == null) {
                result.append(printIdent(ident + 2) + objectName + "." + methodName + "(" + subObjectsName + ");\n");
            } else {
                result.append(printIdent(ident + 2) + "((" + locateContextClass(mapPath, 1).getName() + ") findMapByPath(\"" + mapPath + "\"))." + methodName + "(" + subObjectsName + ");\n");
            }
        } else {
            // Not an array type field, but single Mappable object.
            // Push current mappable object on stack.
            result.append(printIdent(ident) + "treeNodeStack.push(currentMap);\n");
            // Create instance of object.
            result.append(printIdent(ident) + "currentMap = new MappableTreeNode(access, currentMap, classLoader.getClass(\"" + type + "\").newInstance(), false);\n");
            result.append(printIdent(ident + 4) + "currentMap.setNavajoLineNr(" + n.getAttribute("linenr") + ");\n");
            // Create local variable to address new object.
            String subObjectsName = "subObject" + subObjectCounter;
            subObjectCounter++;
            // push currentInMsg, currentParamMsg and inSelectionRef
            ident += 4;
            result.append(printIdent(ident) + "inMsgStack.push(currentInMsg);\n");
            if (isParam) {
                result.append(printIdent(ident) + "paramMsgStack.push(currentParamMsg);\n");
            }
            result.append(printIdent(ident) + "inSelectionRefStack.push(new Boolean(inSelectionRef));\n");
            if (isParam) {
                result.append(printIdent(ident) + "if (!inSelectionRef)\n");
                result.append(printIdent(ident + 2) + "currentParamMsg = (Message) " + messageListName + ".get(0);\n");
            }
            result.append(printIdent(ident) + "if (!inSelectionRef)\n");
            result.append(printIdent(ident + 2) + "currentInMsg = (Message) " + messageListName + ".get(0);\n");
            result.append(printIdent(ident) + "else\n");
            // currentSelection.
            result.append(printIdent(ident + 2) + "currentSelection = (Selection) " + messageListName + ".get(0);\n");
            // Call load on object.
            result.append(printIdent(ident) + "if ( currentMap.myObject instanceof Mappable) { ((Mappable) currentMap.myObject).load(access);}\n");
            // Assign local variable reference.
            result.append(printIdent(ident) + type + " " + subObjectsName + " = (" + type + ") currentMap.myObject;\n");
            result.append(printIdent(ident) + "try {\n");
            ident = ident + 2;
            // Recursively dive into children.
            children = mapNode.getChildNodes();
            for (int i = 0; i < children.getLength(); i++) {
                result.append(compile(ident + 2, children.item(i), type, subObjectsName, dependencies, tenant));
            }
            ident = ident - 2;
            result.append(printIdent(ident) + "} catch (Exception e" + ident + ") {\n");
            result.append(printIdent(ident + 2) + "MappingUtils.callKillOrStoreMethod( " + subObjectsName + ", e" + ident + ");\n");
            result.append(printIdent(ident + 2) + "throw e" + ident + ";\n");
            result.append(printIdent(ident) + "}\n");
            result.append(printIdent(ident) + "MappingUtils.callStoreMethod(" + subObjectsName + ");\n");
            result.append(printIdent(ident) + "currentInMsg = (Message) inMsgStack.pop();\n");
            if (isParam) {
                result.append(printIdent(ident) + "currentParamMsg = (Message) paramMsgStack.pop();\n");
            }
            result.append(printIdent(ident) + "inSelectionRef = ((Boolean) inSelectionRefStack.pop()).booleanValue();\n");
            result.append(printIdent(ident) + "currentSelection = null;\n");
            result.append(printIdent(ident) + "currentMap.setEndtime();\ncurrentMap = (MappableTreeNode) treeNodeStack.pop();\n");
            if (mapPath == null) {
                result.append(printIdent(ident + 2) + objectName + "." + methodName + "(" + subObjectsName + ");\n");
            } else {
                result.append(printIdent(ident + 2) + "((" + locateContextClass(mapPath, 1).getName() + ") findMapByPath(\"" + mapPath + "\"))." + methodName + "(" + subObjectsName + ");\n");
            }
        }
        contextClass = contextClassStack.pop();
    }
    result.append(printIdent(ident) + "}\n");
    return result.toString();
}
Also used : JavaDependency(com.dexels.navajo.mapping.compiler.meta.JavaDependency) NodeList(org.w3c.dom.NodeList) Element(org.w3c.dom.Element) ArrayList(java.util.ArrayList) UserException(com.dexels.navajo.script.api.UserException) TransformerException(javax.xml.transform.TransformerException) MappingException(com.dexels.navajo.script.api.MappingException) TMLExpressionException(com.dexels.navajo.expression.api.TMLExpressionException) ParseException(com.dexels.navajo.parser.compiled.ParseException) KeywordException(com.dexels.navajo.mapping.compiler.meta.KeywordException) MetaCompileException(com.dexels.navajo.mapping.compiler.meta.MetaCompileException) IOException(java.io.IOException) SystemException(com.dexels.navajo.script.api.SystemException) CompilationException(com.dexels.navajo.script.api.CompilationException) UserException(com.dexels.navajo.script.api.UserException)

Aggregations

TMLExpressionException (com.dexels.navajo.expression.api.TMLExpressionException)2 KeywordException (com.dexels.navajo.mapping.compiler.meta.KeywordException)2 MetaCompileException (com.dexels.navajo.mapping.compiler.meta.MetaCompileException)2 ParseException (com.dexels.navajo.parser.compiled.ParseException)2 CompilationException (com.dexels.navajo.script.api.CompilationException)2 MappingException (com.dexels.navajo.script.api.MappingException)2 SystemException (com.dexels.navajo.script.api.SystemException)2 UserException (com.dexels.navajo.script.api.UserException)2 IOException (java.io.IOException)2 TransformerException (javax.xml.transform.TransformerException)2 Element (org.w3c.dom.Element)2 NodeList (org.w3c.dom.NodeList)2 IncludeDependency (com.dexels.navajo.mapping.compiler.meta.IncludeDependency)1 JavaDependency (com.dexels.navajo.mapping.compiler.meta.JavaDependency)1 NS3ToNSXML (com.dexels.navajo.mapping.compiler.navascript.NS3ToNSXML)1 ByteArrayInputStream (java.io.ByteArrayInputStream)1 File (java.io.File)1 FileInputStream (java.io.FileInputStream)1 ArrayList (java.util.ArrayList)1 Document (org.w3c.dom.Document)1