org.pentaho.common.ui.metadata.service.MetadataService2.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.common.ui.metadata.service.MetadataService2.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 (c) 2002-2013 Pentaho Corporation..  All rights reserved.
 */

package org.pentaho.common.ui.metadata.service;

import flexjson.JSONSerializer;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONException;
import org.pentaho.common.ui.messages.Messages;
import org.pentaho.commons.connection.IPentahoResultSet;
import org.pentaho.commons.connection.marshal.MarshallableResultSet;
import org.pentaho.metadata.datatable.DataTable;
import org.pentaho.metadata.model.Domain;
import org.pentaho.metadata.model.LogicalModel;
import org.pentaho.metadata.model.thin.Model;
import org.pentaho.metadata.model.thin.ModelInfo;
import org.pentaho.metadata.model.thin.ModelInfoComparator;
import org.pentaho.metadata.model.thin.ModelProvider;
import org.pentaho.metadata.model.thin.Provider;
import org.pentaho.metadata.model.thin.Query;
import org.pentaho.metadata.query.model.util.QueryXmlHelper;
import org.pentaho.metadata.repository.IMetadataDomainRepository;
import org.pentaho.platform.api.engine.ILogger;
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.plugin.action.pentahometadata.MetadataQueryComponent;
import org.pentaho.platform.util.messages.LocaleHelper;
import org.pentaho.pms.core.exception.PentahoMetadataException;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.StringTokenizer;

/**
 * An object that makes lightweight, serializable metadata models available to callers, and allow queries to be
 * executed. All objects are simple POJOs. This object can be used as a Axis web service.
 * 
 * @author jamesdixon
 * 
 */
public class MetadataService2 extends PentahoBase implements ModelProvider {

    public static final String PROVIDER_ID = "MetadataImpl";

    private static final long serialVersionUID = 8481450224870463494L;

    private Log logger = LogFactory.getLog(MetadataService2.class);

    private Provider provider;

    public MetadataService2() {
        setLoggingLevel(ILogger.ERROR);
        provider = new Provider();
        provider.setId(PROVIDER_ID);
        provider.setName("Relational Metadata");
    }

    /**
     * Returns a list of the available business models
     * 
     * @param domainName
     *          optional domain to limit the results
     * @param context
     *          Area to check for model visibility
     * @return list of ModelInfo objects representing the available models
     * @throws IOException
     */
    @Override
    public ModelInfo[] getModelList(String providerId, String domain, String match) {

        if (providerId != null && !providerId.equals(PROVIDER_ID)) {
            return new ModelInfo[0];
        }
        List<ModelInfo> models = new ArrayList<ModelInfo>();

        // get hold of the metadata repository
        IMetadataDomainRepository repo = getMetadataRepository();
        if (repo == null) {
            error(Messages.getErrorString("MetadataService.ERROR_0001_BAD_REPO")); //$NON-NLS-1$
            return null;
        }

        try {
            if (StringUtils.isEmpty(domain)) {
                // if no domain has been specified, loop over all of them
                for (String aDomain : getMetadataRepository().getDomainIds()) {
                    getModelInfos(match, aDomain, models);
                }
            } else {
                // get the models for the specified domain
                getModelInfos(match, domain, models);
            }
        } catch (Throwable t) {
            error(Messages.getErrorString("MetadataService.ERROR_0002_BAD_MODEL_LIST"), t); //$NON-NLS-1$
        }

        Collections.sort(models, new ModelInfoComparator());
        return models.toArray(new ModelInfo[models.size()]);
    }

    /**
     * Returns a list of ModelInfo objects for the specified domain. These objects are small and this list is intended to
     * allow a client to provide a list of models to a user so the user can pick which one they want to work with.
     * 
     * @param domain
     * @param context
     *          Area to check for model visibility
     * @param models
     */
    private void getModelInfos(final String match, final String domain, List<ModelInfo> models) {

        IMetadataDomainRepository repo = getMetadataRepository();

        String context = null;
        Domain domainObject = repo.getDomain(domain);
        if (domainObject == null) {
            // the domain does not exist
            return;
        }

        // find the best locale
        String locale = LocaleHelper.getClosestLocale(LocaleHelper.getLocale().toString(),
                domainObject.getLocaleCodes());

        // iterate over all of the models in this domain
        for (LogicalModel model : domainObject.getLogicalModels()) {
            String vis = (String) model.getProperty("visible");
            if (vis != null) {
                String[] visibleContexts = vis.split(",");
                boolean visibleToContext = false;
                for (String c : visibleContexts) {
                    if (c.equals(context)) {
                        visibleToContext = true;
                        break;
                    }
                }
                if (!visibleToContext) {
                    continue;
                }
            }
            // create a new ModelInfo object and give it the envelope information about the model
            ModelInfo modelInfo = new ModelInfo();
            modelInfo.setGroupId(domain);
            modelInfo.setModelId(model.getId());
            modelInfo.setName(model.getName(locale));
            modelInfo.setProvider(provider);
            if (model.getDescription() != null) {
                String modelDescription = model.getDescription(locale);
                modelInfo.setDescription(modelDescription);
            }
            models.add(modelInfo);
        }
        return;
    }

