/******************************************************************************* * Copyright (c) 2014 Open Door Logistics (www.opendoorlogistics.com) * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Lesser Public License v3 * which accompanies this distribution, and is available at http://www.gnu.org/licenses/lgpl.txt ******************************************************************************/ package com.opendoorlogistics.core.components; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.Serializable; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JCheckBox; import javax.swing.JPanel; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; import com.opendoorlogistics.api.ODLApi; import com.opendoorlogistics.api.components.ComponentConfigurationEditorAPI; import com.opendoorlogistics.api.components.ComponentExecutionApi; import com.opendoorlogistics.api.components.ODLComponent; import com.opendoorlogistics.api.scripts.ScriptTemplatesBuilder; import com.opendoorlogistics.api.tables.ODLDatastore; import com.opendoorlogistics.api.tables.ODLDatastoreAlterable; import com.opendoorlogistics.api.tables.ODLTable; import com.opendoorlogistics.api.tables.ODLTableAlterable; import com.opendoorlogistics.api.tables.ODLTableDefinition; import com.opendoorlogistics.api.tables.TableFlags; import com.opendoorlogistics.core.tables.memory.ODLDatastoreImpl; import com.opendoorlogistics.core.tables.utils.TableUtils; import com.opendoorlogistics.core.utils.UpdateTimer; import com.opendoorlogistics.core.utils.ui.VerticalLayoutPanel; /** * Update component is a more-or-less dummy component which signals to the script executor that an update query is being done. * We use a 'dummy' component as various parts of the UI use the adapter-component model. * * @author Phil * */ public final class UpdateQueryComponent implements ODLComponent { @XmlRootElement(name = "UpdateQuery") public static class UpdateQueryConfig implements Serializable { private boolean isDeleteQuery; public boolean isDeleteQuery() { return isDeleteQuery; } @XmlAttribute(name = "IsDeleteQuery") public void setDeleteQuery(boolean isDeleteQuery) { this.isDeleteQuery = isDeleteQuery; } } @Override public String getId() { return "com.opendoorlogistics.core.components.UpdateQueryComponent"; } @Override public String getName() { return "Update table"; } @Override public ODLDatastore<? extends ODLTableDefinition> getIODsDefinition(ODLApi api,Serializable configuration) { ODLDatastoreAlterable<? extends ODLTableDefinition> ret = ODLDatastoreImpl.alterableFactory.create(); ret.setFlags(ret.getFlags() | TableFlags.FLAG_TABLE_WILDCARD); return ret; } @Override public ODLDatastore<? extends ODLTableDefinition> getOutputDsDefinition(ODLApi api,int mode, Serializable configuration) { // TODO Auto-generated method stub return null; } @Override public void execute(ComponentExecutionApi reporter,int mode,Object configuration, ODLDatastore<? extends ODLTable> ioDb, ODLDatastoreAlterable<? extends ODLTableAlterable> outputDb ) { // Only one input table will be provided to this component as the engine will split a multi-table // adapter up into single tables for the execute call. UpdateQueryConfig uqc = (UpdateQueryConfig) configuration; ODLTable table = ioDb.getTableAt(0); if (uqc.isDeleteQuery()) { TableUtils.removeAllRows(table); } else { UpdateTimer timer = new UpdateTimer(250); // The engine will have specially processed the input table so all the component needs to do is // read from field i and copy this value to field i+1, for i=0, 2, 4, etc. int rows = table.getRowCount(); int cols = table.getColumnCount(); for (int row = 0; row < rows; row++) { for (int col = 0; col < cols - 1; col += 2) { Object val = table.getValueAt(row, col); table.setValueAt(val, row, col + 1); } if(reporter.isCancelled()){ return; } if(timer.isUpdate()){ reporter.postStatusMessage("Now updating row " + (row+1) + " / " + rows); } } } reporter.postStatusMessage("Finished updating rows"); } @Override public Class<? extends Serializable> getConfigClass() { return UpdateQueryConfig.class; } @Override public JPanel createConfigEditorPanel(ComponentConfigurationEditorAPI factory,int mode,Serializable config, boolean isFixedIO) { VerticalLayoutPanel ret = new VerticalLayoutPanel(); final UpdateQueryConfig uqc = (UpdateQueryConfig) config; final JCheckBox checkBox = new JCheckBox("Delete query (deletes all selected rows)", uqc.isDeleteQuery()); checkBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { uqc.setDeleteQuery(checkBox.isSelected()); } }); ret.add(checkBox); return ret; } // @Override // public Iterable<ODLWizardTemplateConfig> getWizardTemplateConfigs(ODLApi api) { // return Arrays.asList(new ODLWizardTemplateConfig("Update table", "Update table", // "Update a table by copying values between columns or providing formulae to calculate values.", null)); // } @Override public void registerScriptTemplates(ScriptTemplatesBuilder templatesApi) { templatesApi.registerTemplate("Update table", "Update table", "Update a table by copying values between columns or providing formulae to calculate values.", getIODsDefinition(templatesApi.getApi(), new UpdateQueryConfig()), new UpdateQueryConfig()); } @Override public long getFlags(ODLApi api,int mode) { // TODO Auto-generated method stub return 0; } @Override public Icon getIcon(ODLApi api,int mode) { // Use own class loader to prevent problems when jar loaded by reflection return new ImageIcon(this.getClass().getResource("/resources/icons/update-query.png")); } @Override public boolean isModeSupported(ODLApi api,int mode) { return mode==ODLComponent.MODE_DEFAULT; } }