org.pentaho.platform.dataaccess.datasource.wizard.service.impl.ModelerService.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.platform.dataaccess.datasource.wizard.service.impl.ModelerService.java

Source

/*
 * This program is free software; you can redistribute it and/or modify it under the 
 * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software 
 * Foundation.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this 
 * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html 
 * or from the Free Software Foundation, Inc., 
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * 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 Lesser General Public License for more details.
 *
 * Copyright 2009-2010 Pentaho Corporation.  All rights reserved.
 *
 * Created Sep, 2010
 * @author jdixon
 */
package org.pentaho.platform.dataaccess.datasource.wizard.service.impl;

import java.io.File;
import java.util.ArrayList;
import java.util.Locale;

import mondrian.xmla.DataSourcesConfig.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.pentaho.agilebi.modeler.IModelerSource;
import org.pentaho.agilebi.modeler.ModelerMessagesHolder;
import org.pentaho.agilebi.modeler.ModelerWorkspace;
import org.pentaho.agilebi.modeler.gwt.BogoPojo;
import org.pentaho.agilebi.modeler.gwt.GwtModelerWorkspaceHelper;
import org.pentaho.agilebi.modeler.services.IModelerService;
import org.pentaho.agilebi.modeler.util.SpoonModelerMessages;
import org.pentaho.agilebi.modeler.util.TableModelerSource;
import org.pentaho.di.core.Props;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.metadata.model.Domain;
import org.pentaho.metadata.model.LogicalModel;
import org.pentaho.metadata.model.SqlPhysicalModel;
import org.pentaho.metadata.repository.IMetadataDomainRepository;
import org.pentaho.metadata.util.MondrianModelExporter;
import org.pentaho.metadata.util.XmiParser;
import org.pentaho.platform.api.engine.IApplicationContext;
import org.pentaho.platform.api.engine.IPentahoObjectFactory;
import org.pentaho.platform.api.engine.IPentahoSession;
import org.pentaho.platform.api.repository.ISolutionRepository;
import org.pentaho.platform.dataaccess.datasource.wizard.service.agile.AgileHelper;
import org.pentaho.platform.dataaccess.datasource.wizard.service.impl.utils.InlineSqlModelerSource;
import org.pentaho.platform.engine.core.solution.ActionInfo;
import org.pentaho.platform.engine.core.system.PentahoBase;
import org.pentaho.platform.engine.core.system.PentahoSessionHolder;
import org.pentaho.platform.engine.core.system.PentahoSystem;
import org.pentaho.platform.engine.services.metadata.MetadataPublisher;
import org.pentaho.platform.plugin.action.kettle.KettleSystemListener;
import org.pentaho.platform.plugin.action.mondrian.catalog.IMondrianCatalogService;
import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCatalog;
import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianCube;
import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianDataSource;
import org.pentaho.platform.plugin.action.mondrian.catalog.MondrianSchema;

/**
 * User: nbaker
 * Date: Jul 16, 2010
 */
public class ModelerService extends PentahoBase implements IModelerService {

    private static final Log logger = LogFactory.getLog(ModelerService.class);
    public static final String TMP_FILE_PATH = File.separatorChar + "system" + File.separatorChar
            + File.separatorChar + "tmp" + File.separatorChar;

    public Log getLogger() {
        return logger;
    }

    static {
        try {
            // try to set the modelermessages.  at this point, just give it the spoon messages.  no need to give it
            // GWT messages, this is a server-side function.
            ModelerMessagesHolder.setMessages(new SpoonModelerMessages());
        } catch (IllegalStateException e) {
            logger.debug(e.getMessage(), e);
        }
    }

    protected void initKettle() {

        try {
            KettleSystemListener.environmentInit(PentahoSessionHolder.getSession());
            if (Props.isInitialized() == false) {
                Props.init(Props.TYPE_PROPERTIES_EMPTY);
            }
        } catch (KettleException e) {
            logger.error(e);
            throw new IllegalStateException("Failed to initialize Kettle system"); //$NON-NLS-1$
        }
    }

    //TODO: remove this method in favor so specific calls
    @Deprecated
    public Domain generateDomain(String connectionName, String tableName, String dbType, String query,
            String datasourceName) throws Exception {
        initKettle();
        try {
            DatabaseMeta database = AgileHelper.getDatabaseMeta();
            IModelerSource source;
            if (tableName != null) {
                source = new TableModelerSource(database, tableName, null, datasourceName);
            } else {
                source = new InlineSqlModelerSource(connectionName, dbType, query, datasourceName);
            }
            return source.generateDomain();
        } catch (Exception e) {
            logger.error(e);
            throw new Exception(e.getLocalizedMessage());
        }
    }

    public Domain generateCSVDomain(String tableName, String datasourceName) throws Exception {
        initKettle();
        try {
            DatabaseMeta database = AgileHelper.getDatabaseMeta();
            IModelerSource source = new TableModelerSource(database, tableName, null, datasourceName);
            return source.generateDomain();
        } catch (Exception e) {
            logger.error(e);
            throw new Exception(e.getLocalizedMessage());
        }
    }

    public BogoPojo gwtWorkaround(BogoPojo pojo) {
        return new BogoPojo();
    }

    public String serializeModels(Domain domain, String name) throws Exception {
        return serializeModels(domain, name, true);
    }

