001: /*
002: * Copyright 2007 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
007: * BI Platform. The Initial Developer is Pentaho Corporation.
008: *
009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
011: * the license for the specific language governing your rights and limitations.
012: */
013: package org.pentaho.ui.component;
014:
015: import java.util.ArrayList;
016: import java.util.Collections;
017: import java.util.Comparator;
018: import java.util.Iterator;
019: import java.util.List;
020: import java.util.StringTokenizer;
021:
022: import org.apache.commons.logging.Log;
023: import org.apache.commons.logging.LogFactory;
024: import org.dom4j.Document;
025: import org.dom4j.DocumentHelper;
026: import org.dom4j.Element;
027: import org.pentaho.commons.connection.IPentahoResultSet;
028: import org.pentaho.core.runtime.IRuntimeContext;
029: import org.pentaho.core.solution.IParameterProvider;
030: import org.pentaho.core.solution.SimpleParameterProvider;
031: import org.pentaho.core.system.PentahoSystem;
032: import org.pentaho.core.ui.IPentahoUrlFactory;
033: import org.pentaho.messages.Messages;
034: import org.pentaho.messages.util.LocaleHelper;
035: import org.pentaho.plugin.mql.MetadataPublisher;
036: import org.pentaho.pms.core.CWM;
037: import org.pentaho.pms.factory.CwmSchemaFactoryInterface;
038: import org.pentaho.pms.schema.BusinessCategory;
039: import org.pentaho.pms.schema.BusinessColumn;
040: import org.pentaho.pms.schema.BusinessModel;
041: import org.pentaho.pms.schema.SchemaMeta;
042: import org.pentaho.pms.schema.concept.ConceptUtilityInterface;
043: import org.pentaho.pms.schema.concept.types.datatype.DataTypeSettings;
044: import org.pentaho.pms.schema.concept.types.localstring.ConceptPropertyLocalizedString;
045: import org.pentaho.pms.schema.concept.types.localstring.LocalizedStringSettings;
046: import org.pentaho.pms.util.UniqueList;
047: import org.pentaho.ui.ChartHelper;
048: import org.pentaho.ui.XmlComponent;
049:
050: public class PMDUIComponent extends XmlComponent {
051:
052: private static final long serialVersionUID = -911457505257919399L;
053:
054: private static final Log logger = LogFactory
055: .getLog(PMDUIComponent.class);
056:
057: public static final int ACTION_LIST_DOMAINS = 1;
058:
059: public static final int ACTION_LIST_MODELS = 2;
060:
061: public static final int ACTION_MODELS_DETAIL = 3;
062:
063: public static final int ACTION_LOAD_MODEL = 4;
064:
065: public static final int ACTION_LOOKUP = 5;
066:
067: private int action;
068:
069: private String domainName;
070:
071: private String modelId;
072:
073: private String columnId;
074:
075: private IParameterProvider parameters;
076:
077: public PMDUIComponent(IPentahoUrlFactory urlFactory, List messages) {
078: super (urlFactory, messages, ""); //$NON-NLS-1$
079: }
080:
081: public Log getLogger() {
082: return logger;
083: }
084:
085: public boolean validate() {
086: return true;
087: }
088:
089: public Document getXmlContent() {
090:
091: if (action == ACTION_LIST_MODELS) {
092: return listModels();
093: } else if (action == ACTION_LOAD_MODEL) {
094: return loadModel();
095: } else if (action == ACTION_LOOKUP) {
096: return getLookup();
097: } else {
098: throw new RuntimeException(
099: Messages
100: .getErrorString(
101: "PMDUIComponent.ERROR_0002_ILLEGAL_ACTION", String.valueOf(action))); //$NON-NLS-1$
102: }
103: }
104:
105: private Document listModels() {
106:
107: // Create a document that describes the result
108: Document doc = DocumentHelper.createDocument();
109:
110: Element root = doc.addElement("metadata"); //$NON-NLS-1$
111:
112: Element modelsNode = root.addElement("models"); //$NON-NLS-1$
113: if (domainName == null) {
114: try {
115: MetadataPublisher.loadAllMetadata(getSession(), false);
116: String domains[] = CWM.getDomainNames();
117: for (int domainNo = 0; domainNo < domains.length; domainNo++) {
118: addDomainModels(domains[domainNo], modelsNode, root);
119: }
120: } catch (Throwable t) {
121: error(Messages
122: .getString("PMDUIComponent.ERROR_0001_GET_MODEL_LIST")); //$NON-NLS-1$
123: t.printStackTrace();
124: root
125: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_NO_DOMAIN_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$
126: }
127:
128: } else {
129: addDomainModels(domainName, modelsNode, root);
130: }
131: return doc;
132: }
133:
134: private void addDomainModels(String domain, Element modelsNode,
135: Element root) {
136:
137: CWM cwm = null;
138: try {
139: cwm = CWM.getInstance(domain, false);
140: } catch (Throwable t) {
141: root
142: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_DOMAIN_LOADING_ERROR", domain)); //$NON-NLS-1$ //$NON-NLS-2$
143: error(
144: Messages
145: .getString("PMDUIComponent.USER_DOMAIN_LOADING_ERROR") + domain, t); //$NON-NLS-1$
146: return;
147: }
148:
149: CwmSchemaFactoryInterface cwmSchemaFactory = (CwmSchemaFactoryInterface) PentahoSystem
150: .getObject(getSession(), "ICwmSchemaFactory"); //$NON-NLS-1$
151:
152: SchemaMeta schemaMeta = cwmSchemaFactory.getSchemaMeta(cwm);
153:
154: String locale = LocaleHelper.getLocale().toString();
155: schemaMeta.setActiveLocale(locale);
156: List models = schemaMeta.getBusinessModels().getList();
157:
158: MetaObjectComparator comparator = new MetaObjectComparator(
159: locale);
160: Collections.sort(models, comparator);
161:
162: Iterator it = models.iterator();
163: Element modelNode;
164: while (it.hasNext()) {
165: BusinessModel model = (BusinessModel) it.next();
166: modelNode = modelsNode.addElement("model"); //$NON-NLS-1$
167: modelNode.addElement("domain_id").setText(domain); //$NON-NLS-1$
168: if (model.getId() != null) {
169: modelNode.addElement("model_id").setText(model.getId()); //$NON-NLS-1$
170: }
171: if (model.getDisplayName(locale) != null) {
172: modelNode
173: .addElement("model_name").setText(model.getDisplayName(locale)); //$NON-NLS-1$
174: }
175: if (model.getDescription(locale) != null) {
176: modelNode
177: .addElement("model_description").setText(model.getDescription(locale)); //$NON-NLS-1$
178: }
179: }
180: if (debug) {
181:
182: }
183: return;
184: }
185:
186: private Document loadModel() {
187: // Create a document that describes the result
188: Document doc = DocumentHelper.createDocument();
189:
190: Element root = doc.addElement("metadata"); //$NON-NLS-1$
191:
192: if (domainName == null) {
193: // we can't do this without a model
194: root
195: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_NO_DOMAIN_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$
196: return doc;
197: }
198:
199: if (modelId == null) {
200: // we can't do this without a model
201: root
202: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_NO_MODEL_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$
203: return doc;
204: }
205:
206: Element modelNode = root.addElement("model"); //$NON-NLS-1$
207: MetadataPublisher.loadMetadata(domainName, getSession(), false);
208: CWM cwm = null;
209: try {
210: cwm = CWM.getInstance(domainName, false);
211: } catch (Throwable t) {
212: root
213: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_DOMAIN_LOADING_ERROR", domainName)); //$NON-NLS-1$ //$NON-NLS-2$
214: error(
215: Messages
216: .getString(
217: "PMDUIComponent.USER_MODEL_LOADING_ERROR", domainName), t); //$NON-NLS-1$
218: t.printStackTrace();
219: return doc;
220: }
221: CwmSchemaFactoryInterface cwmSchemaFactory = (CwmSchemaFactoryInterface) PentahoSystem
222: .getObject(getSession(), "ICwmSchemaFactory"); //$NON-NLS-1$
223: SchemaMeta schemaMeta = cwmSchemaFactory.getSchemaMeta(cwm);
224:
225: String locale = LocaleHelper.getLocale().toString();
226: schemaMeta.setActiveLocale(locale);
227:
228: BusinessModel model = schemaMeta.findModel(modelId); // This is the business view that was selected.
229: if (model == null) {
230: root
231: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_MODEL_LOADING_ERROR", modelId)); //$NON-NLS-1$ //$NON-NLS-2$
232: error(Messages.getString(
233: "PMDUIComponent.USER_MODEL_LOADING_ERROR", modelId)); //$NON-NLS-1$
234: return doc;
235: }
236: modelNode.addElement("domain_id").setText(domainName); //$NON-NLS-1$
237: if (model.getId() != null) {
238: modelNode.addElement("model_id").setText(model.getId()); //$NON-NLS-1$
239: }
240: if (model.getDisplayName(locale) != null) {
241: modelNode
242: .addElement("model_name").setText(model.getDisplayName(locale)); //$NON-NLS-1$
243: }
244: if (model.getDescription(locale) != null) {
245: modelNode
246: .addElement("model_description").setText(model.getDescription(locale)); //$NON-NLS-1$
247: }
248:
249: BusinessCategory rootView = model.getRootCategory();
250: UniqueList uniqueCategories = rootView.getBusinessCategories();
251: List childCategories = uniqueCategories.getList();
252:
253: MetaObjectComparator comparator = new MetaObjectComparator(
254: locale);
255: Collections.sort(childCategories, comparator);
256: Iterator it = childCategories.iterator();
257:
258: Element tableNode;
259: // BusinessTable table;
260: BusinessCategory businessView;
261:
262: BusinessColumn column;
263: List columns;
264: MetaObjectComparator columnComparator;
265: Iterator columnsIterator;
266:
267: while (it.hasNext()) {
268: businessView = (BusinessCategory) it.next();
269: tableNode = modelNode.addElement("view"); //$NON-NLS-1$
270: if (businessView.getId() != null) {
271: tableNode
272: .addElement("view_id").setText(businessView.getId()); //$NON-NLS-1$
273: }
274: if (businessView.getDisplayName(locale) != null) {
275: tableNode
276: .addElement("view_name").setText(businessView.getDisplayName(locale)); //$NON-NLS-1$
277: }
278: if (businessView.getDescription(locale) != null) {
279: tableNode
280: .addElement("view_description").setText(businessView.getDescription(locale)); //$NON-NLS-1$
281: }
282: columns = businessView.getBusinessColumns().getList();
283:
284: columnComparator = new MetaObjectComparator(locale);
285: Collections.sort(columns, columnComparator);
286: columnsIterator = columns.iterator();
287: while (columnsIterator.hasNext()) {
288: column = (BusinessColumn) columnsIterator.next();
289: if (column.isHidden()) {
290: continue;
291: }
292: addColumn(column, tableNode, locale);
293: }
294: }
295:
296: return doc;
297: }
298:
299: public void addColumn(BusinessColumn column, Element tableNode,
300: String locale) {
301: Element columnNode = tableNode.addElement("column"); //$NON-NLS-1$
302:
303: if (column.getId() != null) {
304: columnNode.addElement("column_id").setText(column.getId()); //$NON-NLS-1$
305: }
306: if (column.getDisplayName(locale) != null) {
307: columnNode
308: .addElement("column_name").setText(column.getDisplayName(locale)); //$NON-NLS-1$
309: }
310: if (column.getDescription(locale) != null) {
311: columnNode
312: .addElement("column_description").setText(column.getDescription(locale)); //$NON-NLS-1$
313: }
314: if (column.getFieldTypeDesc() != null) {
315: // TODO this should take a locale
316: columnNode
317: .addElement("column_field_type").setText(column.getFieldTypeDesc()); //$NON-NLS-1$
318: }
319: DataTypeSettings dataType = column.getDataType();
320: if (dataType != null) {
321: columnNode
322: .addElement("column_type").setText(dataType.getCode()); //$NON-NLS-1$
323: }
324: if (column.getConcept().getProperty("lookup") != null) { //$NON-NLS-1$
325: columnNode.addElement("column_lookup").setText("true"); //$NON-NLS-1$ //$NON-NLS-2$
326: }
327: }
328:
329: public Document getLookup() {
330: // Create a document that describes the result
331: Document doc = DocumentHelper.createDocument();
332:
333: Element root = doc.addElement("metadata"); //$NON-NLS-1$
334:
335: if (domainName == null) {
336: // we can't do this without a model
337: root
338: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_NO_DOMAIN_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$
339: return doc;
340: }
341:
342: if (modelId == null) {
343: // we can't do this without a view
344: root
345: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_NO_MODEL_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$
346: return doc;
347: }
348:
349: if (columnId == null) {
350: // we can't do this without a view
351: root
352: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_NO_COLUMN_SPECIFIED")); //$NON-NLS-1$ //$NON-NLS-2$
353: return doc;
354: }
355:
356: MetadataPublisher.loadMetadata(domainName, getSession(), false);
357: CWM cwm = null;
358: try {
359: cwm = CWM.getInstance(domainName, false);
360: } catch (Throwable t) {
361: root
362: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_DOMAIN_LOADING_ERROR", domainName)); //$NON-NLS-1$ //$NON-NLS-2$
363: error(
364: Messages
365: .getString(
366: "PMDUIComponent.USER_DOMAIN_LOADING_ERROR", domainName), t); //$NON-NLS-1$
367: return doc;
368: }
369: CwmSchemaFactoryInterface cwmSchemaFactory = (CwmSchemaFactoryInterface) PentahoSystem
370: .getObject(getSession(), "ICwmSchemaFactory"); //$NON-NLS-1$
371: SchemaMeta schemaMeta = cwmSchemaFactory.getSchemaMeta(cwm);
372:
373: String locale = LocaleHelper.getLocale().toString();
374: schemaMeta.setActiveLocale(locale);
375:
376: BusinessModel model = schemaMeta.findModel(modelId); // This is the business view that was selected.
377: if (model == null) {
378: root
379: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_MODEL_LOADING_ERROR", modelId)); //$NON-NLS-1$ //$NON-NLS-2$
380: return doc;
381: }
382:
383: BusinessColumn column = model.findBusinessColumn(columnId);
384: if (column == null) {
385: root
386: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_COLUMN_NOT_FOUND")); //$NON-NLS-1$ //$NON-NLS-2$
387: return doc;
388: }
389:
390: // Temporary hack to get the BusinessCategory. When fixed properly, you should be able to interrogate the
391: // business column thingie for it's containing BusinessCategory.
392: BusinessCategory rootCat = model.getRootCategory();
393: BusinessCategory view = rootCat
394: .findBusinessCategoryForBusinessColumn(column);
395: if (view == null) {
396: root
397: .addElement("message").setText(Messages.getString("PMDUIComponent.USER_VIEW_NOT_FOUND")); //$NON-NLS-1$ //$NON-NLS-2$
398: return doc;
399: }
400:
401: 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$
402: if (column.getConcept().getProperty("lookup") == null) { //$NON-NLS-1$
403: mql += "<selection><view>" + view.getId() + "</view><column>" + column.getId() + "</column></selection>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
404: 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$
405:
406: } else {
407:
408: String lookup = column.getConcept()
409: .getProperty("lookup").getValue().toString(); //$NON-NLS-1$
410: // assume model and view are the same...
411: StringTokenizer tokenizer1 = new StringTokenizer(lookup,
412: ";"); //$NON-NLS-1$
413: while (tokenizer1.hasMoreTokens()) {
414: StringTokenizer tokenizer2 = new StringTokenizer(
415: tokenizer1.nextToken(), "."); //$NON-NLS-1$
416: if (tokenizer2.countTokens() == 2) {
417: String lookupViewId = tokenizer2.nextToken();
418: String lookupColumnId = tokenizer2.nextToken();
419: mql += "<selection><view>" + lookupViewId + "</view><column>" + lookupColumnId + "</column></selection>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
420: }
421: }
422: }
423: mql += "</mql>"; //$NON-NLS-1$
424: ArrayList messages = new ArrayList();
425: SimpleParameterProvider lookupParameters = new SimpleParameterProvider();
426: lookupParameters.setParameter("mql", mql); //$NON-NLS-1$
427: IRuntimeContext runtime = ChartHelper
428: .doAction(
429: "system", "metadata", "PickList.xaction", "lookup-list", lookupParameters, getSession(), messages, this ); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
430: IPentahoResultSet results = null;
431: if (runtime != null) {
432: if (runtime.getStatus() == IRuntimeContext.RUNTIME_STATUS_SUCCESS) {
433: if (runtime.getOutputNames().contains("data")) { //$NON-NLS-1$
434: results = runtime
435: .getOutputParameter("data").getValueAsResultSet(); //$NON-NLS-1$
436: Object[][] columnHeaders = results.getMetaData()
437: .getColumnHeaders();
438: boolean hasColumnHeaders = columnHeaders != null;
439:
440: Element rowElement;
441: Element dataElement = root.addElement("data"); //$NON-NLS-1$
442: if (hasColumnHeaders) {
443: for (int rowNo = 0; rowNo < columnHeaders.length; rowNo++) {
444: rowElement = dataElement
445: .addElement("COLUMN-HDR-ROW"); //$NON-NLS-1$
446: for (int columnNo = 0; columnNo < columnHeaders[rowNo].length; columnNo++) {
447: Object nameAttr = results.getMetaData()
448: .getAttribute(rowNo, columnNo,
449: "name"); //$NON-NLS-1$
450: if (nameAttr != null
451: && nameAttr instanceof ConceptPropertyLocalizedString) {
452: ConceptPropertyLocalizedString str = (ConceptPropertyLocalizedString) nameAttr;
453: LocalizedStringSettings settings = (LocalizedStringSettings) str
454: .getValue();
455: String name = settings
456: .getString(LocaleHelper
457: .getLocale()
458: .toString());
459: if (name != null) {
460: rowElement
461: .addElement(
462: "COLUMN-HDR-ITEM").setText(name); //$NON-NLS-1$
463: } else {
464: rowElement
465: .addElement(
466: "COLUMN-HDR-ITEM").setText(columnHeaders[rowNo][columnNo].toString()); //$NON-NLS-1$
467: }
468: } else {
469: rowElement
470: .addElement(
471: "COLUMN-HDR-ITEM").setText(columnHeaders[rowNo][columnNo].toString()); //$NON-NLS-1$
472: }
473: }
474: }
475: }
476: Object row[] = results.next();
477: while (row != null) {
478: rowElement = dataElement.addElement("DATA-ROW"); //$NON-NLS-1$
479: for (int columnNo = 0; columnNo < row.length; columnNo++) {
480: if (row[columnNo] == null) {
481: rowElement
482: .addElement("DATA-ITEM").setText(""); //$NON-NLS-1$ //$NON-NLS-2$
483: } else {
484: rowElement
485: .addElement("DATA-ITEM").setText(row[columnNo].toString()); //$NON-NLS-1$
486: }
487: }
488: row = results.next();
489: }
490: }
491: }
492: }
493:
494: return doc;
495: }
496:
497: public void setAction(int action) {
498: this .action = action;
499: }
500:
501: public int getAction() {
502: return action;
503: }
504:
505: public void setDomainName(String domainName) {
506: this .domainName = domainName;
507: }
508:
509: public String getDomainName() {
510: return domainName;
511: }
512:
513: public IParameterProvider getParameters() {
514: return parameters;
515: }
516:
517: public void setParameters(IParameterProvider parameters) {
518: this .parameters = parameters;
519: }
520:
521: public String getModelId() {
522: return modelId;
523: }
524:
525: public void setModelId(String modelId) {
526: this .modelId = modelId;
527: }
528:
529: public String getColumnId() {
530: return columnId;
531: }
532:
533: public void setColumnId(String columnId) {
534: this .columnId = columnId;
535: }
536:
537: private class MetaObjectComparator implements Comparator {
538: private String localeString;
539:
540: public MetaObjectComparator(String locale) {
541: this .localeString = locale;
542: }
543:
544: public int compare(Object obj1, Object obj2) {
545: ConceptUtilityInterface cui1 = (ConceptUtilityInterface) obj1;
546: ConceptUtilityInterface cui2 = (ConceptUtilityInterface) obj2;
547: return cui1.getDisplayName(this.localeString).compareTo(
548: cui2.getDisplayName(this.localeString));
549: }
550:
551: }
552:
553: }
|