/*
 * Copyright (C) 2005 - 2011 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 free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 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 Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.jaspersoft.jasperserver.api.metadata;

import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;

import com.jaspersoft.jasperserver.api.JSException;
import junit.textui.TestRunner;
import mondrian.olap.Member;
import mondrian.olap.Position;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.olap4j.CellSet;
import org.olap4j.OlapConnection;
import org.olap4j.layout.RectangularCellSetFormatter;
import org.olap4j.layout.TraditionalCellSetFormatter;

import com.jaspersoft.jasperserver.api.common.domain.ExecutionContext;
import com.jaspersoft.jasperserver.api.common.domain.ValidationResult;
import com.jaspersoft.jasperserver.api.common.domain.impl.ExecutionContextImpl;
import com.jaspersoft.jasperserver.api.metadata.common.domain.FileResource;
import com.jaspersoft.jasperserver.api.metadata.common.domain.Folder;
import com.jaspersoft.jasperserver.api.metadata.common.domain.Resource;
import com.jaspersoft.jasperserver.api.metadata.common.domain.ResourceReference;
import com.jaspersoft.jasperserver.api.metadata.common.domain.client.FolderImpl;
import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.JdbcReportDataSource;
import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.JndiJdbcReportDataSource;
import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.ReportUnit;
import com.jaspersoft.jasperserver.api.metadata.olap.domain.MondrianConnection;
import com.jaspersoft.jasperserver.api.metadata.olap.domain.MondrianXMLADefinition;
import com.jaspersoft.jasperserver.api.metadata.olap.domain.OlapUnit;
import com.jaspersoft.jasperserver.api.metadata.olap.domain.XMLAConnection;
import com.jaspersoft.jasperserver.api.metadata.olap.service.impl.OlapConnectionServiceImpl;
import com.jaspersoft.jasperserver.api.metadata.xml.domain.impl.ResourceDescriptor;
import com.jaspersoft.jasperserver.util.test.BaseJasperServerTest;
import com.tonbeller.jpivot.olap.model.OlapException;
import com.tonbeller.jpivot.olap.model.OlapModel;
import com.tonbeller.jpivot.olap.model.Result;

/**
 * @author sbirney
 */

public class OlapConnectionTest extends BaseJasperServerTest {

    private static final Log log = LogFactory.getLog(OlapConnectionTest.class);

    protected final String foodMartSchema2006URI   = "/queries/FoodmartSchema2006.xml";
    protected final String foodMartSchema2006UpperURI   = "/queries/FoodmartSchema2006Upper.xml";
    protected final String foodMartJaSchemaURI = "/queries/FoodMart_ja.xml";
    protected final String sugarCRMSchemaURI   = "/queries/SugarCRMSchema.xml";
    protected final String sugarCRMSchemaUpperURI   = "/queries/SugarcrmSchemaUpper.xml";
	
    private ExecutionContext executionContext;
    // direct access to impl to call methods that aren't in the i/f...
    private OlapConnectionServiceImpl olapConnectionServiceTarget;



  public enum OlapConnectionType {
    CLASSIC("CLASSIC") {},
    OLAP4J("OLAP4J")
     {};

    private String typeName;

    OlapConnectionType(String typeName) {
      this.typeName = typeName;
    }

    public String getOlapConnectionTypeName() {
      return typeName;
    }
  }



    public OlapConnectionTest() {
    	super();
    	setAutowireMode(AUTOWIRE_BY_NAME);
    }

    public OlapConnectionTest(String name) {
    	super(name);
    	setAutowireMode(AUTOWIRE_BY_NAME);
    }
    
    public static void main(String[] args) {
        TestRunner.run(OlapConnectionTest.class);
    }

    protected void onSetUp() throws Exception {

        executionContext = new ExecutionContextImpl();
		basicAuthSetup();
    }
	
	protected void onTearDown() {
		
		/*
		 * Remove repository objects that are not samples in the released product
		 * (ie. objects that users see after installing the application)
		 */
		Resource savedResource;

        savedResource = getRepositoryService().getResource(executionContext, "/analysis/views/Test_Sugar_View");

        if (savedResource != null) {
            getRepositoryService().deleteResource(executionContext, savedResource.getURI());
        }
		
		savedResource = getRepositoryService().getResource(executionContext, "/analysis/connections/SugarCRMTest");
                
        if (savedResource != null) {
            getRepositoryService().deleteResource(executionContext, savedResource.getURI());
        }
	}

    protected void createFoodmartSchemaResource() {
        createOrUpdateSchemaResource("/analysis/schemas",
                "FoodmartSchema",
                "FoodmartSchema",
                "Foodmart Analysis Schema",
                foodMartSchema2006URI);
    }

