001: /*
002: * Copyright 2006-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.
007: *
008: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
009: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
010: * the license for the specific language governing your rights and limitations.
011: *
012: * Additional Contributor(s): Martin Schmid gridvision engineering GmbH
013: */
014: package org.pentaho.reportdesigner.crm.report.datasetplugin.staticfactory;
015:
016: import com.jgoodies.forms.layout.CellConstraints;
017: import com.jgoodies.forms.layout.FormLayout;
018: import org.gjt.xpp.XmlPullNode;
019: import org.jetbrains.annotations.NonNls;
020: import org.jetbrains.annotations.NotNull;
021: import org.jetbrains.annotations.Nullable;
022: import org.jfree.report.ParameterDataRow;
023: import org.jfree.report.ReportDataFactoryException;
024: import org.jfree.report.modules.misc.datafactory.StaticDataFactory;
025: import org.jfree.report.util.ReportProperties;
026: import org.pentaho.reportdesigner.crm.report.PropertyKeys;
027: import org.pentaho.reportdesigner.crm.report.ReportDialog;
028: import org.pentaho.reportdesigner.crm.report.ReportDialogConstants;
029: import org.pentaho.reportdesigner.crm.report.connection.ColumnInfo;
030: import org.pentaho.reportdesigner.crm.report.datasetplugin.ColumnInfoTableModel;
031: import org.pentaho.reportdesigner.crm.report.datasetplugin.DataFetchException;
032: import org.pentaho.reportdesigner.crm.report.datasetplugin.properties.PropertyInfo;
033: import org.pentaho.reportdesigner.crm.report.model.ReportElement;
034: import org.pentaho.reportdesigner.crm.report.model.TextFieldReportElement;
035: import org.pentaho.reportdesigner.crm.report.model.dataset.TableModelDataSetReportElement;
036: import org.pentaho.reportdesigner.crm.report.model.functions.ExpressionRegistry;
037: import org.pentaho.reportdesigner.crm.report.reportelementinfo.ReportElementInfoFactory;
038: import org.pentaho.reportdesigner.crm.report.reportexporter.ReportCreationException;
039: import org.pentaho.reportdesigner.crm.report.reportexporter.ReportVisitor;
040: import org.pentaho.reportdesigner.lib.client.i18n.TranslationManager;
041: import org.pentaho.reportdesigner.lib.client.undo.Undo;
042: import org.pentaho.reportdesigner.lib.client.undo.UndoEntry;
043: import org.pentaho.reportdesigner.lib.common.xml.ObjectConverter;
044: import org.pentaho.reportdesigner.lib.common.xml.ObjectConverterFactory;
045: import org.pentaho.reportdesigner.lib.common.xml.XMLConstants;
046: import org.pentaho.reportdesigner.lib.common.xml.XMLContext;
047: import org.pentaho.reportdesigner.lib.common.xml.XMLUtils;
048: import org.pentaho.reportdesigner.lib.common.xml.XMLWriter;
049:
050: import javax.swing.*;
051: import javax.swing.table.TableModel;
052: import java.awt.datatransfer.DataFlavor;
053: import java.awt.datatransfer.Transferable;
054: import java.awt.datatransfer.UnsupportedFlavorException;
055: import java.awt.dnd.DnDConstants;
056: import java.io.IOException;
057: import java.util.ArrayList;
058: import java.util.Collection;
059: import java.util.HashSet;
060: import java.util.TreeSet;
061: import java.util.logging.Level;
062: import java.util.logging.Logger;
063:
064: /**
065: * User: Martin
066: * Date: 31.01.2006
067: * Time: 10:30:43
068: */
069: public class StaticFactoryDataSetReportElement extends
070: TableModelDataSetReportElement {
071: @NonNls
072: @NotNull
073: private static final Logger LOG = Logger
074: .getLogger(StaticFactoryDataSetReportElement.class
075: .getName());
076:
077: @NotNull
078: private String queryName;
079: @NotNull
080: private String className;
081: @NotNull
082: private String methodName;
083: @NotNull
084: private TreeSet<PropertyInfo> parameters;
085:
086: @NotNull
087: private ArrayList<ColumnInfo> columnInfos;
088:
089: @Nullable
090: private TableModel cachedTableModel;
091: @Nullable
092: private JTable infoTable;
093:
094: public StaticFactoryDataSetReportElement() {
095: queryName = ReportDialogConstants.DEFAULT_DATA_FACTORY;
096: className = "";
097: methodName = "";
098: parameters = new TreeSet<PropertyInfo>();
099: columnInfos = new ArrayList<ColumnInfo>();
100: }
101:
102: @NotNull
103: public String getQueryName() {
104: return queryName;
105: }
106:
107: public void setQueryName(@NotNull
108: final String queryName) {
109: final String oldQueryName = this .queryName;
110: this .queryName = queryName;
111:
112: Undo undo = getUndo();
113: if (undo != null && !undo.isInProgress()) {
114: undo.startTransaction(PropertyKeys.QUERY_NAME);
115: undo.add(new UndoEntry() {
116: public void undo() {
117: setQueryName(oldQueryName);
118: }
119:
120: public void redo() {
121: setQueryName(queryName);
122: }
123: });
124: undo.endTransaction();
125: }
126:
127: firePropertyChange(PropertyKeys.QUERY_NAME, oldQueryName,
128: queryName);
129: }
130:
131: @NotNull
132: public TreeSet<PropertyInfo> getParameters() {
133: return parameters;
134: }
135:
136: public void setParameters(@NotNull
137: final TreeSet<PropertyInfo> parameters) {
138: final TreeSet<PropertyInfo> oldParameters = this .parameters;
139: this .parameters = parameters;
140:
141: JTable table = infoTable;
142: if (table != null) {
143: table.setModel(new ParametersTableModel(
144: new ArrayList<PropertyInfo>(parameters)));
145: }
146:
147: Undo undo = getUndo();
148: if (undo != null && !undo.isInProgress()) {
149: undo.startTransaction(PropertyKeys.PARAMETERS);
150: undo.add(new UndoEntry() {
151: public void undo() {
152: setParameters(oldParameters);
153: }
154:
155: public void redo() {
156: setParameters(parameters);
157: }
158: });
159: undo.endTransaction();
160: }
161:
162: firePropertyChange(PropertyKeys.PARAMETERS, oldParameters,
163: parameters);
164: }
165:
166: public boolean canCreateReportOnServer() {
167: return false;
168: }
169:
170: public void createReportOnServer(@NotNull
171: String jFreeReportDefinition) {
172: throw new RuntimeException(
173: "Can not create the report on the server");
174: }
175:
176: public boolean canFetchPreviewDataTableModel() {
177: return true;
178: }
179:
180: @NotNull
181: public String getQuery() {
182: return StaticFactoryDataSetReportElement.getQuery(className,
183: methodName, parameters);
184: }
185:
186: @NotNull
187: public static String getQuery(@NotNull
188: String className, @NotNull
189: String methodName, @NotNull
190: Collection<PropertyInfo> parameters) {
191: StringBuilder sb = new StringBuilder(className).append("#")
192: .append(methodName);
193: //if (!parameters.isEmpty())
194: {
195: sb.append("(");
196: }
197: boolean first = true;
198: for (PropertyInfo propertyInfo : parameters) {
199: if (!first) {
200: sb.append(", ");
201: } else {
202: first = false;
203: }
204: sb.append(propertyInfo.getKey());
205: }
206: //if (!parameters.isEmpty())
207: {
208: sb.append(")");
209: }
210: return sb.toString();
211: }
212:
213: @NotNull
214: public static ReportProperties getReportProperties(@NotNull
215: Collection<PropertyInfo> parameters) {
216: ReportProperties reportProperties = new ReportProperties();
217: for (PropertyInfo propertyInfo : parameters) {
218: reportProperties.put(propertyInfo.getKey(), propertyInfo
219: .getValue());
220: }
221: return reportProperties;
222: }
223:
224: @NotNull
225: public TableModel fetchPreviewDataTableModel()
226: throws DataFetchException {
227: try {
228: long l1 = System.nanoTime();
229: TableModel ctm = cachedTableModel;
230: if (cachedTableModel == null) {
231: StaticDataFactory staticDataFactory = new StaticDataFactory();
232: ctm = staticDataFactory.queryData(getQuery(className,
233: methodName, parameters), new ParameterDataRow(
234: getReportProperties(parameters)));
235: cachedTableModel = ctm;
236: }
237: long l2 = System.nanoTime();
238: if (StaticFactoryDataSetReportElement.LOG
239: .isLoggable(Level.FINE))
240: StaticFactoryDataSetReportElement.LOG.log(Level.FINE,
241: "JDBCDataSetReportElement.fetchDataTableModel "
242: + (l2 - l1) / (1000. * 1000.) + " ms");
243: return ctm;
244: } catch (Throwable e) {
245: throw new DataFetchException(e);
246: }
247: }
248:
249: @NotNull
250: public static TableModel fetchPreviewDataTableModel(@NotNull
251: String className, @NotNull
252: String methodName, @NotNull
253: Collection<PropertyInfo> parameters)
254: throws ReportDataFactoryException {
255: StaticDataFactory staticDataFactory = new StaticDataFactory();
256: return staticDataFactory.queryData(getQuery(className,
257: methodName, parameters), new ParameterDataRow(
258: getReportProperties(parameters)));
259: }
260:
261: public boolean canFetchRealDataTableModel() {
262: return true;
263: }
264:
265: @NotNull
266: public TableModel fetchRealDataTableModel()
267: throws DataFetchException {
268: try {
269: return StaticFactoryDataSetReportElement
270: .fetchPreviewDataTableModel(className, methodName,
271: parameters);
272: } catch (Throwable e) {
273: throw new DataFetchException(e);
274: }
275: }
276:
277: @NotNull
278: public String getClassName() {
279: return className;
280: }
281:
282: public void setClassName(@NotNull
283: final String className) {
284: //noinspection ConstantConditions
285: if (className == null) {
286: throw new IllegalArgumentException(
287: "className must not be null");
288: }
289:
290: final String oldClassName = this .className;
291: this .className = className;
292:
293: Undo undo = getUndo();
294: if (undo != null && !undo.isInProgress()) {
295: undo.startTransaction(PropertyKeys.CLASS_NAME);
296: undo.add(new UndoEntry() {
297: public void undo() {
298: setClassName(oldClassName);
299: }
300:
301: public void redo() {
302: setClassName(className);
303: }
304: });
305: undo.endTransaction();
306: }
307: firePropertyChange(PropertyKeys.CLASS_NAME, oldClassName,
308: className);
309: }
310:
311: @NotNull
312: public String getMethodName() {
313: return methodName;
314: }
315:
316: public void setMethodName(@NotNull
317: final String methodName) {
318: //noinspection ConstantConditions
319: if (methodName == null) {
320: throw new IllegalArgumentException(
321: "methodName must not be null");
322: }
323:
324: final String oldMethodName = this .methodName;
325: this .methodName = methodName;
326:
327: Undo undo = getUndo();
328: if (undo != null && !undo.isInProgress()) {
329: undo.startTransaction(PropertyKeys.METHOD_NAME);
330: undo.add(new UndoEntry() {
331: public void undo() {
332: setMethodName(oldMethodName);
333: }
334:
335: public void redo() {
336: setMethodName(methodName);
337: }
338: });
339: undo.endTransaction();
340: }
341: firePropertyChange(PropertyKeys.METHOD_NAME, oldMethodName,
342: methodName);
343: }
344:
345: @NotNull
346: public ArrayList<ColumnInfo> getColumnInfos() {
347: return columnInfos;
348: }
349:
350: public void setColumnInfos(@NotNull
351: final ArrayList<ColumnInfo> columnInfos) {
352: //noinspection ConstantConditions
353: if (columnInfos == null) {
354: throw new IllegalArgumentException(
355: "columnInfos must not be null");
356: }
357:
358: final ArrayList<ColumnInfo> oldColumnInfos = this .columnInfos;
359: this .columnInfos = columnInfos;
360:
361: //if (infoTable != null)
362: //{
363: // infoTable.setModel(new HelperTableModel(columnInfos));
364: //}
365:
366: Undo undo = getUndo();
367: if (undo != null && !undo.isInProgress()) {
368: undo.startTransaction(PropertyKeys.COLUMN_INFOS);
369: undo.add(new UndoEntry() {
370: public void undo() {
371: setColumnInfos(oldColumnInfos);
372: }
373:
374: public void redo() {
375: setColumnInfos(columnInfos);
376: }
377: });
378: undo.endTransaction();
379: }
380: firePropertyChange(PropertyKeys.COLUMN_INFOS, oldColumnInfos,
381: columnInfos);
382: }
383:
384: @NotNull
385: public String getShortSummary() {
386: String niceName = className;
387: try {
388: Class<?> clazz = Class.forName(className);
389: if (clazz != null) {
390: niceName = clazz.getSimpleName();
391: }
392: } catch (ClassNotFoundException e) {
393: if (LOG.isLoggable(Level.FINE))
394: LOG
395: .log(
396: Level.FINE,
397: "StaticFactoryDataSetReportElement.getShortSummary ",
398: e);
399: }
400:
401: StringBuilder sb = new StringBuilder(niceName).append(".")
402: .append(methodName).append("(");
403: boolean first = true;
404: for (PropertyInfo propertyInfo : parameters) {
405: if (!first) {
406: sb.append(", ");
407: } else {
408: first = false;
409: }
410: sb.append(propertyInfo.getValue());
411: }
412: sb.append(")");
413: return getQueryName() + " " + sb.toString();
414: }
415:
416: @NotNull
417: public HashSet<String> getDefinedFields() {
418: HashSet<String> definedFields = new HashSet<String>();
419: for (ColumnInfo columnInfo : columnInfos) {
420: definedFields.add(columnInfo.getColumnName());
421: }
422: return definedFields;
423: }
424:
425: public boolean canConfigure() {
426: return true;
427: }
428:
429: public boolean showConfigurationComponent(@NotNull
430: ReportDialog parent, boolean firsttime) {
431: boolean ok = StaticFactoryDataSetReportElementConfigurator
432: .showStaticFactoryDataSetReportElementConfigurator(
433: parent, this );
434: cachedTableModel = null;
435: return ok;
436: }
437:
438: @NotNull
439: public JComponent getInfoComponent() {
440: @NonNls
441: FormLayout formLayout = new FormLayout(
442: "2dlu, pref, 4dlu, 0dlu:grow, 2dlu",
443: "2dlu, pref, 4dlu, pref, 4dlu, fill:default:grow, 2dlu");
444: JPanel infoPanel = new JPanel(formLayout);
445: @NonNls
446: CellConstraints cc = new CellConstraints();
447:
448: infoPanel
449: .add(
450: new JLabel(
451: TranslationManager
452: .getInstance()
453: .getTranslation("R",
454: "StaticFactoryDataSetReportElement.ClassName")),
455: cc.xy(2, 2));
456: JLabel classLabel = new JLabel(className);
457: classLabel.setToolTipText(className);
458: infoPanel.add(classLabel, cc.xy(4, 2));
459:
460: infoPanel
461: .add(
462: new JLabel(
463: TranslationManager
464: .getInstance()
465: .getTranslation("R",
466: "StaticFactoryDataSetReportElement.MethodName")),
467: cc.xy(2, 4));
468: JLabel methodLabel = new JLabel(methodName);
469: methodLabel.setToolTipText(methodName);
470: infoPanel.add(methodLabel, cc.xy(4, 4));
471:
472: JTable table = new JTable(new ColumnInfoTableModel(columnInfos));
473: table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
474: initDragAndDrop(table);
475: infoTable = table;
476:
477: infoPanel.add(new JScrollPane(infoTable), cc.xyw(2, 6, 3,
478: "fill, fill"));
479:
480: return infoPanel;
481: }
482:
483: private void initDragAndDrop(@NotNull
484: final JTable table) {
485: @NonNls
486: final DataFlavor dataFlavorLibraryItems = new DataFlavor(
487: "application/x-icore-reportelement;class="
488: + ReportElement.class.getName(),
489: "ReportElement " + ReportDialogConstants.UNSELECTED);
490:
491: table.setTransferHandler(new TransferHandler() {
492: @NotNull
493: protected Transferable createTransferable(@NotNull
494: JComponent c) {
495: TextFieldReportElement textFieldReportElement = ReportElementInfoFactory
496: .getInstance().getTextFieldReportElementInfo()
497: .createReportElement();
498: int selectedRow = table.getSelectedRow();
499: ColumnInfo columnInfo = columnInfos.get(selectedRow);
500: textFieldReportElement.setFieldName(columnInfo
501: .getColumnName());
502: final ReportElement reportElement = textFieldReportElement;
503:
504: return new Transferable() {
505: @NotNull
506: public DataFlavor[] getTransferDataFlavors() {
507: return new DataFlavor[] { dataFlavorLibraryItems };
508: }
509:
510: public boolean isDataFlavorSupported(@NotNull
511: DataFlavor flavor) {
512: return dataFlavorLibraryItems.equals(flavor);
513: }
514:
515: @NotNull
516: public Object getTransferData(@NotNull
517: DataFlavor flavor)
518: throws UnsupportedFlavorException {
519: if (dataFlavorLibraryItems.equals(flavor)) {
520: return reportElement;
521: } else {
522: throw new UnsupportedFlavorException(flavor);
523: }
524: }
525: };
526: }
527:
528: public int getSourceActions(@NotNull
529: JComponent c) {
530: return DnDConstants.ACTION_COPY;
531: }
532: });
533:
534: table.setDragEnabled(true);
535:
536: }
537:
538: protected void externalizeElements(@NotNull
539: XMLWriter xmlWriter, @NotNull
540: XMLContext xmlContext) throws IOException {
541: super .externalizeElements(xmlWriter, xmlContext);
542:
543: xmlWriter.writeProperty(PropertyKeys.QUERY_NAME, queryName);
544: xmlWriter.writeProperty(PropertyKeys.CLASS_NAME, className);
545: xmlWriter.writeProperty(PropertyKeys.METHOD_NAME, methodName);
546:
547: for (ColumnInfo columnInfo : columnInfos) {
548: xmlWriter.startElement(PropertyKeys.COLUMN_INFO);
549: columnInfo.externalizeObject(xmlWriter, xmlContext);
550: xmlWriter.closeElement(PropertyKeys.COLUMN_INFO);
551: }
552:
553: xmlWriter.startElement(PropertyKeys.PARAMETERS);
554: for (PropertyInfo propertyInfo : parameters) {
555: Object value = propertyInfo.getValue();
556: if (value != null) {
557: ObjectConverter converter = ObjectConverterFactory
558: .getInstance().getConverter(value.getClass(),
559: null, xmlContext);
560: if (converter != null) {
561: xmlWriter.writeProperty(propertyInfo.getKey(),
562: propertyInfo.getClazz().getName(),
563: converter.getString(value));
564: }
565: }
566: }
567: xmlWriter.closeElement(PropertyKeys.PARAMETERS);
568: }
569:
570: protected void readElement(@NotNull
571: ExpressionRegistry expressions, @NotNull
572: XmlPullNode node, @NotNull
573: XMLContext xmlContext) throws Exception {
574: super .readElement(expressions, node, xmlContext);
575:
576: if (XMLConstants.PROPERTY.equals(node.getRawName())
577: && PropertyKeys.QUERY_NAME
578: .equals(node
579: .getAttributeValueFromRawName(XMLConstants.NAME))) {
580: queryName = XMLUtils.readProperty(PropertyKeys.QUERY_NAME,
581: node);
582: } else if (XMLConstants.PROPERTY.equals(node.getRawName())
583: && PropertyKeys.CLASS_NAME
584: .equals(node
585: .getAttributeValueFromRawName(XMLConstants.NAME))) {
586: className = XMLUtils.readProperty(PropertyKeys.CLASS_NAME,
587: node);
588: } else if (XMLConstants.PROPERTY.equals(node.getRawName())
589: && PropertyKeys.METHOD_NAME
590: .equals(node
591: .getAttributeValueFromRawName(XMLConstants.NAME))) {
592: methodName = XMLUtils.readProperty(
593: PropertyKeys.METHOD_NAME, node);
594: } else if (PropertyKeys.PARAMETERS.equals(node.getRawName())) {
595: while (!node.isFinished()) {
596: Object child = node.readNextChild();
597: if (child instanceof XmlPullNode) {
598: XmlPullNode xmlPullNode = (XmlPullNode) child;
599: if (XMLConstants.PROPERTY.equals(xmlPullNode
600: .getRawName())) {
601: try {
602: String name = xmlPullNode
603: .getAttributeValueFromRawName(XMLConstants.NAME);
604: String type = xmlPullNode
605: .getAttributeValueFromRawName(XMLConstants.TYPE);
606: while (!xmlPullNode.isFinished()) {
607: Object value = xmlPullNode
608: .readNextChild();
609: if (value instanceof String) {
610: String s = (String) value;
611: Class<?> clazz = Class
612: .forName(type);
613: ObjectConverter converter = ObjectConverterFactory
614: .getInstance()
615: .getConverter(clazz, null,
616: xmlContext);
617: if (converter != null) {
618: Object object = converter
619: .getObject(s);
620: PropertyInfo propertyInfo = new PropertyInfo(
621: name, clazz, object);
622: parameters.add(propertyInfo);
623: }
624: }
625: }
626: } catch (ClassNotFoundException e) {
627: if (LOG.isLoggable(Level.FINE))
628: LOG
629: .log(
630: Level.FINE,
631: "PropertiesDataSetReportElement.readElement ",
632: e);
633: }
634: }
635: }
636: }
637: } else if (PropertyKeys.COLUMN_INFO.equals(node.getRawName())) {
638: ColumnInfo columnInfo = new ColumnInfo("", "", Object.class);
639: columnInfo.readObject(node, xmlContext);
640: columnInfos.add(columnInfo);
641: }
642:
643: }
644:
645: public void accept(@Nullable
646: Object parent, @NotNull
647: ReportVisitor reportVisitor) throws ReportCreationException {
648: /*Object newParent = */
649: reportVisitor.visit(parent, this);
650: }
651:
652: }
|