    /**
     * Returns a Model object for the requested model. The model will include the basic metadata - categories and columns.
     * 
     * @param domainId
     * @param modelId
     * @return
     */
    @Override
    public Model getModel(String id) {

        // parse out the id
        StringTokenizer tokenizer = new StringTokenizer(id, "~");

        String providerId = null;
        String domainId = null;
        String modelId = null;
        while (tokenizer.hasMoreElements()) {
            String str = tokenizer.nextToken();
            if (providerId == null) {
                providerId = str;
            } else if (domainId == null) {
                domainId = str;
            } else {
                modelId = str;
            }
        }

        if (domainId == null) {
            // we can't do this without a model
            error(Messages.getErrorString("MetadataService.ERROR_0003_NULL_DOMAIN")); //$NON-NLS-1$
            return null;
        }

        if (modelId == null) {
            // we can't do this without a model
            error(Messages.getErrorString("MetadataService.ERROR_0004_NULL_Model")); //$NON-NLS-1$
            return null;
        }

        // because it's lighter weight, check the thin model
        Domain domain = getMetadataRepository().getDomain(domainId);
        if (domain == null) {
            error(Messages.getErrorString("MetadataService.ERROR_0005_DOMAIN_NOT_FOUND", domainId)); //$NON-NLS-1$
            return null;
        }

        LogicalModel model = domain.findLogicalModel(modelId);

        if (model == null) {
            // the model cannot be found or cannot be loaded
            error(Messages.getErrorString("MetadataService.ERROR_0006_MODEL_NOT_FOUND", modelId)); //$NON-NLS-1$
            return null;
        }

        // create the thin metadata model and return it
        MetadataServiceUtil2 util = new MetadataServiceUtil2();
        util.setDomain(domain);
        Model thinModel = util.createThinModel(model, domainId);
        thinModel.setProvider(provider);
        return thinModel;

    }

    /**
     * Executes a query model and returns a serializable result set
     * 
     * @param query
     * @param rowLimit
     *          An optional row limit, -1 or null means all rows
     * @return
     */
    @Override
    public DataTable executeQuery(Query query, int rowLimit) {
        return null;
    }

    public MarshallableResultSet doQuery(Query query, Integer rowLimit) {

        MetadataServiceUtil2 util = new MetadataServiceUtil2();

        Model model = getModel(query.getSourceId());

        org.pentaho.metadata.query.model.Query fullQuery = util.convertQuery(query, model);
        QueryXmlHelper helper = new QueryXmlHelper();
        String xml = helper.toXML(fullQuery);
        return doXmlQuery(xml, rowLimit);
    }

    /**
     * Executes a XML query and returns a serializable result set
     * 
     * @param query
     * @param rowLimit
     *          An optional row limit, -1 or null means all rows
     * @return
     */
    public MarshallableResultSet doXmlQuery(String xml, Integer rowLimit) {
        IPentahoResultSet resultSet = executeQuery(xml, rowLimit);
        if (resultSet == null) {
            return null;
        }
        MarshallableResultSet result = new MarshallableResultSet();
        result.setResultSet(resultSet);
        return result;
    }

    /**
     * Executes a XML query and returns a JSON serialization of the result set
     * 
     * @param query
     * @param rowLimit
     * @return
     */
    public String doXmlQueryToJson(String xml, int rowLimit) {
        MarshallableResultSet resultSet = doXmlQuery(xml, rowLimit);
        if (resultSet == null) {
            return null;
        }
        JSONSerializer serializer = new JSONSerializer();
        String json = serializer.deepSerialize(resultSet);
        return json;
    }