    protected void createFoodmartSchemaUpperResource() {
        createOrUpdateSchemaResource("/analysis/schemas",
                "FoodmartSchemaUpper",
                "Foodmart Schema Uppercase",
                "Foodmart Analysis Schema Uppercase",
                foodMartSchema2006UpperURI);
    }    
    
    // Pseudo Japanese schema version
    protected void createFoodmartJaSchemaResource() {
        createOrUpdateSchemaResource("/analysis/schemas",
                "FoodmartJaSchema",
                "Foodmart Schema Pseudo Japanese",
                "Foodmart Analysis Pseudo Japanese Schema",
                foodMartJaSchemaURI);
    }

    protected void createSugarCRMSchemaResource() {
        createOrUpdateSchemaResource("/analysis/schemas",
                "SugarCRMSchema",
                "SugarCRM Schema",
                "SugarCRM Analysis Schema",
                sugarCRMSchemaURI);
    }

    protected void createSugarCRMSchemaUpperResource() {
        createOrUpdateSchemaResource("/analysis/schemas",
                "SugarCRMSchemaUpper",
                "SugarCRM Schema Uppercase",
                "SugarCRM Analysis Schema Upper Case",
                sugarCRMSchemaUpperURI);
    }    
    
    protected void createFoodmartJDBCDataSourceResource() throws Exception {
        createJDBCDataSourceResource("/analysis/datasources",
                        "FoodmartDataSource",
                        "Foodmart Data Source",
                        "Foodmart Data Source",
                        getJdbcProps().getProperty("foodmart.jdbc.driverClassName"),
                        getJdbcProps().getProperty("foodmart.jdbc.url"),
                        getJdbcProps().getProperty("foodmart.jdbc.username"),
                        getJdbcProps().getProperty("foodmart.jdbc.password"));
    }

    protected void createFoodmartJNDIDataSourceResource() {
        createJNDIDataSourceResource("/analysis/datasources",
                        "FoodmartDataSourceJNDI",
                        "Foodmart Data Source JNDI",
                        "Foodmart Data Source JNDI",
                        "jdbc/foodmart");
    }
    
    protected void createFoodmartJaDataSourceResource() throws Exception {
        createJDBCDataSourceResource("/analysis/datasources",
                        "FoodmartJaDataSource",
                        "Foodmart Japanese Data Source",
                        "Foodmart Japanese Data Source",
                        getJdbcProps().getProperty("foodmart_ja.jdbc.driverClassName"),
                        getJdbcProps().getProperty("foodmart_ja.jdbc.url"),
                        getJdbcProps().getProperty("foodmart_ja.jdbc.username"),
                        getJdbcProps().getProperty("foodmart_ja.jdbc.password"));
    }

    protected void createSugarCRMDataSourceResource() throws Exception {
        createJDBCDataSourceResource("/analysis/datasources",
                        "SugarCRMDataSource",
                        "SugarCRM Data Source",
                        "SugarCRM Data Source",
                        getJdbcProps().getProperty("test.jdbc.driverClassName"),
                        getJdbcProps().getProperty("test.jdbc.url"),
                        getJdbcProps().getProperty("test.jdbc.username"),
                        getJdbcProps().getProperty("test.jdbc.password"));
    }

    protected void createSugarCRMDataSourceResourceJNDI() {
        createJNDIDataSourceResource("/analysis/datasources",
                        "SugarCRMDataSourceJNDI",
                        "SugarCRM Data Source JNDI",
                        "SugarCRM Data Source JNDI",
                        "jdbc/sugarcrm");
    }
    
    protected void createFoodmartMondrianConnectionResource() throws Exception {

        String schemaResourceReference = "/analysis/schemas/FoodmartSchema";

        if (getJdbcProps().getProperty("foodmart.upperCaseNames") != null &&
        		getJdbcProps().getProperty("foodmart.upperCaseNames").equalsIgnoreCase("true")) {
            schemaResourceReference = "/analysis/schemas/FoodmartSchemaUpper";
        }

        createMondrianConnectionResource("/analysis/connections",
                        "Foodmart",
                        "Foodmart Mondrian Connection",
                        "Foodmart Mondrian Analysis Connection",
                        schemaResourceReference,
                       "/analysis/datasources/FoodmartDataSourceJNDI");
    }
    
    protected void createFoodmartJaMondrianConnectionResource() {
        createMondrianConnectionResource("/analysis/connections",
                        "FoodmartJa",
                        "FoodmartJa Mondrian Connection",
                        "FoodmartJa Mondrian Analysis Connection",
                        "/analysis/schemas/FoodmartJaSchema",
                        "/analysis/datasources/FoodmartJaDataSource");
    }

