Java tutorial
/*! * 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.agilebi.spoon.perspective; import org.apache.commons.io.IOUtils; import org.pentaho.metadata.model.concept.types.LocalizedString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.dom4j.DocumentHelper; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.FileDialog; import org.pentaho.agilebi.modeler.*; import org.pentaho.agilebi.modeler.util.ModelerWorkspaceUtil; import org.pentaho.agilebi.spoon.ModelerEngineMeta; import org.pentaho.agilebi.spoon.SpoonModelerMessages; import org.pentaho.agilebi.spoon.SpoonModelerWorkspaceHelper; import org.pentaho.agilebi.spoon.XulUI; import org.pentaho.di.core.EngineMetaInterface; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.gui.SpoonFactory; import org.pentaho.di.i18n.BaseMessages; import org.pentaho.di.ui.spoon.FileListener; import org.pentaho.di.ui.spoon.Spoon; import org.pentaho.di.ui.spoon.SpoonPerspective; import org.pentaho.di.ui.spoon.SpoonPerspectiveManager; import org.pentaho.metadata.model.LogicalModel; import org.pentaho.metadata.util.MondrianModelExporter; import org.pentaho.ui.xul.XulException; import org.pentaho.ui.xul.XulOverlay; import org.pentaho.ui.xul.binding.Binding; import org.pentaho.ui.xul.binding.BindingFactory; import org.pentaho.ui.xul.binding.DefaultBinding; import org.pentaho.ui.xul.binding.DefaultBindingFactory; import org.pentaho.ui.xul.components.XulConfirmBox; import org.pentaho.ui.xul.components.XulMenuitem; import org.pentaho.ui.xul.components.XulMessageBox; import org.pentaho.ui.xul.components.XulTab; import org.pentaho.ui.xul.components.XulTabpanel; import org.pentaho.ui.xul.impl.XulEventHandler; import org.w3c.dom.Node; import java.io.*; import java.util.*; public class AgileBiModelerPerspective extends AbstractPerspective implements SpoonPerspective, FileListener { public static final String PERSPECTIVE_ID = "010-agilebi"; //$NON-NLS-1$ private Logger logger = LoggerFactory.getLogger(AgileBiModelerPerspective.class); private static final AgileBiModelerPerspective INSTANCE = new AgileBiModelerPerspective(); protected List<ModelerWorkspace> models = new ArrayList<ModelerWorkspace>(); private XulMenuitem modelPropItem; private AgileBiModelerPerspectiveController perspectiveController = new AgileBiModelerPerspectiveController(); BindingFactory bf = new DefaultBindingFactory(); private AgileBiModelerPerspective() { super("org/pentaho/agilebi/spoon/perspective/perspective.xul"); setDefaultExtension("xmi"); bf.setDocument(document); try { ModelerMessagesHolder.setMessages(new SpoonModelerMessages()); } catch (IllegalStateException e) { // someone else set this first, ignore the error } } public static AgileBiModelerPerspective getInstance() { return INSTANCE; } public String getDisplayName(Locale l) { return BaseMessages.getString(this.getClass(), "Modeler.Perspective.perspectiveName"); } public InputStream getPerspectiveIcon() { ClassLoader loader = getClass().getClassLoader(); return loader.getResourceAsStream("org/pentaho/agilebi/spoon/perspective/blueprint.png"); } public String getId() { return PERSPECTIVE_ID; } public boolean acceptsXml(String nodeName) { return false; } public String[] getFileTypeDisplayNames(Locale locale) { return new String[] { "Models" }; } public String[] getSupportedExtensions() { return new String[] { "xmi" }; } public void createTabForModel(final ModelerWorkspace aModel, String name) throws ModelerException { try { SpoonPerspectiveManager.getInstance().activatePerspective(getClass()); XulTabAndPanel tabAndPanel = createTab(); Spoon spoon = ((Spoon) SpoonFactory.getInstance()); XulUI xul = new XulUI(spoon.getShell(), aModel); metas.put(tabAndPanel.tab, xul.getMeta()); if (selectedMeta != xul.getMeta()) { setSelectedMeta(xul.getMeta()); } Composite parentComposite = (Composite) tabAndPanel.panel.getManagedObject(); xul.getMainPanel().setParent(parentComposite); parentComposite.layout(true); setNameForTab(tabAndPanel.tab, name); Binding bind = new DefaultBinding(aModel, "shortFileName", tabAndPanel.tab, "label"); //$NON-NLS-1$ //$NON-NLS-2$ bind.setConversion(new NameBindingConvertor(this, tabAndPanel.tab)); bind.setBindingType(Binding.Type.ONE_WAY); document.addBinding(bind); models.add(aModel); model = aModel; setSelectedMeta(xul.getMeta()); Spoon.getInstance().enableMenus(); } catch (KettleException e) { throw new ModelerException(e); } } public boolean open(Node transNode, String fname, boolean importfile) { try { // files may be a mix of absolute and relative. Constructing File objects to test equality File incomingFile = new File(fname); for (Map.Entry<XulTab, EngineMetaInterface> m : this.metas.entrySet()) { if (m == null) { continue; } String fileName = ((ModelerEngineMeta) m.getValue()).getController().getModel().getFileName(); if (fileName != null && new File(fileName).getAbsoluteFile().equals(incomingFile.getAbsoluteFile())) { int idx = this.tabbox.getTabs().getChildNodes().indexOf(m.getKey()); if (idx > -1) { SpoonPerspectiveManager.getInstance().activatePerspective(getClass()); this.tabbox.setSelectedIndex(idx); return true; } } } Spoon spoon = ((Spoon) SpoonFactory.getInstance()); ModelerWorkspace theModel = new ModelerWorkspace(new SpoonModelerWorkspaceHelper(), SpoonModelerWorkspaceHelper.initGeoContext()); theModel.setTemporary(false); theModel.setDirty(false); String xml = new String(IOUtils.toByteArray(new FileInputStream(new File(fname))), "UTF-8"); //$NON-NLS-1$ ModelerWorkspaceUtil.loadWorkspace(fname, xml, theModel); createTabForModel(theModel, createShortName(fname)); File f = new File(fname); String fullPath = f.getAbsolutePath(); spoon.getProperties().addLastFile("Model", fullPath, null, false, null); //$NON-NLS-1$ spoon.addMenuLast(); return true; } catch (IncompatibleModelerException e) { try { XulMessageBox box = (XulMessageBox) document.createElement("messagebox"); box.setTitle(BaseMessages.getString(AgileBiModelerPerspective.class, "incompatible_model_title")); box.setMessage(BaseMessages.getString(AgileBiModelerPerspective.class, "incompatible_model_msg")); box.setModalParent(((Spoon) SpoonFactory.getInstance()).getShell()); box.open(); } catch (XulException e1) { e1.printStackTrace(); } } catch (ModelerException e) { logger.error("Error opening file", e); } catch (IOException e) { logger.error("Error opening file", e); } catch (KettleException e) { logger.error("Error opening file", e); } return false; } public boolean save(EngineMetaInterface meta, String fname, boolean isExport) { try { return ((ModelerEngineMeta) meta).getController().saveWorkspace(fname); } catch (ModelerException e) { e.printStackTrace(); } return false; } public void syncMetaName(EngineMetaInterface meta, String name) { } public List<XulEventHandler> getEventHandlers() { return Collections.singletonList((XulEventHandler) perspectiveController); } public List<XulOverlay> getOverlays() { XulOverlay overlay = new XulOverlay() { public String getId() { return "agileBi"; //$NON-NLS-1$ } public String getOverlayUri() { return "org/pentaho/agilebi/spoon/perspective/modeler_perspective_overlay.xul"; //$NON-NLS-1$ } @Override public int getPriority() { return 0; } public String getOverlayXml() { return null; } public String getResourceBundleUri() { return null; } public String getSource() { return null; } }; return Collections.singletonList(overlay); } @Override public String getName() { return "agileBiPerspective"; //$NON-NLS-1$ } public boolean onTabClose(final int pos) throws XulException { String contentId = PERSPECTIVE_ID + "\t" + models.get(pos).getFileName(); //$NON-NLS-1$ if (models.get(pos).isDirty()) { XulConfirmBox confirm = (XulConfirmBox) document.createElement("confirmbox"); //$NON-NLS-1$ confirm.setTitle(BaseMessages.getString(this.getClass(), "Modeler.Perspective.unsavedChanges")); //$NON-NLS-1$ confirm.setMessage( BaseMessages.getString(this.getClass(), "Modeler.Perspective.unsavedChangesMessage")); //$NON-NLS-1$ CloseConfirmXulDialogCallback callback = new CloseConfirmXulDialogCallback(); confirm.addDialogCallback(callback); confirm.open(); if (!callback.closeIt) { return false; } } tabClosed(pos); switchToCaller(contentId); return true; } /** * Close the tab at the specified position. Tab removal from its container is assumed to be handled elsewhere. * This handles updating our internal state. * * @param pos Position of tab being closed */ private void tabClosed(final int pos) { models.remove(pos); metas.remove(tabbox.getTabs().getChildNodes().get(pos)); } /** * Close and remove the tab at the specified position * @param pos Position of tab to close */ public void removeTab(final int pos) { if (pos < 0 || pos >= tabbox.getTabs().getChildNodes().size()) { throw new IllegalArgumentException("invalid position: " + pos); } tabClosed(pos); // TODO XulTabbox.removeTab() does not work here. We must remove the tab and panel directly. :( XulTab tab = (XulTab) tabs.getChildNodes().get(pos); XulTabpanel panel = (XulTabpanel) panels.getChildNodes().get(pos); tabs.removeChild(tab); panels.removeChild(panel); } public void exportSchema() { try { if (this.model.isValid()) { this.model.getWorkspaceHelper().populateDomain(this.model); LogicalModel lModel = this.model.getLogicalModel(ModelerPerspective.ANALYSIS); FileDialog fileDialog = new FileDialog(Spoon.getInstance().getShell(), SWT.SAVE); String[] theExtensions = { "*.xml" }; fileDialog.setFilterExtensions(theExtensions); String theFile = fileDialog.open(); if (theFile != null) { MondrianModelExporter exporter = new MondrianModelExporter(lModel, LocalizedString.DEFAULT_LOCALE); String mondrianSchema = exporter.createMondrianModelXML(); logger.info(mondrianSchema); org.dom4j.Document schemaDoc = DocumentHelper.parseText(mondrianSchema); byte schemaBytes[] = schemaDoc.asXML().getBytes(); File modelFile = new File(theFile); OutputStream out = new FileOutputStream(modelFile); out.write(schemaBytes); out.flush(); out.close(); } } else { StringBuffer validationErrors = new StringBuffer(); for (String msg : this.model.getValidationMessages()) { validationErrors.append(msg); validationErrors.append("\n"); logger.info(msg); } MessageDialog.openError(Spoon.getInstance().getShell(), "", validationErrors.toString()); } } catch (Exception e) { logger.error("Error exporting Schema", e); MessageDialog.openError(Spoon.getInstance().getShell(), "", e.getMessage()); } } @Override public void setSelectedMeta(EngineMetaInterface meta) { super.setSelectedMeta(meta); perspectiveController.setSelectedModelerMeta((ModelerEngineMeta) meta); } }