xmlamediator.java

来自「数据仓库展示程序」· Java 代码 · 共 827 行 · 第 1/3 页

JAVA
827
字号
                    valueType = "xsd:double";
                } else {
                    valueType = "xsd:string";
                }

                if (value != null) {
                    if (cellPropLong.equals(Property.VALUE.name)) {
                        saxHandler.startElement(cellProps[i], new String[]{"xsi:type", valueType});
                    } else {
                        saxHandler.startElement(cellProps[i]);
                    }

                    String valueString = value.toString();

                    if (cellPropLong.equals(Property.VALUE.name) &&
                           value instanceof Number) {
                        valueString = normalizeNumricString(valueString);
                    }

                    saxHandler.characters(valueString);
                    saxHandler.endElement();
                }
            }
            saxHandler.endElement(); // Cell
        }
    }

    private void discover(Element discover, SAXHandler saxHandler) {
        String requestType = firstElementCDATA(discover, "RequestType");
        if (requestType == null) {
            throw Util.newError("<RequestType> parameter is required");
        }

        HashMap restrictionsProperties = getRestrictions(discover);
        Properties propertyProperties = getProperties(discover);
        final RowsetDefinition rowsetDefinition = RowsetDefinition.getValue(requestType);
        Rowset rowset = rowsetDefinition.getRowset(restrictionsProperties, propertyProperties);

        try {
            saxHandler.startElement("DiscoverResponse", new String[] {
                "xmlns", XMLA_NS});
            saxHandler.startElement("return");
            saxHandler.startElement("root", new String[] {
                "xmlns", XMLA_ROWSET_NS});
            saxHandler.startElement("xsd:schema", new String[] {
                "xmlns:xsd", XSD_NS,
                "targetNamespace", XMLA_ROWSET_NS,
                "xmlns:xsi", XSI_NS,
                "xmlns:sql", "urn:schemas-microsoft-com:xml-sql",
                "elementFormDefault", "qualified"});
            //TODO: add schema
            saxHandler.endElement();
            try {
                rowset.unparse(saxHandler);
            } catch(RuntimeException re) { // MondrianException is subclass of RuntimeException
                saxHandler.completeBeforeElement("root");
                reportXmlaError(saxHandler, re);
            } finally {
                // keep the tags balanced, even if there's an error
                saxHandler.endElement();
                saxHandler.endElement();
                saxHandler.endElement();
            }
        } catch (SAXException e) {
            throw Util.newError(e, "Error while processing '" + requestType + "' discovery request");
        }
    }

    private void reportXmlaError(SAXHandler saxHandler, Exception exception) throws SAXException {
        Throwable throwable = gotoRootThrowable(exception);
        saxHandler.startElement("Messages");
        saxHandler.startElement("Error", new String[] {
                "ErrorCode", throwable.getClass().getName(),
                "Description", throwable.getMessage(),
                "Source", "Mondrian",
                "Help", "",
        });
        // Don't dump stack trace to client
//        StringWriter stackWriter = new StringWriter();
//        throwable.printStackTrace(new PrintWriter(stackWriter));
//        saxHandler.characters(stackWriter.getBuffer().toString());
        saxHandler.endElement();
        saxHandler.endElement();
    }


    private HashMap getRestrictions(Element discover) {
        Element restrictions = firstElement(discover, "Restrictions");
        if (restrictions == null) {
            throw Util.newError("<Restrictions> parameter is required (but may be empty)");
        }
        Element restrictionList = firstElement(restrictions, "RestrictionList");
        HashMap restrictionsMap = new HashMap();
        if (restrictionList != null) {
            NodeList childNodes = restrictionList.getChildNodes();
            for (int i = 0, n = childNodes.getLength(); i < n; i++) {
                Node childNode = childNodes.item(i);
                if (childNode instanceof Element) {
                    Element childElement = (Element) childNode;
                    String childTag = childElement.getLocalName();
                    Object childValue = getCDATA2(childElement);
                    restrictionsMap.put(childTag, childValue);
                }
            }
        }
        return restrictionsMap;
    }

    /**
     * Returns the &lt;Properties&gt; contained within a &lt;Execute&gt; or
     * &lt;Discover&gt; element.
     */
    private Properties getProperties(Element method) {
        Element properties = firstElement(method, "Properties");
        if (properties == null) {
            throw Util.newError("<Properties> parameter is required (but may be epmty)");
        }
        Element propertyList = firstElement(properties, "PropertyList");
        Properties propertyProperties = new Properties();
        if (propertyList != null) {
            NodeList childNodes = propertyList.getChildNodes();
            for (int i = 0, n = childNodes.getLength(); i < n; i++) {
                Node childNode = childNodes.item(i);
                if (childNode instanceof Element) {
                    Element childElement = (Element) childNode;
                    String childTag = childElement.getLocalName();
                    String childValue = getCDATA(childElement);
                    propertyProperties.setProperty(childTag, childValue);
                }
            }
        }
        return propertyProperties;
    }


    /**
     * Returns a Mondrian connection as specified by a set of properties
     * (especially the "Connect string" property).
     * @param properties
     * @return
     */
    static Connection getConnection(Properties properties) {
        final String dataSourceInfo = properties.getProperty(PropertyDefinition.DataSourceInfo.name);
        if (!dataSourcesMap.containsKey(dataSourceInfo)) {
                throw Util.newError("no data source is configured with name '" + dataSourceInfo + "'");
        }

        DataSourcesConfig.DataSource ds = (DataSourcesConfig.DataSource)dataSourcesMap.get(dataSourceInfo);
        Util.PropertyList connectProperties = Util.parseConnectString(ds.getDataSourceInfo());
        final String catalog = properties.getProperty(PropertyDefinition.Catalog.name);
        if (catalog != null) {
            connectProperties.put("CatalogName", catalog);
        }
        final ServletContext servletContext =
                (ServletContext) threadServletContext.get();
        return DriverManager.getConnection(connectProperties, servletContext,
                false);
    }

    /**
         * Retrieving the root MondrianException in an exception chain if exists.
         * @param throwable the last one in exception chain.
         * @return the root MondrianException if exists, otherwise the input exception.
         */
        static Throwable gotoRootThrowable(Throwable throwable) {
                Throwable rootThrowable = throwable.getCause();
                if (rootThrowable != null && rootThrowable instanceof MondrianException) {
                        return gotoRootThrowable(rootThrowable);
                }
                return throwable;
    }

    /**
     * Returns the first child element with a given tag, or null if there are
     * none.
     */
    private Element firstElement(Element element, String tagName) {
        NodeList elements = element.getElementsByTagNameNS("*", tagName);
        for (int i = 0; i < elements.getLength(); i++) {
            Node node = elements.item(i);
            if (node instanceof Element) {
                return (Element) node;
            }
        }
        return null;
    }

    /**
     * Returns the text content of the first child element with a
     * given tag, or null if there is no such child.
     */
    private String firstElementCDATA(Element element, String tagName) {
        Element child = firstElement(element, tagName);
        if (child == null) {
            return null;
        }
        return getCDATA(child);
    }

    private String getCDATA(Element child) {
        child.normalize();
        NodeList childNodes = child.getChildNodes();
        switch (childNodes.getLength()) {
        case 0:
            return "";
        case 1:
            final Text grandChild = (Text) childNodes.item(0);
            return grandChild.getData();
        default:
            StringBuffer sb = new StringBuffer();
            for (int i = 0, n = childNodes.getLength(); i < n; i++) {
                sb.append(childNodes.item(i).toString());
            }
            return sb.toString();
        }
    }

    private Object getCDATA2(Element child) {
        child.normalize();
        NodeList childNodes = child.getChildNodes();
        if (valuesExist(childNodes)) {
            ArrayList list = new ArrayList();
            for (int i = 0, n = childNodes.getLength(); i < n; i++) {
                final Node node = childNodes.item(i);
                if (node instanceof Element && node.getLocalName().equals("Value")) {
                    list.add(getCDATA((Element) node));
                }
            }
            return (String[]) list.toArray(new String[0]);
        } else {
            return getCDATA(child);
        }
    }

    private static boolean valuesExist(NodeList childNodes) {
        for (int i = 0, n = childNodes.getLength(); i < n; i++) {
            final Node node = childNodes.item(i);
            if (node instanceof Element && node.getLocalName().equals("Value")) {
                return true;
            }
        }
        return false;
    }

    private static String normalizeNumricString(String numericStr) {
        // This is here because different JDBC drivers
        // use different Number classes to return
        // numeric values (Double vs BigDecimal) and
        // these have different toString() behavior.
        // If it contains a decimal point, then
        // strip off trailing '0's. After stripping off
        // the '0's, if there is nothing right of the
        // decimal point, then strip off decimal point.
        int index = numericStr.indexOf('.');
        if (index > 0) {
            boolean found = false;
            int p = numericStr.length();
            char c = numericStr.charAt(p-1);
            while (c == '0') {
                found = true;
                p--;
                c = numericStr.charAt(p-1);
            }
            if (c == '.') {
                p--;
            }
            if (found)
                return numericStr.substring(0, p);
        }
        return numericStr;
    }
}

// End XmlaMediator.java

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?