    protected void createSugarCRMMondrianConnectionResource() throws Exception {

        String schemaResourceReference = "/analysis/schemas/SugarCRMSchema";

        if (getJdbcProps().getProperty("sugarcrm.upperCaseNames") != null &&
        		getJdbcProps().getProperty("sugarcrm.upperCaseNames").equalsIgnoreCase("true")) {
            schemaResourceReference = "/analysis/schemas/SugarCRMSchemaUpper";
        }

        createMondrianConnectionResource("/analysis/connections",
                        "SugarCRM",
                        "SugarCRM Mondrian Connection",
                        "SugarCRM Mondrian Analysis Connection: only opportunities",
                        schemaResourceReference,
                       "/analysis/datasources/SugarCRMDataSourceJNDI");
    }
        
    protected void createSugarCRMTestMondrianConnectionResource() throws Exception {
        String schemaResourceReference = "/analysis/schemas/SugarCRMSchema";

        if (getJdbcProps().getProperty("sugarcrm.upperCaseNames") != null &&
        		getJdbcProps().getProperty("sugarcrm.upperCaseNames").equalsIgnoreCase("true")) {
            schemaResourceReference = "/analysis/schemas/SugarCRMSchemaUpper";
        }

        createMondrianConnectionResource("/analysis/connections",
                        "SugarCRMTest",
                        "SugarCRM Mondrian Connection - Test Only",
                        "SugarCRM Mondrian Analysis Connection: test only",
                        schemaResourceReference,
                       "/analysis/datasources/SugarCRMDataSource");
    }

    protected void createFoodmartXMLAConnectionResource() {
        createXMLAConnectionResource("/analysis/connections",
                        "SugarCRMXmlaConnection",
                        "SugarCRM XML/A Connection",
                        "SugarCRM XML/A Connection",
                        "SugarCRM",
                        "Provider=Mondrian;DataSource=SugarCRM;",
                        "http://localhost:8080/jasperserver/xmla",
                        "jasperadmin",
                        "jasperadmin");
    }

    protected void createSugarCRMXMLAConnectionResource() {
        createXMLAConnectionResource("/analysis/connections",
                        "FoodmartXmlaConnection",
                        "Foodmart XML/A Connection",
                        "Foodmart XML/A Connection",
                        "Foodmart",
                        "Provider=Mondrian;DataSource=Foodmart;",
                        "http://localhost:8080/jasperserver/xmla",
                        "jasperadmin",
                        "jasperadmin");
    }

    protected void createFoodmartMondrianXMLADefinitionResource() {
        creatMondrianXMLADefinitionResource("/analysis/xmla/definitions",
                        "FoodmartXmlaDefinition",
                        "Foodmart Mondrian XMLA definition",
                        "Foodmart Mondrian XMLA definition",
                        "Foodmart",
                        "/analysis/connections/Foodmart");
    }

    protected void createSugarCRMMondrianXMLADefinitionResource() {
        creatMondrianXMLADefinitionResource("/analysis/xmla/definitions",
                        "SugarCRMXmlaDefinition",
                        "SugarCRM Mondrian XMLA definition",
                        "SugarCRM Mondrian XMLA definition",
                        "SugarCRM",
                        "/analysis/connections/SugarCRM");
    }

    public static String SAMPLE_FOODMART_JA_MDX_QUERY =
	"select {[Measures].[Unit Sales日本語], [Measures].[Store Cost日本語], [Measures].[Store Sales日本語]} on columns, {([Promotion Media日本語].[All Media日本語], [Product日本語].[All Products日本語])} ON rows from [Sales日本語] where ([Time日本語].[2006])";


    public static String SAMPLE_FOODMART_MDX_QUERY =
	"select {[Measures].[Unit Sales], [Measures].[Store Cost], [Measures].[Store Sales]} on columns, " +
	"{([Promotion Media].[All Media], [Product].[All Products])} ON rows " + 
	"from Sales " +
	"where ([Time].[2006].[Q4].[12])";


    protected void createFoodmartJaOlapUnit() {
        creatOlapUnitResource("/analysis/views",
                        "FoodmartJa_sample_unit_1",
                        "FoodmartJa Sample Analysis View",
                        "Sample Analysis View: 2006 Q1 FoodmartJa Unit Sales",
                        "/analysis/connections/FoodmartJa",
                        SAMPLE_FOODMART_JA_MDX_QUERY,
                        true);
    }

    protected void createFoodmartOlapUnit() {
        creatOlapUnitResource("/analysis/views",
                        "Foodmart_sample",
                        "Foodmart Sample Analysis View",
                        "Sample Analysis View: 2006 Q1 Foodmart Unit Sales",
                        "/analysis/connections/Foodmart",
                        SAMPLE_FOODMART_MDX_QUERY,
                        true);
    }
    
