Package net.sf.jasperreports.olap.xmla

Source Code of net.sf.jasperreports.olap.xmla.JRXmlaQueryExecuter

/*
* JasperReports - Free Java Reporting Library.
* Copyright (C) 2001 - 2009 Jaspersoft Corporation. All rights reserved.
* http://www.jaspersoft.com
*
* Unless you have purchased a commercial license agreement from Jaspersoft,
* the following license terms apply:
*
* This program is part of JasperReports.
*
* JasperReports 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 3 of the License, or
* (at your option) any later version.
*
* JasperReports 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 JasperReports. If not, see <http://www.gnu.org/licenses/>.
*/
package net.sf.jasperreports.olap.xmla;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPConnectionFactory;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFactory;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRDataset;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRRuntimeException;
import net.sf.jasperreports.engine.query.JRAbstractQueryExecuter;
import net.sf.jasperreports.olap.JROlapDataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


/**
* @author Michael G�nther (m.guenther at users.sourceforge.net)
* @version $Id: JRXmlaQueryExecuter.java 3748 2010-04-16 17:12:43Z lucianc $
*/
public class JRXmlaQueryExecuter extends JRAbstractQueryExecuter
{

  private static final Log log = LogFactory.getLog(JRXmlaQueryExecuter.class);
 
  private static final String SLICER_AXIS_NAME = "SlicerAxis";
  private static final String MDD_URI = "urn:schemas-microsoft-com:xml-analysis:mddataset";
  private static final String XMLA_URI = "urn:schemas-microsoft-com:xml-analysis";
 
  private static final Pattern LEVEL_UNIQUE_NAME_PATTERN = Pattern.compile("\\[[^\\]]+\\]\\.\\[([^\\]]+)\\]");
  private static final int LEVEL_UNIQUE_NAME_PATTERN_NAME_GROUP = 1;

  private SOAPFactory sf;
  private SOAPConnection connection;
  private JRXmlaResult xmlaResult;


  public JRXmlaQueryExecuter(JRDataset dataset, Map parametersMap)
  {
    super(dataset, parametersMap);

    parseQuery();
  }

  protected String getParameterReplacement(String parameterName)
  {
    return String.valueOf(getParameterValue(parameterName));
  }

 
  public JRDataSource createDatasource() throws JRException
  {
    try
    {
      this.sf = SOAPFactory.newInstance();
      this.connection = createSOAPConnection();
      SOAPMessage queryMessage = createQueryMessage();

      URL soapURL = new URL(getSoapUrl());
      SOAPMessage resultMessage = executeQuery(queryMessage, soapURL);
     
      xmlaResult = new JRXmlaResult();
      parseResult(resultMessage);
    }
    catch (MalformedURLException e)
    {
      throw new JRRuntimeException(e);
    }
    catch (SOAPException e)
    {
      throw new JRRuntimeException(e);
    }
   
    return new JROlapDataSource(dataset, xmlaResult);
  }

  protected String getSoapUrl() throws MalformedURLException
  {
    String soapUrl;
    String xmlaUrl = (String) getParameterValue(JRXmlaQueryExecuterFactory.PARAMETER_XMLA_URL);
    String user = (String) getParameterValue(JRXmlaQueryExecuterFactory.PARAMETER_XMLA_USER, true);
    if (user == null || user.length() == 0)
    {
      soapUrl = xmlaUrl;
    }
    else
    {
      URL url = new URL(xmlaUrl);
      soapUrl = url.getProtocol() + "://" + user;
     
      String password = (String) getParameterValue(JRXmlaQueryExecuterFactory.PARAMETER_XMLA_PASSWORD, true);
      if (password != null && password.length() > 0)
      {
        soapUrl += ":" + password;
      }

      soapUrl += "@" + url.getHost() + ":" + url.getPort() + url.getPath();
    }
    return soapUrl;
  }

  public boolean cancelQuery() throws JRException
  {
    return false;
  }

  public void close()
  {
    if (connection != null)
    {
      try
      {
        connection.close();
      }
      catch (SOAPException e)
      {
        throw new JRRuntimeException(e);
      }
      connection = null;
    }
  }

  protected SOAPConnection createSOAPConnection()
  {
    try
    {
      SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance();
      return scf.createConnection();
    }
    catch (UnsupportedOperationException e)
    {
      throw new JRRuntimeException(e);
    }
    catch (SOAPException e)
    {
      throw new JRRuntimeException(e);
    }
  }

