/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU General Public License, version 2 as published by the Free Software * Foundation. * * You should have received a copy of the GNU General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/gpl-2.0.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 General Public License for more details. * * Copyright 2007 - 2008 Pentaho Corporation. All rights reserved. * */ package org.pentaho.platform.uifoundation.component.xml; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.pentaho.commons.connection.IPentahoResultSet; import org.pentaho.metadata.model.Category; import org.pentaho.metadata.model.Domain; import org.pentaho.metadata.model.LogicalColumn; import org.pentaho.metadata.model.LogicalModel; import org.pentaho.metadata.model.concept.types.DataType; import org.pentaho.metadata.model.concept.types.LocalizedString; import org.pentaho.metadata.repository.IMetadataDomainRepository; import org.pentaho.platform.api.engine.IParameterProvider; import org.pentaho.platform.api.engine.IPentahoUrlFactory; import org.pentaho.platform.api.engine.IRuntimeContext; import org.pentaho.platform.engine.core.solution.SimpleParameterProvider; import org.pentaho.platform.engine.core.system.PentahoSystem; import org.pentaho.platform.engine.services.solution.SolutionHelper; import org.pentaho.platform.uifoundation.messages.Messages; import org.pentaho.platform.util.messages.LocaleHelper; public class PMDUIComponent extends XmlComponent { private static final long serialVersionUID = -911457505257919399L; private static final Log logger = LogFactory.getLog(PMDUIComponent.class); public static final int ACTION_LIST_DOMAINS = 1; public static final int ACTION_LIST_MODELS = 2; public static final int ACTION_MODELS_DETAIL = 3; public static final int ACTION_LOAD_MODEL = 4; public static final int ACTION_LOOKUP = 5; private int action; private String domainName; private String modelId; private String columnId; private IParameterProvider parameters; public PMDUIComponent(final IPentahoUrlFactory urlFactory, final List messages) { super(urlFactory, messages, ""); //$NON-NLS-1$ } @Override public Log getLogger() { return PMDUIComponent.logger; } @Override public boolean validate() { return true; } public IMetadataDomainRepository getMetadataRepository() { return PentahoSystem.get(IMetadataDomainRepository.class, getSession()); } @Override public Document getXmlContent() { if (action == PMDUIComponent.ACTION_LIST_MODELS) { return listModels(); } else if (action == PMDUIComponent.ACTION_LOAD_MODEL) { return loadModel(); } else if (action == PMDUIComponent.ACTION_LOOKUP) { return getLookup(); } else { throw new RuntimeException(Messages.getInstance().getErrorString( "PMDUIComponent.ERROR_0002_ILLEGAL_ACTION", String.valueOf(action))); //$NON-NLS-1$ } } private Document listModels() { // Create a document that describes the result Document doc = DocumentHelper.createDocument(); Element root = doc.addElement("metadata"); //$NON-NLS-1$ Element modelsNode = root.addElement("models"); //$NON-NLS-1$ if (domainName == null) { try { for (String domain : getMetadataRepository().getDomainIds()) { addThinDomainModels(domain, modelsNode, root); } } catch (Throwable t) { error(Messages.getInstance().getString("PMDUIComponent.ERROR_0001_GET_MODEL_LIST")); //$NON-NLS-1$ t.printStackTrace(); root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_NO_DOMAIN_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$ } } else { addThinDomainModels(domainName, modelsNode, root); } return doc; } private void addThinDomainModels(final String domain, final Element modelsNode, final Element root) { IMetadataDomainRepository repo = getMetadataRepository(); Domain domainObject = repo.getDomain(domain); String locale = LocaleHelper.getClosestLocale(LocaleHelper.getLocale().toString(), domainObject.getLocaleCodes()); Element modelNode; for (LogicalModel model : domainObject.getLogicalModels()) { modelNode = modelsNode.addElement("model"); //$NON-NLS-1$ modelNode.addElement("domain_id").setText(domain); //$NON-NLS-1$ if (model.getId() != null) { modelNode.addElement("model_id").setText(model.getId()); //$NON-NLS-1$ } String modelName = model.getName(locale); if (modelName != null) { modelNode.addElement("model_name").setText(modelName); //$NON-NLS-1$ } if (model.getDescription() != null) { String modelDescription = model.getDescription(locale); if (modelDescription != null) { modelNode.addElement("model_description").setText(modelDescription); //$NON-NLS-1$ } } } return; } private Document loadModel() { // Create a document that describes the result Document doc = DocumentHelper.createDocument(); Element root = doc.addElement("metadata"); //$NON-NLS-1$ if (domainName == null) { // we can't do this without a model root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_NO_DOMAIN_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$ return doc; } if (modelId == null) { // we can't do this without a model root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_NO_MODEL_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$ return doc; } Element modelNode = root.addElement("model"); //$NON-NLS-1$ // because it's lighter weight, check the thin model Domain domain = getMetadataRepository().getDomain(domainName); if (domain == null) { root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_DOMAIN_LOADING_ERROR", domainName)); //$NON-NLS-1$ //$NON-NLS-2$ return doc; } String locale = LocaleHelper.getClosestLocale(LocaleHelper.getLocale().toString(), domain.getLocaleCodes()); LogicalModel model = domain.findLogicalModel(modelId); if (model == null) { root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_MODEL_LOADING_ERROR", modelId)); //$NON-NLS-1$ //$NON-NLS-2$ error(Messages.getInstance().getString("PMDUIComponent.USER_MODEL_LOADING_ERROR", modelId)); //$NON-NLS-1$ return doc; } modelNode.addElement("domain_id").setText(domainName); //$NON-NLS-1$ if (model.getId() != null) { modelNode.addElement("model_id").setText(model.getId()); //$NON-NLS-1$ } if (model.getName(locale) != null) { modelNode.addElement("model_name").setText(model.getName(locale)); //$NON-NLS-1$ } if (model.getDescription(locale) != null) { modelNode.addElement("model_description").setText(model.getDescription(locale)); //$NON-NLS-1$ } Element tableNode; for (Category category : model.getCategories()) { tableNode = modelNode.addElement("view"); //$NON-NLS-1$ if (category.getId() != null) { tableNode.addElement("view_id").setText(category.getId()); //$NON-NLS-1$ } if (category.getName(locale) != null) { tableNode.addElement("view_name").setText(category.getName(locale)); //$NON-NLS-1$ } if (category.getDescription(locale) != null) { tableNode.addElement("view_description").setText(category.getDescription(locale)); //$NON-NLS-1$ } for (LogicalColumn column : category.getLogicalColumns()) { Boolean hidden = (Boolean)column.getProperty("hidden"); //$NON-NLS-1$ if (hidden != null && hidden) { continue; } addColumn(column, tableNode, locale); } } return doc; } public void addColumn(final LogicalColumn column, final Element tableNode, final String locale) { Element columnNode = tableNode.addElement("column"); //$NON-NLS-1$ if (column.getId() != null) { columnNode.addElement("column_id").setText(column.getId()); //$NON-NLS-1$ } if (column.getName(locale) != null) { columnNode.addElement("column_name").setText(column.getName(locale)); //$NON-NLS-1$ } if (column.getDescription(locale) != null) { columnNode.addElement("column_description").setText(column.getDescription(locale)); //$NON-NLS-1$ } if (column.getFieldType() != null) { // TODO this should take a locale String desc = column.getFieldType().getDescription(); desc = org.pentaho.pms.messages.Messages.getString(desc); columnNode.addElement("column_field_type").setText(desc); //$NON-NLS-1$ } DataType dataType = column.getDataType(); if (dataType != null) { columnNode.addElement("column_type").setText(dataType.getName()); //$NON-NLS-1$ } if (column.getProperty("lookup") != null) { //$NON-NLS-1$ columnNode.addElement("column_lookup").setText("true"); //$NON-NLS-1$ //$NON-NLS-2$ } } public Document getLookup() { // Create a document that describes the result Document doc = DocumentHelper.createDocument(); Element root = doc.addElement("metadata"); //$NON-NLS-1$ if (domainName == null) { // we can't do this without a model root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_NO_DOMAIN_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$ return doc; } if (modelId == null) { // we can't do this without a view root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_NO_MODEL_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$ return doc; } if (columnId == null) { // we can't do this without a view root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_NO_COLUMN_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$ return doc; } Domain domain = getMetadataRepository().getDomain(domainName); String locale = LocaleHelper.getClosestLocale(LocaleHelper.getLocale().toString(), domain.getLocaleCodes()); LogicalModel model = domain.findLogicalModel(modelId); // This is the business view that was selected. if (model == null) { root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_MODEL_LOADING_ERROR", modelId)); //$NON-NLS-1$ //$NON-NLS-2$ return doc; } LogicalColumn column = model.findLogicalColumn(columnId); if (column == null) { root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_COLUMN_NOT_FOUND")); //$NON-NLS-1$ //$NON-NLS-2$ return doc; } // Temporary hack to get the BusinessCategory. When fixed properly, you should be able to interrogate the // business column thingie for it's containing BusinessCategory. Category view = null; for (Category category : model.getCategories()) { for (LogicalColumn col : category.getLogicalColumns()) { if (col.getId().equals(column.getId())) { view = category; break; } } } if (view == null) { root.addElement("message").setText(Messages.getInstance().getString("PMDUIComponent.USER_VIEW_NOT_FOUND")); //$NON-NLS-1$ //$NON-NLS-2$ return doc; } String mql = "<mql><domain_type>relational</domain_type><domain_id>" + domainName + "</domain_id><model_id>" + modelId + "</model_id>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if (column.getProperty("lookup") == null) { //$NON-NLS-1$ mql += "<selection><view>" + view.getId() + "</view><column>" + column.getId() + "</column></selection>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ mql += "<orders><order><direction>asc</direction><view_id>" + view.getId() + "</view_id><column_id>" + column.getId() + "</column_id></order></orders>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } else { String lookup = (String)column.getProperty("lookup"); //$NON-NLS-1$ // assume model and view are the same... StringTokenizer tokenizer1 = new StringTokenizer(lookup, ";"); //$NON-NLS-1$ while (tokenizer1.hasMoreTokens()) { StringTokenizer tokenizer2 = new StringTokenizer(tokenizer1.nextToken(), "."); //$NON-NLS-1$ if (tokenizer2.countTokens() == 2) { String lookupViewId = tokenizer2.nextToken(); String lookupColumnId = tokenizer2.nextToken(); mql += "<selection><view>" + lookupViewId + "</view><column>" + lookupColumnId + "</column></selection>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } } } mql += "</mql>"; //$NON-NLS-1$ ArrayList messages = new ArrayList(); SimpleParameterProvider lookupParameters = new SimpleParameterProvider(); lookupParameters.setParameter("mql", mql); //$NON-NLS-1$ IRuntimeContext runtime = SolutionHelper.doAction( "system", "metadata", "PickList.xaction", "lookup-list", lookupParameters, getSession(), messages, this); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ IPentahoResultSet results = null; if (runtime != null) { if (runtime.getStatus() == IRuntimeContext.RUNTIME_STATUS_SUCCESS) { if (runtime.getOutputNames().contains("data")) { //$NON-NLS-1$ results = runtime.getOutputParameter("data").getValueAsResultSet(); //$NON-NLS-1$ Object[][] columnHeaders = results.getMetaData().getColumnHeaders(); boolean hasColumnHeaders = columnHeaders != null; Element rowElement; Element dataElement = root.addElement("data"); //$NON-NLS-1$ if (hasColumnHeaders) { for (int rowNo = 0; rowNo < columnHeaders.length; rowNo++) { rowElement = dataElement.addElement("COLUMN-HDR-ROW"); //$NON-NLS-1$ for (int columnNo = 0; columnNo < columnHeaders[rowNo].length; columnNo++) { Object nameAttr = results.getMetaData().getAttribute(rowNo, columnNo, "name"); //$NON-NLS-1$ if ((nameAttr != null) && (nameAttr instanceof LocalizedString)) { LocalizedString str = (LocalizedString) nameAttr; String name = str.getLocalizedString(locale); if (name != null) { rowElement.addElement("COLUMN-HDR-ITEM").setText(name); //$NON-NLS-1$ } else { rowElement.addElement("COLUMN-HDR-ITEM").setText(columnHeaders[rowNo][columnNo].toString()); //$NON-NLS-1$ } } else { rowElement.addElement("COLUMN-HDR-ITEM").setText(columnHeaders[rowNo][columnNo].toString()); //$NON-NLS-1$ } } } } Object row[] = results.next(); while (row != null) { rowElement = dataElement.addElement("DATA-ROW"); //$NON-NLS-1$ for (Object element : row) { if (element == null) { rowElement.addElement("DATA-ITEM").setText(""); //$NON-NLS-1$ //$NON-NLS-2$ } else { rowElement.addElement("DATA-ITEM").setText(element.toString()); //$NON-NLS-1$ } } row = results.next(); } } } } return doc; } public void setAction(final int action) { this.action = action; } public int getAction() { return action; } public void setDomainName(final String domainName) { this.domainName = domainName; } public String getDomainName() { return domainName; } public IParameterProvider getParameters() { return parameters; } public void setParameters(final IParameterProvider parameters) { this.parameters = parameters; } public String getModelId() { return modelId; } public void setModelId(final String modelId) { this.modelId = modelId; } public String getColumnId() { return columnId; } public void setColumnId(final String columnId) { this.columnId = columnId; } }