    protected void createSugarCRMXmlaOlapUnit() {
        creatOlapUnitResource("/analysis/views",
                        "SugarCRM_xmla_sample",
                        "SugarCRM Sample XMLA Analysis View",
                        "Sample SugarCRM Analysis View (XMLA): Sales Performance by Industry/Account",
                        "/analysis/connections/SugarCRMXmlaConnection",
                        SAMPLE_SUGAR_CRM_MDX_QUERY,
                        true);
    }

    protected void createFoodmartXmlaOlapUnit() {
        creatOlapUnitResource("/analysis/views",
                        "Foodmart_xmla_sample",
                        "Foodmart Sample XMLA Analysis View",
                        "Sample XMLA Analysis View: 2006 Q1 Foodmart Unit Sales",
                        "/analysis/connections/FoodmartXmlaConnection",
                        SAMPLE_FOODMART_MDX_QUERY,
                        true);
    }

    private String SAMPLE_SUGAR_CRM_MDX_QUERY =
	"select {[Measures].[Total Sale Amount], [Measures].[Number of Sales], [Measures].[Avg Sale Amount], [Measures].[Avg Time To Close (Days)], [Measures].[Avg Close Probability]} ON COLUMNS, " +
	" NON EMPTY {([Account Categorization].[All Accounts], [Close Period].[All Periods])} ON ROWS " +
	" from [SalesAnalysis] " +
	" where [Sale State].[All Types].[Closed Won]";

    protected void createSugarCRMOlapUnit() {
        creatOlapUnitResource("/analysis/views",
                        "SugarCRM_sample",
                        "SugarCRM Sample Analysis View",
                        "Sample SugarCRM Analysis View: Sales Performance by Industry/Account",
                        "/analysis/connections/SugarCRM",
                        SAMPLE_SUGAR_CRM_MDX_QUERY,
                        true);
        //OlapUnit cycledView = (OlapUnit)rep.getResource(null,
        //"/analysis/views/SugarCRM_sample");
        // calling validate here with view instead of cycledView throws null pointer
        // XXX jasperserver bug?
        //assertTrue( "validation of SugarCRM Olap Unit failed",
        //	    getConnectionService().validate(null, cycledView).
        //	    getValidationState() != ValidationResult.STATE_ERROR );
    }

    
    protected void executeSampleFoodmartQuery() {
	assertQueryShape( "/analysis/connections/Foodmart",
			  SAMPLE_FOODMART_MDX_QUERY,
			  "", new int[]{0,0});
    }

    protected void executeSampleSugarQuery() {
	assertQueryShape( "/analysis/connections/SugarCRM",
			  SAMPLE_SUGAR_CRM_MDX_QUERY,
			  "Total Sale Amount", new int[]{5,1});
    }

    protected void executeSampleSugarTestQuery() {
	assertQueryShape( "/analysis/connections/SugarCRMTest",
			  SAMPLE_SUGAR_CRM_MDX_QUERY, 
			  "Total Sale Amount", new int[]{5,1});
    }

  protected mondrian.olap.Connection getMondrianConnection(String connResourceName, OlapConnectionType connType)
      throws Exception {
    if (connType == OlapConnectionType.CLASSIC) {
      return getOlapConnectionServiceTarget().getMondrianConnection(null, connResourceName);
    } else if (connType == OlapConnectionType.OLAP4J) {
      try {

        return getOlapConnectionServiceTarget().getOlap4jMondrianConnection((ExecutionContext) null,
            connResourceName);
      } catch (Exception e) {
        throw new Exception("could not get mondrian.olap.Connection for '" + connType.getOlapConnectionTypeName() + "' " + e.getMessage());
      }
    }
    return null;
  }

    public void assertQueryShape( String connResourceName,
				     String mdxQuery,
				     String expectedCaption,
				     int[] expectedAxesLengths) {
      assertQueryShape(connResourceName,
				     mdxQuery,
				     expectedCaption,
				     expectedAxesLengths,
             OlapConnectionType.CLASSIC);
    }

    public void assertQueryShape( String connResourceName,
				     String mdxQuery,
				     String expectedCaption,
				     int[] expectedAxesLengths,
             OlapConnectionType olapConnType){

      mondrian.olap.Connection monConnection = null;

      try {
        monConnection = getMondrianConnection(connResourceName, olapConnType);
      } catch (Exception e) {
        fail(e.getMessage());
      }


        // perform olap test query with this mondrian Connection
        mondrian.olap.Query monQuery = monConnection.parseQuery(mdxQuery);
        mondrian.olap.Result monResult = monConnection.execute(monQuery);
        mondrian.olap.Axis[] axes = monResult.getAxes();
        mondrian.olap.Position pos = (Position)axes[0].getPositions().get(0);
        mondrian.olap.Member m0 = (Member)pos.get(0);
        String caption = m0.getCaption();

        assertEquals( "Number of axes - expected: " + expectedAxesLengths.length + ",  got: " + axes.length,
                axes.length,
                expectedAxesLengths.length );
        
        String axesDetail = "";
        for (int i = 0; i < axes.length; i++) {
            assertEquals("Axis " + i + " length error: expected " + expectedAxesLengths[i] + ", got " + axes[i].getPositions().size(),
                    expectedAxesLengths[i],
                    axes[i].getPositions().size() );

            axesDetail += (" " + axes[i].getPositions().size());
        }

        if (log.isDebugEnabled()) {
            log.debug("caption = " + caption + ", " +
                  "axes.length=" + axes.length + ", " +
                  "axes.lengths=" + axesDetail);
        }

        assertEquals( caption, expectedCaption );
    }