  protected SOAPMessage createQueryMessage()
  {
    String queryStr = getQueryString();

    if (log.isDebugEnabled())
    {
      log.debug("MDX query: " + queryStr);
    }
   
    try
    {
      MessageFactory mf = MessageFactory.newInstance();
      SOAPMessage message = mf.createMessage();

      MimeHeaders mh = message.getMimeHeaders();
      mh.setHeader("SOAPAction", "\"urn:schemas-microsoft-com:xml-analysis:Execute\"");

      SOAPPart soapPart = message.getSOAPPart();
      SOAPEnvelope envelope = soapPart.getEnvelope();
      SOAPBody body = envelope.getBody();
      Name nEx = envelope.createName("Execute", "", XMLA_URI);

      SOAPElement eEx = body.addChildElement(nEx);

      // add the parameters

      // COMMAND parameter
      // <Command>
      // <Statement>queryStr</Statement>
      // </Command>
      Name nCom = envelope.createName("Command", "", XMLA_URI);
      SOAPElement eCommand = eEx.addChildElement(nCom);
      Name nSta = envelope.createName("Statement", "", XMLA_URI);
      SOAPElement eStatement = eCommand.addChildElement(nSta);
      eStatement.addTextNode(queryStr);

      // <Properties>
      // <PropertyList>
      // <DataSourceInfo>dataSource</DataSourceInfo>
      // <Catalog>catalog</Catalog>
      // <Format>Multidimensional</Format>
      // <AxisFormat>TupleFormat</AxisFormat>
      // </PropertyList>
      // </Properties>
      Map paraList = new HashMap();
      String datasource = (String) getParameterValue(JRXmlaQueryExecuterFactory.PARAMETER_XMLA_DATASOURCE);
      paraList.put("DataSourceInfo", datasource);
      String catalog = (String) getParameterValue(JRXmlaQueryExecuterFactory.PARAMETER_XMLA_CATALOG);
      paraList.put("Catalog", catalog);
      paraList.put("Format", "Multidimensional");
      paraList.put("AxisFormat", "TupleFormat");
      addParameterList(envelope, eEx, "Properties", "PropertyList", paraList);
      message.saveChanges();

      if (log.isDebugEnabled())
      {
        log.debug("XML/A query message: " + message.toString());
      }

      return message;
    }
    catch (SOAPException e)
    {
      throw new JRRuntimeException(e);
    }
  }

  protected void addParameterList(SOAPEnvelope envelope, SOAPElement eParent, String typeName, String listName, Map params) throws SOAPException
  {
    Name nPara = envelope.createName(typeName, "", XMLA_URI);
    SOAPElement eType = eParent.addChildElement(nPara);
    nPara = envelope.createName(listName, "", XMLA_URI);
    SOAPElement eList = eType.addChildElement(nPara);
    if (params == null)
    {
      return;
    }
    for (Iterator entryIt = params.entrySet().iterator(); entryIt.hasNext();)
    {
      Map.Entry entry = (Map.Entry) entryIt.next();
      String tag = (String) entry.getKey();
      String value = (String) entry.getValue();
      nPara = envelope.createName(tag, "", XMLA_URI);
      SOAPElement eTag = eList.addChildElement(nPara);
      eTag.addTextNode(value);
    }
  }

  /**
   * Sends the SOAP Message over the connection and returns the
   * Result-SOAP-Message
   *
   * @return Reply-Message
   */
  protected SOAPMessage executeQuery(SOAPMessage message, URL url)
  {
    try
    {
     
      return connection.call(message, url);
    }
    catch (SOAPException e)
    {
      throw new JRRuntimeException("Message-Call failed.", e);
    }
  }