    /**
     * Executes a XML query and returns a CDA compatible JSON serialization of the result set
     * 
     * @param query
     * @param rowLimit
     * @return
     */
    public String doXmlQueryToCdaJson(String xml, int rowLimit) {
        IPentahoResultSet resultSet = executeQuery(xml, rowLimit);
        if (resultSet == null) {
            return null;
        }
        String json = null;
        try {
            MetadataServiceUtil2 util = new MetadataServiceUtil2();
            Domain domain = util.getDomainObject(xml);
            util.setDomain(domain);
            String locale = LocaleHelper.getClosestLocale(LocaleHelper.getLocale().toString(),
                    domain.getLocaleCodes());
            json = util.createCdaJson(resultSet, locale);
        } catch (JSONException e) {
            error(Messages.getErrorString("MetadataService.ERROR_0007_JSON_ERROR"), e); //$NON-NLS-1$
        } catch (PentahoMetadataException e) {
            error(Messages.getErrorString("MetadataService.ERROR_0007_BAD_QUERY_DOMAIN"), e); //$NON-NLS-1$
        }
        return json;
    }

    /**
     * Executes a XML query and returns a serializable result set
     * 
     * @param query
     * @param rowLimit
     *          An optional row limit, -1 or null means all rows
     * @return
     */
    public MarshallableResultSet doJsonQuery(String json, Integer rowLimit) {

        // return the results
        return doXmlQuery(getQueryXmlFromJson(json), rowLimit);
    }

    /**
     * Executes a XML query and returns a JSON serialization of the result set
     * 
     * @param query
     * @param rowLimit
     * @return
     */
    public String doJsonQueryToJson(String json, int rowLimit) {
        // return the results
        return doXmlQueryToJson(getQueryXmlFromJson(json), rowLimit);
    }

    /**
     * Executes a XML query and returns a CDA compatible JSON serialization of the result set
     * 
     * @param query
     * @param rowLimit
     * @return
     */
    public String doJsonQueryToCdaJson(String json, int rowLimit) {
        // return the results
        return doXmlQueryToCdaJson(getQueryXmlFromJson(json), rowLimit);
    }

    /**
     * Executes a XML query and returns a native result set
     * 
     * @param query
     * @param rowLimit
     *          An optional row limit, -1 or null means all rows
     * @return
     */
    protected IPentahoResultSet executeQuery(String query, Integer rowLimit) {
        // create a component to execute the query
        MetadataQueryComponent dataComponent = new MetadataQueryComponent();
        dataComponent.setQuery(query);
        dataComponent.setLive(false);
        dataComponent.setUseForwardOnlyResultSet(true);
        if (rowLimit != null && rowLimit > -1) {
            // set the row limit
            dataComponent.setMaxRows(rowLimit);
        }
        if (dataComponent.execute()) {
            return dataComponent.getResultSet();
        }
        return null;
    }

    /**
     * Converts a JSON query into a full Query object by going via a thin Query object
     * 
     * @param json
     * @return
     */
    protected String getQueryXmlFromJson(String json) {
        MetadataServiceUtil2 util = new MetadataServiceUtil2();
        Query query = util.deserializeJsonQuery(json);
        try {
            // convert the thin query model into a full one
            Model model = getModel(query.getSourceId());
            org.pentaho.metadata.query.model.Query fullQuery = util.convertQuery(query, model);

            // get the XML for the query
            QueryXmlHelper helper = new QueryXmlHelper();
            String xml = helper.toXML(fullQuery);
            return xml;
        } catch (Exception e) {
            error(Messages.getErrorString("MetadataService.ERROR_0008_BAD_QUERY"), e); //$NON-NLS-1$
        }
        return null;
    }

    /**
     * Returns a instance of the IMetadataDomainRepository for the current session
     * 
     * @return
     */
    protected IMetadataDomainRepository getMetadataRepository() {
        IMetadataDomainRepository mdr = PentahoSystem.get(IMetadataDomainRepository.class,
                PentahoSessionHolder.getSession());
        if (mdr instanceof ILogger) {
            ((ILogger) mdr).setLoggingLevel(getLoggingLevel());
        }
        return mdr;
    }

    @Override
    public Log getLogger() {
        return logger;
    }

    @Override
    public String getId() {
        return PROVIDER_ID;
    }

}