    // move this to configuration file if people want to use
    // this for testing on a regular basis...
    private final boolean DO_PSEUDO_JAPANESE_FOODMART = false;

    public void olapUnitTest() {
        // Test validation of view _not_yet_stored in DB

        OlapUnit view = creatOlapUnitResource("/analysis/views",
                        "Test_Sugar_View",
                        "Test SugarCRM View with JDBC",
                        "Test SugarCRM View with JDBC",
                        "/analysis/connections/SugarCRMTest",
                        SAMPLE_SUGAR_CRM_MDX_QUERY,
                        false);

        assertTrue( "validation of SugarCRM test view _not_ in DB failed",
                getOlapConnectionService().validate(null, view).getValidationState().equals(ValidationResult.STATE_VALID ));

        // Test validation of view stored in DB

        getOlapConnectionService().saveResource( null, "/analysis/views", view );

        view = (OlapUnit) getRepositoryService().getResource(null,
                        "/analysis/views/Test_Sugar_View");
        // calling validate here with view instead of cycledView throws null pointer
        // XXX jasperserver bug?sure

        //something tells me foodmart isn't set up right on aphid
        assertTrue( "validation of SugarCRM test view in DB failed",
                getOlapConnectionService().validate(null, view).getValidationState().equals(ValidationResult.STATE_VALID ));

        executeSampleSugarTestQuery();
        
        OlapModel sampleSugarModel = getModel( "Test_Sugar_View" );

        // call getResult on the models and assert they are good
        // Can't test OlapModel as is can't run outside of servlet engine
        //assertOlapModelResult( sampleSugarModel, 5 );

    }

    public void testOlapConnection() throws Exception {
        // create test metadata in the repository
    	createFoodmartSchemaResource();
    	createFoodmartSchemaUpperResource();    	
    	createSugarCRMSchemaResource();
    	createSugarCRMSchemaUpperResource();
        createFoodmartJDBCDataSourceResource();
        createFoodmartJNDIDataSourceResource();
        createSugarCRMDataSourceResource();
        createSugarCRMDataSourceResourceJNDI();
        createFoodmartMondrianConnectionResource();
        createFoodmartXMLAConnectionResource();
        createSugarCRMMondrianConnectionResource();
        createSugarCRMTestMondrianConnectionResource();
        createSugarCRMXMLAConnectionResource();
        createFoodmartOlapUnit();
        createSugarCRMOlapUnit();

	    createSugarCRMXmlaOlapUnit();
	    createFoodmartXmlaOlapUnit();
	    createFoodmartMondrianXMLADefinitionResource();
	    createSugarCRMMondrianXMLADefinitionResource();

	if (DO_PSEUDO_JAPANESE_FOODMART) {
	    createFoodmartJaSchemaResource();
	    createFoodmartJaDataSourceResource();
	    createFoodmartJaMondrianConnectionResource();
	    createFoodmartJaOlapUnit();
	}

	Folder analysisReports = createAnalysisReportsFolder();
	createMondrianFoodmartReport(analysisReports);
	createXmlaFoodmartReport(analysisReports);
	
	// test hitting mondrian directly
	olapUnitTest();

	// make some jpivot compatible olap models
	//OlapModel sampleFoodmartModel1 = getModel( "Foodmart_sample" );
	//OlapModel sampleSugarModel1 = getModel( "SugarCRM_sample" );
	//OlapModel sampleSugarModel2 = getModel( "SugarCRM_sample_unit_2" );
	getModel( "SugarCRM_xmla_sample" );

	// call getResult on the models and assert they are good
	//assertOlapModelResult( sampleSugarModel2, 5 );

	// server must be running for xmla model to work
	// should move Xmla to remote-tests
	//assertOlapModelResult( sampleSugarXmlaModel1, 5 );

	//assertOlapModelResult( sampleSugarXmlaModel2, 5 );
    }