  /**
   * Parses the result-Message into this class's structure
   *
   * @param reply
   *            The reply-Message from the Server
   */
  protected void parseResult(SOAPMessage reply) throws SOAPException
  {
    SOAPPart soapPart = reply.getSOAPPart();
    SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
    SOAPBody soapBody = soapEnvelope.getBody();
    SOAPElement eElement = null;

    if (log.isDebugEnabled())
    {
      log.debug("XML/A result envelope: " + soapEnvelope.toString());
    }
   
    SOAPFault fault = soapBody.getFault();
    if (fault != null)
    {
      handleResultFault(fault);
    }
   
    Name eName = soapEnvelope.createName("ExecuteResponse", "", XMLA_URI);

    // Get the ExecuteResponse-Node
    Iterator responseElements = soapBody.getChildElements(eName);
    if (responseElements.hasNext())
    {
      Object eObj = responseElements.next();
      if (eObj == null)
      {
        throw new JRRuntimeException("ExecuteResponse Element is null.");
      }
      eElement = (SOAPElement) eObj;
    }
    else
    {
      throw new JRRuntimeException("Could not retrieve ExecuteResponse Element.");
    }

    // Get the return-Node
    Name rName = soapEnvelope.createName("return", "", XMLA_URI);
    Iterator returnElements = eElement.getChildElements(rName);
    SOAPElement returnElement = null;
    if (returnElements.hasNext())
    {
      Object eObj = returnElements.next();
      if (eObj == null)
      {
        throw new JRRuntimeException("return Element is null.");
      }
      returnElement = (SOAPElement) eObj;
    }
    else
    {
      // Should be old-Microsoft XMLA-SDK. Try without m-prefix
      Name rName2 = soapEnvelope.createName("return", "", "");
      returnElements = eElement.getChildElements(rName2);
      if (returnElements.hasNext())
      {
        Object eObj = returnElements.next();
        if (eObj == null)
        {
          throw new JRRuntimeException("return Element is null.");
        }
        returnElement = (SOAPElement) eObj;
      }
      else
      {
        throw new JRRuntimeException("Could not retrieve return Element.");
      }
    }

    // Get the root-Node
    Name rootName = soapEnvelope.createName("root", "", MDD_URI);
    SOAPElement rootElement = null;
    Iterator rootElements = returnElement.getChildElements(rootName);
    if (rootElements.hasNext())
    {
      Object eObj = rootElements.next();
      if (eObj == null)
      {
        throw new JRRuntimeException("root Element is null.");
      }
      rootElement = (SOAPElement) eObj;
    }
    else
    {
      throw new JRRuntimeException("Could not retrieve root Element.");
    }
    // Get the OlapInfo-Node
    Name olapInfoName = soapEnvelope.createName("OlapInfo", "", MDD_URI);
    SOAPElement olapInfoElement = null;
    Iterator olapInfoElements = rootElement.getChildElements(olapInfoName);
    if (olapInfoElements.hasNext())
    {
      Object eObj = olapInfoElements.next();
      if (eObj == null)
      {
        throw new JRRuntimeException("OlapInfo Element is null.");
      }
      olapInfoElement = (SOAPElement) eObj;
    }
    else
    {
      throw new JRRuntimeException("Could not retrieve OlapInfo Element.");
    }

    parseOLAPInfoElement(olapInfoElement);

    // Get the Axes Element
    Name axesName = soapEnvelope.createName("Axes", "", MDD_URI);
    SOAPElement axesElement = null;
    Iterator axesElements = rootElement.getChildElements(axesName);
    if (axesElements.hasNext())
    {
      Object eObj = axesElements.next();
      if (eObj == null)
      {
        throw new JRRuntimeException("Axes Element is null");
      }
      axesElement = (SOAPElement) eObj;
    }
    else
    {
      throw new JRRuntimeException("Could not retrieve Axes Element.");
    }

    parseAxesElement(axesElement);

    // Get the CellData Element
    Name cellDataName = soapEnvelope.createName("CellData", "", MDD_URI);
    SOAPElement cellDataElement = null;
    Iterator cellDataElements = rootElement.getChildElements(cellDataName);
    if (cellDataElements.hasNext())
    {
      Object eObj = cellDataElements.next();
      if (eObj == null)
      {
        throw new JRRuntimeException("CellData element is null");
      }
      cellDataElement = (SOAPElement) eObj;
    }
    else
    {
      throw new JRRuntimeException("Could not retrieve CellData Element.");
    }
    parseCellDataElement(cellDataElement);
  }

  protected void handleResultFault(SOAPFault fault)
  {
    StringBuffer errorMsg = new StringBuffer();
    errorMsg.append("XML/A fault: ");
   
    String faultString = fault.getFaultString();
    if (faultString != null)
    {
      errorMsg.append(faultString);
      errorMsg.append("; ");
    }

    String faultActor = fault.getFaultActor();
    if (faultActor != null)
    {
      errorMsg.append("Actor: ");
      errorMsg.append(faultActor);
      errorMsg.append("; ");
    }

    String faultCode = fault.getFaultCode();
    if (faultCode != null)
    {
      errorMsg.append("Code: ");
      errorMsg.append(faultCode);
      errorMsg.append("; ");
    }
   
    throw new JRRuntimeException(errorMsg.toString());
  }