    public String serializeModels(Domain domain, String name, boolean doOlap) throws Exception {
        String domainId = null;
        initKettle();

        try {
            ModelerWorkspace model = new ModelerWorkspace(new GwtModelerWorkspaceHelper());
            model.setModelName(name);
            model.setDomain(domain);
            String solutionStorage = AgileHelper.getDatasourceSolutionStorage();

            String metadataLocation = "resources" + ISolutionRepository.SEPARATOR + "metadata"; //$NON-NLS-1$  //$NON-NLS-2$

            String path = solutionStorage + ISolutionRepository.SEPARATOR + metadataLocation
                    + ISolutionRepository.SEPARATOR;
            domainId = path + name + ".xmi"; //$NON-NLS-1$ 
            domain.setId(domainId);

            IApplicationContext appContext = PentahoSystem.getApplicationContext();
            if (appContext != null) {
                path = PentahoSystem.getApplicationContext().getSolutionPath(path);
            }

            File pathDir = new File(path);
            if (!pathDir.exists()) {
                pathDir.mkdirs();
            }

            IPentahoObjectFactory pentahoObjectFactory = PentahoSystem.getObjectFactory();
            IPentahoSession session = pentahoObjectFactory.get(IPentahoSession.class, "systemStartupSession", null); //$NON-NLS-1$

            ISolutionRepository repository = PentahoSystem.get(ISolutionRepository.class, session);

            LogicalModel lModel = domain.getLogicalModels().get(0);
            String catName = lModel.getName(Locale.getDefault().toString());

            cleanseExistingCatalog(catName, session);
            if (doOlap) {
                lModel.setProperty("MondrianCatalogRef", catName); //$NON-NLS-1$
            }
            XmiParser parser = new XmiParser();
            String reportXML = parser.generateXmi(model.getDomain());

            // Serialize domain to xmi.
            String base = PentahoSystem.getApplicationContext().getSolutionRootPath();
            String parentPath = ActionInfo.buildSolutionPath(solutionStorage, metadataLocation, ""); //$NON-NLS-1$
            int status = repository.publish(base, '/' + parentPath, name + ".xmi", reportXML.getBytes("UTF-8"), //$NON-NLS-1$//$NON-NLS-2$
                    true);
            if (status != ISolutionRepository.FILE_ADD_SUCCESSFUL) {
                throw new RuntimeException("Unable to save to repository. Status: " + status); //$NON-NLS-1$
            }

            // Serialize domain to olap schema.
            if (doOlap) {
                MondrianModelExporter exporter = new MondrianModelExporter(lModel, Locale.getDefault().toString());
                String mondrianSchema = exporter.createMondrianModelXML();
                Document schemaDoc = DocumentHelper.parseText(mondrianSchema);
                byte[] schemaBytes = schemaDoc.asXML().getBytes("UTF-8"); //$NON-NLS-1$

                status = repository.publish(base, '/' + parentPath, name + ".mondrian.xml", schemaBytes, true); //$NON-NLS-1$
                if (status != ISolutionRepository.FILE_ADD_SUCCESSFUL) {
                    throw new RuntimeException("Unable to save to repository. Status: " + status); //$NON-NLS-1$
                }

                // Refresh Metadata
                PentahoSystem.publish(session, MetadataPublisher.class.getName());

                // Write this catalog to the default Pentaho DataSource and refresh the cache.
                File file = new File(path + name + ".mondrian.xml"); //$NON-NLS-1$
                // Need to find a better way to get the connection name instead of using the Id.
                String catConnectStr = "Provider=mondrian;DataSource=" //$NON-NLS-1$
                        + ((SqlPhysicalModel) domain.getPhysicalModels().get(0)).getId();
                String catDef = "solution:" + solutionStorage + ISolutionRepository.SEPARATOR //$NON-NLS-1$
                        + "resources" + ISolutionRepository.SEPARATOR + "metadata" + ISolutionRepository.SEPARATOR //$NON-NLS-1$//$NON-NLS-2$
                        + file.getName();
                addCatalog(catName, catConnectStr, catDef, session);
            }

        } catch (Exception e) {
            logger.error(e);
            throw e;
        }
        return domainId;
    }

    private void cleanseExistingCatalog(String catName, IPentahoSession session) {

        // If mondrian catalog exists delete it to avoid duplicates and orphan entries in the datasources.xml registry.
        //IPentahoSession session = PentahoSessionHolder.getSession();
        if (session != null) {
            IMondrianCatalogService service = PentahoSystem.get(IMondrianCatalogService.class, null);
            MondrianCatalog catalog = service.getCatalog(catName, session);
            if (catalog != null) {
                service.removeCatalog(catName, session);
            }
        }
    }

    private void addCatalog(String catName, String catConnectStr, String catDef, IPentahoSession session) {

        IMondrianCatalogService mondrianCatalogService = PentahoSystem.get(IMondrianCatalogService.class,
                "IMondrianCatalogService", session); //$NON-NLS-1$

        String dsUrl = PentahoSystem.getApplicationContext().getBaseUrl();
        if (!dsUrl.endsWith("/")) { //$NON-NLS-1$
            dsUrl += "/"; //$NON-NLS-1$
        }
        dsUrl += "Xmla"; //$NON-NLS-1$

        MondrianDataSource ds = new MondrianDataSource("Provider=Mondrian;DataSource=Pentaho", //$NON-NLS-1$
                "Pentaho BI Platform Datasources", //$NON-NLS-1$
                dsUrl, "Provider=Mondrian", // no default jndi datasource should be specified //$NON-NLS-1$
                "PentahoXMLA", //$NON-NLS-1$
                DataSource.PROVIDER_TYPE_MDP, DataSource.AUTH_MODE_UNAUTHENTICATED, null);

        MondrianCatalog cat = new MondrianCatalog(catName, catConnectStr, catDef, ds,
                new MondrianSchema(catName, new ArrayList<MondrianCube>()));

        mondrianCatalogService.addCatalog(cat, true, session);
    }

    public Domain loadDomain(String id) throws Exception {
        IMetadataDomainRepository repo = PentahoSystem.get(IMetadataDomainRepository.class);
        return repo.getDomain(id);
    }
}