	private void assertOlapModelResult( OlapModel m, int expectedNumCells ) {
        try {
            m.initialize();
            Result r = m.getResult();
            log.info( "cell count = " + r.getCells().size() );
            assertNotNull( r );
            assertTrue( "sample query returned " + r.getCells().size() +
                " cells, when expecting " + expectedNumCells,
                r.getCells().size() == expectedNumCells );
        } catch (OlapException e) {
            log.error(e);
            throw new RuntimeException(e);
        }
    }

    /*
    public void testOlapUnitFind() {
	ResourceLookup[] results 
	    = getRepository().findResource(null, FilterCriteria.createFilter(OlapUnit.class));
	assertTrue("got results: " + results.length + " when expecting 6", 
		   results.length == (DO_PSEUDO_JAPANESE_FOODMART ? 1 : 0) + 6);
    }
    */

    private OlapModel getModel( String viewName ) {
        OlapUnit unit = (OlapUnit)getRepositoryService().getResource( null, "/analysis/views/" + viewName );
        OlapModel olapModel = null;
        try {
            olapModel = getOlapConnectionService().createOlapModel( null, unit );
        } catch(Exception e) {
            if (e instanceof JSException) {
                log.error(e.getMessage());
            }
        }
        return olapModel;

//        Can't do initializeOlapModel: JPivot throws exception
//        com.tonbeller.wcf.controller.EmptyThreadLocalStackException
//            at com.tonbeller.wcf.controller.ThreadLocalStack.peek(ThreadLocalStack.java:35)
//            at com.tonbeller.wcf.controller.RequestContext.instance(RequestContext.java:57)
//            at com.jaspersoft.jasperserver.api.metadata.olap.service.impl.OlapConnectionServiceImpl.initializeOlapModel(OlapConnectionServiceImpl.java:355)
//            at com.jaspersoft.jasperserver.api.metadata.OlapConnectionTest.getModel(OlapConnectionTest.java:570)
//            at com.jaspersoft.jasperserver.api.metadata.OlapConnectionTest.olapUnitTest(OlapConnectionTest.java:482)

        //return getConnectionService().initializeOlapModel(null, unit, new MockHttpSession(null));
    }

    /**
     * property: repository
     */
    //private RepositoryService mRepository;
    //public RepositoryService getRepositoryService() {
    //    return mRepository;
    //}
    //public void setRepositoryService(RepositoryService repository) {
    //    mRepository = repository;
    //}

    /**
     * property: olapConnectionService
     */
    //private OlapConnectionService mConnectionService;
    //public OlapConnectionService getOlapConnectionService() {
    //    return mConnectionService;
    //}
    //public void setOlapConnectionService( OlapConnectionService cs ) {
    //    mConnectionService = cs;
    //}

    
    private final static String FOODMART_REPORT_JRXML = "/reports/jasper/MondrianFoodMartSalesReport2006.jrxml";
    
    protected void createXmlaFoodmartReport(Folder parent) {
	createOlapFoodmartReport(parent,
				 "/analysis/reports/",
				 "FoodmartSalesXmlaReport",
				 "Foodmart XML/A Sales Report",
				 "Report with XML/A Datasource",
				 "/analysis/connections/FoodmartXmlaConnection");
    }

    protected void createMondrianFoodmartReport(Folder parent) {
	createOlapFoodmartReport(parent,
				 "/analysis/reports/",
				 "FoodmartSalesMondrianReport",
				 "Foodmart Mondrian Sales Report",
				 "Report with Mondrian Datasource",
				 "/analysis/connections/Foodmart");
    }

    protected Folder createAnalysisReportsFolder() {
        return createOrUpdateFolder("/analysis", "reports", "Analysis Reports");
    }

    public void createOlapFoodmartReport(Folder parent,
					    String path,
					    String name,
					    String label,
					    String desc,
					    String connectionUri) {

        boolean newRU = false;

        ReportUnit ru = (ReportUnit) getRepositoryService().getResource(null, path + name, ReportUnit.class);

        if (ru == null) {
            ru = (ReportUnit) getRepositoryService().newResource(executionContext, ReportUnit.class);
            ru.setParentFolder(parent);
            ru.setName(name);
            newRU = true;
        }
        ru.setLabel(label);
        ru.setDescription(desc);
	
        FileResource report = null;
        
        if (!newRU) {
            report = (FileResource) ru.getMainReport().getLocalResource();
            assert(report != null);
        } else {
            report = (FileResource) getRepositoryService().newResource(executionContext, FileResource.class);
            report.setFileType(FileResource.TYPE_JRXML);
            report.setName("FoodmartSalesReportJRXML");
            report.setLabel("FoodmartSalesReportJRXML");
        }
        report.readData(getClass().getResourceAsStream(FOODMART_REPORT_JRXML));

        ru.setMainReport(report);

        ru.setDataSourceReference(connectionUri);

        getRepositoryService().saveResource(executionContext, ru);

        Resource savedResource = getRepositoryService().getResource(executionContext, path + name);
        assertNotNull(savedResource);
        assertTrue(savedResource instanceof ReportUnit);
        ReportUnit savedRU = (ReportUnit) savedResource;
        ResourceReference savedDSRef = savedRU.getDataSource();
        assertNotNull(savedDSRef);
        assertFalse(savedDSRef.isLocal());
        assertEquals(connectionUri, savedDSRef.getReferenceURI());
    }