  protected void parseOLAPInfoElement(SOAPElement olapInfoElement) throws SOAPException
  {
    // CubeInfo-Element is not needed

    // Get the AxesInfo-Node
    Name axesInfoName = sf.createName("AxesInfo", "", MDD_URI);
    SOAPElement axesElement = null;
    Iterator axesInfoElements = olapInfoElement.getChildElements(axesInfoName);
    if (axesInfoElements.hasNext())
    {
      Object axesObj = axesInfoElements.next();
      if (axesObj == null)
      {
        throw new JRRuntimeException("AxisInfo Element is null.");
      }
      axesElement = (SOAPElement) axesObj;
    }
    else
    {
      throw new JRRuntimeException("Could not retrieve AxesInfo Element.");
    }
   
    parseAxesInfoElement(axesElement);

    // CellInfo is not needed
  }

  protected void parseAxesInfoElement(SOAPElement axesInfoElement) throws SOAPException
  {
    // Cycle over AxisInfo-Elements
    Name axisInfoName = sf.createName("AxisInfo", "", MDD_URI);
    Iterator itAxis = axesInfoElement.getChildElements(axisInfoName);
    while (itAxis.hasNext())
    {
      SOAPElement axisElement = (SOAPElement) itAxis.next();
      Name name = sf.createName("name");
      String axisName = axisElement.getAttributeValue(name);
      if (axisName.equals(SLICER_AXIS_NAME))
      {
        continue;
      }

      JRXmlaResultAxis axis = new JRXmlaResultAxis(axisName);
      xmlaResult.addAxis(axis);

      // retrieve the hierarchies by <HierarchyInfo>
      name = sf.createName("HierarchyInfo", "", MDD_URI);
      Iterator itHierInfo = axisElement.getChildElements(name);
      while (itHierInfo.hasNext())
      {
        SOAPElement eHierInfo = (SOAPElement) itHierInfo.next();
        handleHierInfo(axis, eHierInfo);
      }
    }
  }

  protected void parseAxesElement(SOAPElement axesElement) throws SOAPException
  {
    // Cycle over Axis-Elements
    Name aName = sf.createName("Axis", "", MDD_URI);
    Iterator itAxis = axesElement.getChildElements(aName);
    while (itAxis.hasNext())
    {
      SOAPElement axisElement = (SOAPElement) itAxis.next();
      Name name = sf.createName("name");
      String axisName = axisElement.getAttributeValue(name);

      if (axisName.equals(SLICER_AXIS_NAME))
      {
        continue;
      }

      // LookUp for the Axis
      JRXmlaResultAxis axis = xmlaResult.getAxisByName(axisName);

      // retrieve the tuples by <Tuples>
      name = sf.createName("Tuples", "", MDD_URI);
      Iterator itTuples = axisElement.getChildElements(name);
      if (itTuples.hasNext())
      {
        SOAPElement eTuples = (SOAPElement) itTuples.next();
        handleTuplesElement(axis, eTuples);
      }
    }
  }

  protected void parseCellDataElement(SOAPElement cellDataElement) throws SOAPException
  {
    Name name = sf.createName("Cell", "", MDD_URI);
    Iterator itCells = cellDataElement.getChildElements(name);
    while (itCells.hasNext())
    {
      SOAPElement cellElement = (SOAPElement) itCells.next();
     
      Name errorName = sf.createName("Error", "", MDD_URI);
      Iterator errorElems = cellElement.getChildElements(errorName);
      if (errorElems.hasNext())
      {
        handleCellErrors(errorElems);
      }
     
      Name ordinalName = sf.createName("CellOrdinal");
      String cellOrdinal = cellElement.getAttributeValue(ordinalName);

      Object value = null;
      Iterator valueElements = cellElement.getChildElements(sf.createName("Value", "", MDD_URI));
      if (valueElements.hasNext())
      {
        SOAPElement valueElement = (SOAPElement) valueElements.next();
        String valueType = valueElement.getAttribute("xsi:type");
        if (valueType.equals("xsd:int"))
        {
          value = new Long(valueElement.getValue());
        }
        else if (valueType.equals("xsd:double"))
        {
          value = new Double(valueElement.getValue());
        }
        else if (valueType.equals("xsd:decimal"))
        {
          value = new Double(valueElement.getValue());
        }
        else
        {
          value = valueElement.getValue();
        }
      }

      String fmtValue = "";
      Iterator fmtValueElements = cellElement.getChildElements(sf.createName("FmtValue", "", MDD_URI));
      if (fmtValueElements.hasNext())
      {
        SOAPElement fmtValueElement = ((SOAPElement) fmtValueElements.next());
        fmtValue = fmtValueElement.getValue();
      }

      int pos = Integer.parseInt(cellOrdinal);
      JRXmlaCell cell = new JRXmlaCell(value, fmtValue);
      xmlaResult.setCell(cell, pos);
    }
  }