    public Folder createOrUpdateFolder(String folderParentURI, String folderName, String folderLabel) {
       	Folder aFolder = null;

        aFolder = getRepositoryService().getFolder(null, folderParentURI + Folder.SEPARATOR + folderName);

        if (aFolder == null) {
            aFolder = new FolderImpl();
            aFolder.setParentFolder(folderParentURI);
            aFolder.setName(folderName);
        }
    	aFolder.setLabel(folderLabel);
    	getRepositoryService().saveFolder(executionContext, aFolder);
        return aFolder;
    }

    public void createOrUpdateSchemaResource(String schemaFolderParentURI,
                String schemaName,
                String schemaLabel,
                String schemaDescription,
                String resourcePath) {
        FileResource schemaResource = (FileResource) getRepositoryService().getResource(null, schemaFolderParentURI + Folder.SEPARATOR + schemaName, FileResource.class);

         if (schemaResource == null) {
             schemaResource = (FileResource) getRepositoryService().newResource( null, FileResource.class );
            schemaResource.setParentFolder(schemaFolderParentURI);
            schemaResource.setName( schemaName );
        }
        schemaResource.setLabel( schemaLabel );
        schemaResource.setDescription( schemaDescription );
        
        schemaResource.setFileType(ResourceDescriptor.TYPE_MONDRIAN_SCHEMA);
        InputStream in = getClass().getResourceAsStream( resourcePath );
        schemaResource.readData(in);
        
        getOlapConnectionService().saveResource( null, schemaFolderParentURI, schemaResource );
    }

    public void createJDBCDataSourceResource(String dataSourceFolderParentURI,
                String dataSourceName,
                String dataSourceLabel,
                String dataSourceDescription,
                String driverClassName,
                String connectionURL,
                String username,
                String password) {
        JdbcReportDataSource dataSourceResource = (JdbcReportDataSource) getRepositoryService().getResource(null, dataSourceFolderParentURI + Folder.SEPARATOR + dataSourceName, JdbcReportDataSource.class);
        if (dataSourceResource == null) {
            dataSourceResource = (JdbcReportDataSource) getRepositoryService().newResource( null, JdbcReportDataSource.class );
            dataSourceResource.setParentFolder(dataSourceFolderParentURI);
            dataSourceResource.setName( dataSourceName );
        }
        dataSourceResource.setLabel( dataSourceLabel );
        dataSourceResource.setDescription( dataSourceDescription );
        dataSourceResource.setDriverClass(driverClassName);
        dataSourceResource.setConnectionUrl(connectionURL);
        dataSourceResource.setUsername(username);
        dataSourceResource.setPassword(password);
        getOlapConnectionService().saveResource( null, dataSourceFolderParentURI, dataSourceResource );
    }

    public void createJNDIDataSourceResource(String dataSourceFolderParentURI,
                String dataSourceName,
                String dataSourceLabel,
                String dataSourceDescription,
                String jndiURI) {
        JndiJdbcReportDataSource dataSourceResource = (JndiJdbcReportDataSource) getRepositoryService().getResource(null, dataSourceFolderParentURI + Folder.SEPARATOR + dataSourceName, JndiJdbcReportDataSource.class);
        if (dataSourceResource == null) {
            dataSourceResource = (JndiJdbcReportDataSource) getRepositoryService().newResource( null, JndiJdbcReportDataSource.class );
            dataSourceResource.setParentFolder(dataSourceFolderParentURI);
            dataSourceResource.setName( dataSourceName );
        }
        dataSourceResource.setLabel( dataSourceLabel );
        dataSourceResource.setDescription( dataSourceDescription );
        dataSourceResource.setJndiName(jndiURI);
        getOlapConnectionService().saveResource( null, dataSourceFolderParentURI, dataSourceResource );
    }