  protected void handleCellErrors(Iterator errorElems) throws SOAPException
  {
    SOAPElement errorElem = (SOAPElement) errorElems.next();
   
    StringBuffer errorMsg = new StringBuffer();
    errorMsg.append("Cell error: ");
   
    Iterator descriptionElems = errorElem.getChildElements(sf.createName("Description", "", MDD_URI));
    if (descriptionElems.hasNext())
    {
      SOAPElement descrElem = (SOAPElement) descriptionElems.next();
      errorMsg.append(descrElem.getValue());
      errorMsg.append("; ");
    }
   
    Iterator sourceElems = errorElem.getChildElements(sf.createName("Source", "", MDD_URI));
    if (sourceElems.hasNext())
    {
      SOAPElement sourceElem = (SOAPElement) sourceElems.next();
      errorMsg.append("Source: ");
      errorMsg.append(sourceElem.getValue());
      errorMsg.append("; ");
    }
   
    Iterator codeElems = errorElem.getChildElements(sf.createName("ErrorCode", "", MDD_URI));
    if (codeElems.hasNext())
    {
      SOAPElement codeElem = (SOAPElement) codeElems.next();
      errorMsg.append("Code: ");
      errorMsg.append(codeElem.getValue());
      errorMsg.append("; ");
    }
   
    throw new JRRuntimeException(errorMsg.toString());
  }

  protected void handleHierInfo(JRXmlaResultAxis axis, SOAPElement hierInfoElement) throws SOAPException
  {
    Name name = sf.createName("name");
    String dimName = hierInfoElement.getAttributeValue(name); // Get the Dimension Name

    JRXmlaHierarchy hier = new JRXmlaHierarchy(dimName);
    axis.addHierarchy(hier);
  }

  protected void handleTuplesElement(JRXmlaResultAxis axis, SOAPElement tuplesElement) throws SOAPException
  {
    Name tName = sf.createName("Tuple", "", MDD_URI);
    for (Iterator itTuple = tuplesElement.getChildElements(tName); itTuple.hasNext();)
    {
      SOAPElement eTuple = (SOAPElement) itTuple.next();
      handleTupleElement(axis, eTuple);
    }
  }

  protected void handleTupleElement(JRXmlaResultAxis axis, SOAPElement tupleElement) throws SOAPException
  {
    JRXmlaMemberTuple tuple = new JRXmlaMemberTuple(axis.getHierarchiesOnAxis().length);
   
    Name memName = sf.createName("Member", "", MDD_URI);
    Iterator itMember = tupleElement.getChildElements(memName);
    int memNum = 0;
    while (itMember.hasNext())
    {
      SOAPElement memElement = (SOAPElement) itMember.next();
     
      Name name = sf.createName("Hierarchy", "", "");
      String hierName = memElement.getAttributeValue(name);
     
      String uName = "";
      Iterator uNameElements = memElement.getChildElements(sf.createName("UName", "", MDD_URI));
      if (uNameElements.hasNext())
      {
        uName = ((SOAPElement) uNameElements.next()).getValue();
      }
      String caption = "";
      Iterator captionElements = memElement.getChildElements(sf.createName("Caption", "", MDD_URI));
      if (captionElements.hasNext())
      {
        caption = ((SOAPElement) captionElements.next()).getValue();
      }
      String lName = "";
      Iterator lNameElements = memElement.getChildElements(sf.createName("LName", "", MDD_URI));
      if (lNameElements.hasNext())
      {
        String levelUniqueName = ((SOAPElement) lNameElements.next()).getValue();
        Matcher matcher = LEVEL_UNIQUE_NAME_PATTERN.matcher(levelUniqueName);
        if (matcher.matches())
        {
          lName = matcher.group(LEVEL_UNIQUE_NAME_PATTERN_NAME_GROUP);
        }
      }
     
      int lNum = 0;
      Iterator lNumElements = memElement.getChildElements(sf.createName("LNum", "", MDD_URI));
      if (lNumElements.hasNext())
      {
        lNum = Integer.parseInt(((SOAPElement) lNumElements.next()).getValue());
      }
      JRXmlaMember member = new JRXmlaMember(caption, uName, hierName, lName, lNum);
      tuple.setMember(memNum++, member);
    }

    axis.addTuple(tuple);
  }
}
TOP

Related Classes of net.sf.jasperreports.olap.xmla.JRXmlaQueryExecuter

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.