    public void createMondrianConnectionResource(String mondrianConnectionFolderParentURI,
                String mondrianConnectionName,
                String mondrianConnectionLabel,
                String mondrianConnectionDescription,
                String schemaURI,
                String dataSourceURI) {
        MondrianConnection mondrianConnectionResource = (MondrianConnection) getRepositoryService().getResource(null, mondrianConnectionFolderParentURI + Folder.SEPARATOR + mondrianConnectionName, MondrianConnection.class);
        if (mondrianConnectionResource == null) {
            mondrianConnectionResource = (MondrianConnection) getRepositoryService().newResource( null, MondrianConnection.class );
            mondrianConnectionResource.setParentFolder(mondrianConnectionFolderParentURI);
            mondrianConnectionResource.setName( mondrianConnectionName );
        }
        mondrianConnectionResource.setLabel(mondrianConnectionName);
        mondrianConnectionResource.setDescription(mondrianConnectionDescription);

        mondrianConnectionResource.setSchemaReference(schemaURI);
        mondrianConnectionResource.setDataSourceReference(dataSourceURI);
        getOlapConnectionService().saveResource( null, mondrianConnectionFolderParentURI, mondrianConnectionResource );
    }

    public void createXMLAConnectionResource(String xmlaConnectionFolderParentURI,
                String xmlaConnectionName,
                String xmlaConnectionLabel,
                String xmlaConnectionDescription,
                String catalog,
                String xmlaDataSource,
                String URI,
                String username,
                String password) {
        XMLAConnection xmlaConnection = (XMLAConnection) getRepositoryService().getResource(null, xmlaConnectionFolderParentURI + Folder.SEPARATOR + xmlaConnectionName, XMLAConnection.class);
        if (xmlaConnection == null) {
            xmlaConnection = (XMLAConnection) getRepositoryService().newResource( null, XMLAConnection.class );
            xmlaConnection.setParentFolder(xmlaConnectionFolderParentURI);
            xmlaConnection.setName( xmlaConnectionName );
        }
        xmlaConnection.setLabel(xmlaConnectionLabel);
        xmlaConnection.setDescription(xmlaConnectionDescription);
        xmlaConnection.setCatalog(catalog);
        xmlaConnection.setDataSource(xmlaDataSource);
        xmlaConnection.setURI(URI);
        // TODO: create a sample USER_XMLA and ROLE_XMLA_USER
        xmlaConnection.setUsername(username);
        xmlaConnection.setPassword(password);
        getOlapConnectionService().saveResource( null, xmlaConnectionFolderParentURI, xmlaConnection );
    }

    public void creatMondrianXMLADefinitionResource(String xmlaDefinitionFolderParentURI,
                String xmlaDefinitionName,
                String xmlaDefinitionLabel,
                String xmlaDefinitionDescription,
                String catalog,
                String mondrianConnectionURI) {
        MondrianXMLADefinition mondrianXmlaConnection = (MondrianXMLADefinition) getRepositoryService().getResource(null, xmlaDefinitionFolderParentURI + Folder.SEPARATOR + xmlaDefinitionName, MondrianXMLADefinition.class);
        if (mondrianXmlaConnection == null) {
            mondrianXmlaConnection = (MondrianXMLADefinition) getRepositoryService().newResource( null, MondrianXMLADefinition.class );
            mondrianXmlaConnection.setParentFolder(xmlaDefinitionFolderParentURI);
            mondrianXmlaConnection.setName( xmlaDefinitionName );
        }
        mondrianXmlaConnection.setLabel(xmlaDefinitionLabel);
        mondrianXmlaConnection.setDescription(xmlaDefinitionDescription);
        mondrianXmlaConnection.setCatalog(catalog);
        mondrianXmlaConnection.setMondrianConnectionReference(mondrianConnectionURI);

        getOlapConnectionService().saveResource( null, xmlaDefinitionFolderParentURI, mondrianXmlaConnection );
    }


    public OlapUnit creatOlapUnitResource(String olapUnitFolderParentURI,
                String olapUnitName,
                String olapUnitLabel,
                String olapUnitDescription,
                String connectionReference,
                String mdxQuery,
                boolean saveUnit) {
        OlapUnit olapUnit = (OlapUnit) getRepositoryService().getResource(null, olapUnitFolderParentURI + Folder.SEPARATOR + olapUnitName, OlapUnit.class);
        if (olapUnit == null) {
            olapUnit = (OlapUnit) getRepositoryService().newResource( null, OlapUnit.class );
            olapUnit.setParentFolder(olapUnitFolderParentURI);
            olapUnit.setName( olapUnitName );
        }
        olapUnit.setLabel(olapUnitLabel);
        olapUnit.setDescription(olapUnitDescription);
        olapUnit.setOlapClientConnectionReference(connectionReference);
        olapUnit.setMdxQuery(mdxQuery);

        if (saveUnit) {
            getOlapConnectionService().saveResource( null, olapUnitFolderParentURI, olapUnit );
        }

        return olapUnit;
    }

	public void setOlapConnectionServiceTarget(
			OlapConnectionServiceImpl olapConnectionServiceTarget) {
		this.olapConnectionServiceTarget = olapConnectionServiceTarget;
	}

	public OlapConnectionServiceImpl getOlapConnectionServiceTarget() {
		return olapConnectionServiceTarget;
	}
}
