1733 lines
45 KiB
Java
1733 lines
45 KiB
Java
/*
|
|
----
|
|
This file is part of SECONDO.
|
|
|
|
Copyright (C) 2004, University in Hagen, Department of Computer Science,
|
|
Database Systems for New Applications.
|
|
|
|
SECONDO is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
SECONDO 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.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with SECONDO; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
---
|
|
*/
|
|
|
|
package viewer.update2;
|
|
|
|
import java.awt.Component;
|
|
import java.awt.event.*;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import javax.swing.JCheckBox;
|
|
import javax.swing.JComponent;
|
|
import javax.swing.JOptionPane;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
import java.util.Vector;
|
|
|
|
import javax.accessibility.AccessibleValue;
|
|
|
|
import sj.lang.*;
|
|
|
|
import tools.Reporter;
|
|
|
|
import viewer.UpdateViewer2;
|
|
import viewer.update2.gui.*;
|
|
import viewer.update2.format.*;
|
|
|
|
|
|
/*
|
|
This class controls the actionflow of update-operations in the 'UpdateViewer2'.
|
|
|
|
*/
|
|
public class UpdateViewerController implements ActionListener, MouseListener
|
|
{
|
|
|
|
private CommandGenerator commandGenerator;
|
|
private CommandExecuter commandExecuter;
|
|
private FormatDialog formatDialog;
|
|
private LoadDialog loadDialog;
|
|
private UpdateViewer2 viewer;
|
|
private int state;
|
|
private LoadProfile loadProfile;
|
|
private DocumentFormatter formatter;
|
|
|
|
// Name of relation which contain LoadProfiles
|
|
public final static String RELNAME_LOAD_PROFILES_HEAD = "uv2loadprofiles";
|
|
public final static String RELNAME_LOAD_PROFILES_POS = "uv2loadprofilespos";
|
|
|
|
// button commands in UpdateViewer2 main window
|
|
public final static String CMD_OPEN_LOAD_DIALOG = "Open Load Dialog";
|
|
public final static String CMD_OPEN_FORMAT_DIALOG = "Open Format Dialog";
|
|
public final static String CMD_CLEAR = "Clear";
|
|
public final static String CMD_INSERT = "Insert";
|
|
public final static String CMD_UPDATE = "Update";
|
|
public final static String CMD_DELETE = "Delete";
|
|
public final static String CMD_UNDO = "Undo";
|
|
public final static String CMD_RESET = "Reset";
|
|
public final static String CMD_COMMIT = "Commit";
|
|
public final static String CMD_CLOSE_TAB = "Close tab";
|
|
// button commands in FormatDialog
|
|
public final static String CMD_CLOSE_FORMAT_DIALOG = "Close Format Dialog";
|
|
public final static String CMD_FORMAT = "Format";
|
|
// public final static String CMD_SAVE_DOCUMENT = "Save formatted document";
|
|
// button commands in LoadDialog
|
|
public final static String CMD_LOAD_DIRECT = "Load single relation";
|
|
public final static String CMD_LOAD_FROM_PROFILE = "Load selected profile";
|
|
public final static String CMD_CLOSE_LOAD_DIALOG = "Close Load Dialog";
|
|
public final static String CMD_CREATE_PROFILE = "Create new profile";
|
|
public final static String CMD_CREATE_PROFILEPOS = "Add relation";
|
|
public final static String CMD_EDIT_PROFILE = "Edit load profile";
|
|
public final static String CMD_EDIT_PROFILEPOS = "Edit relation restrictions";
|
|
public final static String CMD_REMOVE_PROFILE = "Remove profile";
|
|
public final static String CMD_REMOVE_PROFILEPOS = "Remove relation";
|
|
// button commands in TupleEditor
|
|
public final static String CMD_CANCEL = "Cancel";
|
|
public final static String CMD_SAVE_PROFILE = "Save load profile";
|
|
public final static String CMD_SAVE_PROFILEPOS = "Save relation restrictions";
|
|
// button commands for search/replace
|
|
public final static String CMD_SEARCH = "Search";
|
|
public final static String CMD_CLEAR_SEARCH = "Clear search";
|
|
public final static String CMD_PREVIOUS = "Previous";
|
|
public final static String CMD_NEXT = "Next";
|
|
public final static String CMD_LAST = "Last";
|
|
public final static String CMD_FIRST = "First";
|
|
public final static String CMD_REPLACE = "Replace";
|
|
public final static String CMD_REPLACE_ALL = "Replace all";
|
|
public final static String CMD_PRINT = "Print";
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
public UpdateViewerController(UpdateViewer2 viewer)
|
|
{
|
|
this.viewer = viewer;
|
|
this.formatDialog = new FormatDialog(this);
|
|
this.commandGenerator = new CommandGenerator();
|
|
this.commandExecuter = new CommandExecuter();
|
|
this.state = States.INITIAL;
|
|
}
|
|
|
|
/**
|
|
* Reacts on user actions in UpdateViewer2 and LoadDialog.
|
|
* Sets the next state.
|
|
*/
|
|
public void actionPerformed(ActionEvent e)
|
|
{
|
|
// UpdateViewer2 window
|
|
if (e.getActionCommand() == CMD_OPEN_LOAD_DIALOG)
|
|
{
|
|
this.processCommandOpenLoadDialog();
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_CLEAR)
|
|
{
|
|
this.processCommandClear();
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_INSERT)
|
|
{
|
|
this.processCommandInsert();
|
|
this.setState(States.INSERT);
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_DELETE)
|
|
{
|
|
this.setState(States.DELETE);
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_UPDATE)
|
|
{
|
|
this.setState(States.UPDATE);
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_RESET)
|
|
{
|
|
this.processCommandReset();
|
|
this.setState(States.LOADED);
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_UNDO)
|
|
{
|
|
this.processCommandUndo();
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_COMMIT)
|
|
{
|
|
if (this.processCommandCommit())
|
|
{
|
|
this.setState(States.LOADED);
|
|
}
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_OPEN_FORMAT_DIALOG)
|
|
{
|
|
this.processCommandOpenFormatDialog();
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_CLOSE_TAB)
|
|
{
|
|
if (e.getSource() instanceof AccessibleValue)
|
|
{
|
|
int index = ((AccessibleValue)e.getSource()).getCurrentAccessibleValue().intValue();
|
|
this.viewer.removeRelationPanel(index);
|
|
}
|
|
return;
|
|
}
|
|
//
|
|
// FormatDialog
|
|
//
|
|
if (e.getActionCommand() == CMD_FORMAT)
|
|
{
|
|
this.processCommandFormat();
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_CLOSE_FORMAT_DIALOG)
|
|
{
|
|
this.formatDialog.setVisible(false);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// LoadDialog
|
|
//
|
|
if (e.getActionCommand() == CMD_LOAD_DIRECT)
|
|
{
|
|
if (processCommandLoadDirect())
|
|
{
|
|
this.setState(States.LOADED);
|
|
this.loadDialog.dispose();
|
|
this.loadDialog = null;
|
|
}
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_LOAD_FROM_PROFILE)
|
|
{
|
|
if (processCommandLoadFromProfile())
|
|
{
|
|
this.setState(States.LOADED);
|
|
this.loadDialog.dispose();
|
|
this.loadDialog = null;
|
|
}
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_CLOSE_LOAD_DIALOG)
|
|
{
|
|
this.loadDialog.dispose();
|
|
this.loadDialog = null;
|
|
return;
|
|
}
|
|
|
|
if (e.getActionCommand() == CMD_CREATE_PROFILE)
|
|
{
|
|
this.processCommandAddLoadProfile();
|
|
return;
|
|
}
|
|
|
|
if (e.getActionCommand() == CMD_EDIT_PROFILE)
|
|
{
|
|
String profname = this.loadDialog.getCurrentLoadProfileName();
|
|
this.loadDialog.showEditLoadProfile(profname);
|
|
return;
|
|
}
|
|
|
|
if (e.getActionCommand() == CMD_SAVE_PROFILE)
|
|
{
|
|
if(this.processCommandSaveLoadProfile())
|
|
{
|
|
this.loadDialog.closeEditDialog();
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
if (e.getActionCommand() == CMD_REMOVE_PROFILE)
|
|
{
|
|
String profileName = this.loadDialog.getCurrentLoadProfileName();
|
|
int option = JOptionPane.showConfirmDialog(this.loadDialog
|
|
, "Really remove load profile \"" + profileName + " \"?"
|
|
, "Remove load profile"
|
|
, JOptionPane.YES_NO_OPTION);
|
|
if (option == JOptionPane.YES_OPTION)
|
|
{
|
|
if (this.processCommandRemoveLoadProfile(profileName))
|
|
{
|
|
this.loadDialog.removeLoadProfile(profileName);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (e.getActionCommand() == CMD_CREATE_PROFILEPOS)
|
|
{
|
|
this.processCommandAddRelationProfile();
|
|
return;
|
|
}
|
|
|
|
if (e.getActionCommand() == CMD_EDIT_PROFILEPOS)
|
|
{
|
|
String profname = this.loadDialog.getCurrentLoadProfileName();
|
|
String relname = this.loadDialog.getCurrentRelationProfileName();
|
|
this.loadDialog.showEditRelationProfile(profname, relname);
|
|
return;
|
|
}
|
|
|
|
if (e.getActionCommand() == CMD_SAVE_PROFILEPOS)
|
|
{
|
|
if (this.processCommandSaveRelationProfile())
|
|
{
|
|
this.loadDialog.closeEditDialog();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (e.getActionCommand() == CMD_REMOVE_PROFILEPOS)
|
|
{
|
|
String profileName = this.loadDialog.getCurrentLoadProfileName();
|
|
String relName = this.loadDialog.getCurrentRelationProfileName();
|
|
if (this.processCommandRemoveRelationProfile(profileName, relName))
|
|
{
|
|
this.loadDialog.removeRelationProfile(profileName, relName);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
if (e.getActionCommand() == CMD_CANCEL)
|
|
{
|
|
this.loadDialog.closeEditDialog();
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// Search
|
|
//
|
|
if (e.getActionCommand() == CMD_SEARCH)
|
|
{
|
|
// read keyword from searchfield
|
|
String key = this.viewer.getCurrentRelationPanel().getSearchKey();
|
|
boolean caseSensitive = this.viewer.getCurrentRelationPanel().getCaseSensitive();
|
|
|
|
if (key == null || key.length() == 0)
|
|
{
|
|
Reporter.showInfo("Please specify a search key");
|
|
}
|
|
else
|
|
{
|
|
if (!this.processCommandSearch())
|
|
{
|
|
Reporter.showInfo("No matches found.");
|
|
this.processCommandClearSearch();
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_CLEAR_SEARCH)
|
|
{
|
|
this.processCommandClearSearch();
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_NEXT)
|
|
{
|
|
this.processCommandNext();
|
|
return;
|
|
|
|
}
|
|
if (e.getActionCommand() == CMD_PREVIOUS)
|
|
{
|
|
this.processCommandPrevious();
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_LAST)
|
|
{
|
|
this.viewer.getCurrentRelationPanel().showHit(this.viewer.getCurrentRelationPanel().getHitCount()-1);
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_FIRST)
|
|
{
|
|
this.viewer.getCurrentRelationPanel().showHit(0);
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_REPLACE)
|
|
{
|
|
this.processCommandReplace();
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_REPLACE_ALL)
|
|
{
|
|
this.processCommandReplaceAll();
|
|
return;
|
|
}
|
|
if (e.getActionCommand() == CMD_PRINT)
|
|
{
|
|
this.processCommandPrint();
|
|
return;
|
|
}
|
|
|
|
// This point should never be reached
|
|
Reporter.showError("Command not known");
|
|
}
|
|
|
|
|
|
/**
|
|
* Creates empty profile relations, that can be queried.
|
|
* Returns true on success.
|
|
*/
|
|
private boolean createProfileRelations()
|
|
{
|
|
List<String> commands = new ArrayList<String>();
|
|
|
|
StringBuffer sb = new StringBuffer("let ");
|
|
sb.append(RELNAME_LOAD_PROFILES_HEAD);
|
|
sb.append(" = [const rel (tuple (");
|
|
sb.append(" [ProfileName: string, FormatType: string, FormatAliases: text, ");
|
|
sb.append(" FormatQuery: text, FormatScript: text, OutputDir: text, ");
|
|
sb.append(" FormatTemplateHead: text, FormatTemplateBody: text, FormatTemplateTail: text]");
|
|
sb.append(" )) value ()]");
|
|
commands.add(sb.toString());
|
|
|
|
sb = new StringBuffer("let ");
|
|
sb.append(RELNAME_LOAD_PROFILES_POS);
|
|
sb.append(" = [const rel (tuple (");
|
|
sb.append(" [ProfileName: string, RelName: string,");
|
|
sb.append(" FilterExpr: text, ProjectExpr: text, SortExpr: text]");
|
|
sb.append(" )) value ()]");
|
|
commands.add(sb.toString());
|
|
|
|
if (!this.executeBulk(commands))
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Executes given commands.
|
|
*/
|
|
private boolean executeBulk(List<String> pCommands)
|
|
{
|
|
String errorMessage;
|
|
|
|
for (String command : pCommands)
|
|
{
|
|
if(!this.commandExecuter.executeCommand(command, SecondoInterface.EXEC_COMMAND_LISTEXPR_SYNTAX))
|
|
{
|
|
errorMessage = this.commandExecuter.getErrorMessage().toString();
|
|
Reporter.showError("UpdateViewerController.executeBulk: Error on executing command "
|
|
+ command + ": " + errorMessage);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Executes deletions for all relations.
|
|
*/
|
|
private boolean executeBulkDelete()
|
|
{
|
|
String errorMessage;
|
|
|
|
// treat all relations with deletions
|
|
for (RelationPanel rp : this.viewer.getRelationPanels())
|
|
{
|
|
List<String> deleteTupleIds = rp.getDeleteTuples();
|
|
|
|
if (!deleteTupleIds.isEmpty())
|
|
{
|
|
List<String> commands = this.commandGenerator.generateDelete(rp.getName(),
|
|
rp.getRelation().getAttributeNames(),
|
|
deleteTupleIds);
|
|
|
|
for (String com : commands){Reporter.debug("UpdateViewerController.executeDelete: " + com);}
|
|
|
|
int failures = 0;
|
|
ListExpr result;
|
|
|
|
for (String command : commands)
|
|
{
|
|
if(! this.commandExecuter.executeCommand(command, SecondoInterface.EXEC_COMMAND_LISTEXPR_SYNTAX))
|
|
{
|
|
errorMessage = this.commandExecuter.getErrorMessage().toString();
|
|
Reporter.showError("UpdateViewerController.executeDelete: Error on executing command "
|
|
+ command + ": " + errorMessage);
|
|
|
|
}
|
|
result = this.commandExecuter.getResultList();
|
|
if ( result.second().intValue() != 1)
|
|
failures++;
|
|
}
|
|
|
|
if (failures > 0)
|
|
{
|
|
if (failures > 1)
|
|
Reporter.showError("Warning: " + failures + " tuples that should be"
|
|
+ " deleted have already been deleted by a different user!");
|
|
else
|
|
Reporter.showError("Warning: One tuple that should be deleted has "
|
|
+ "already been deleted by a different user!");
|
|
}
|
|
|
|
rp.deleteTuples();
|
|
this.executeSearch(rp.getName());
|
|
}
|
|
//else Reporter.debug("UpdateViewerController.executeDelete: no deletions for relation " + rp.getName());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Executes all inserts for all relations.
|
|
*/
|
|
private boolean executeBulkInsert()
|
|
{
|
|
String errorMessage;
|
|
List<ListExpr> result = new ArrayList<ListExpr>();
|
|
|
|
|
|
RelationPanel rp = this.viewer.getCurrentRelationPanel();
|
|
rp.takeOverLastEditing(false);
|
|
|
|
{
|
|
List<String> commands = null;
|
|
|
|
try
|
|
{
|
|
commands = this.commandGenerator.generateInsert(rp.getName(),
|
|
rp.getRelation().getAttributeNames(),
|
|
rp.getRelation().getAttributeTypes(),
|
|
rp.getInsertTuples());
|
|
}
|
|
catch(InvalidFormatException e)
|
|
{
|
|
Reporter.debug(e);
|
|
errorMessage = e.getMessage() + "\n at table position (" + e.getRow() + ", " + e.getColumn()
|
|
+ "). Insert operation was not commited. Please correct error first.";
|
|
Reporter.showError(errorMessage);
|
|
rp.goToInsert(e.getRow()-1);
|
|
return false;
|
|
}
|
|
|
|
for (String command : commands)
|
|
{
|
|
ListExpr le = this.executeInsert(command);
|
|
if (le != null)
|
|
{
|
|
result.add(le);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (ListExpr le : result)
|
|
{
|
|
Reporter.debug("UpdateViewerController.executeBulkInsert: " + le.toString());
|
|
rp.insertTuple(le);
|
|
}
|
|
rp.resetInsert();
|
|
this.executeSearch(rp.getName());
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Executes updates for all relations.
|
|
*/
|
|
private boolean executeBulkUpdate()
|
|
{
|
|
String errorMessage;
|
|
|
|
for (RelationPanel rp : this.viewer.getRelationPanels())
|
|
{
|
|
rp.takeOverLastEditing(true);
|
|
|
|
List<String> commands;
|
|
|
|
Map<Integer, HashMap<String, Change>> changesByTupleId = rp.getUpdateTuples();
|
|
|
|
if (changesByTupleId.isEmpty())
|
|
{
|
|
Reporter.debug("UpdateViewerController.executeBulkUpdate: no changes in relation " + rp.getName());
|
|
}
|
|
|
|
try
|
|
{
|
|
commands = this.commandGenerator.generateUpdate(rp.getName(),
|
|
rp.getRelation().getAttributeNames(),
|
|
changesByTupleId);
|
|
|
|
for (String com : commands){Reporter.debug("UpdateViewerController.executeBulkUpdate: " + com);}
|
|
}
|
|
catch(InvalidFormatException e)
|
|
{
|
|
Reporter.debug(e);
|
|
String message = e.getMessage()+"\n at position ("+ e.getRow() + ", " + e.getColumn()
|
|
+ "). Update operations were not committed. Please correct error first. ";
|
|
Reporter.showError(message);
|
|
rp.goTo(e.getRow(), 0, 0);
|
|
|
|
return false;
|
|
}
|
|
|
|
int failures = 0;
|
|
ListExpr result;
|
|
|
|
for (String command : commands)
|
|
{
|
|
if(! this.commandExecuter.executeCommand(command, SecondoInterface.EXEC_COMMAND_LISTEXPR_SYNTAX))
|
|
{
|
|
errorMessage = this.commandExecuter.getErrorMessage().toString();
|
|
Reporter.showError("Error trying to update a tuple: " + errorMessage);
|
|
}
|
|
result = this.commandExecuter.getResultList();
|
|
if ( result.second().intValue() != 1)
|
|
failures++;
|
|
}
|
|
|
|
if (failures > 0)
|
|
{
|
|
if (failures > 1)
|
|
Reporter.showError("Warning: " + failures + " tuples that should be"
|
|
+ " updated have already been deleted by a different user!");
|
|
else
|
|
Reporter.showError("Warning: One tuple that should be updated has "
|
|
+ "already been deleted by a different user!");
|
|
}
|
|
|
|
rp.clearUpdateChanges();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Executes one single insert command.
|
|
* Returns the inserted tuple (with tuple ID)
|
|
*/
|
|
private ListExpr executeInsert(String pCommand)
|
|
{
|
|
Reporter.debug("UpdateViewerController.executeInsert: " + pCommand);
|
|
if(!this.commandExecuter.executeCommand(pCommand, SecondoInterface.EXEC_COMMAND_LISTEXPR_SYNTAX))
|
|
{
|
|
Reporter.showError("Error trying to insert a tuple: "
|
|
+ this.commandExecuter.getErrorMessage().toString());
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
ListExpr le = new ListExpr();
|
|
le.setValueTo(this.commandExecuter.getResultList());
|
|
if (!le.isEmpty() && le.listLength() == 2)
|
|
{
|
|
return le.second().first();
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Executes search and shows results in specified RelationPanel.
|
|
*/
|
|
private boolean executeSearch(String pRelationName)
|
|
{
|
|
RelationPanel rp = this.viewer.getRelationPanel(pRelationName);
|
|
|
|
if (rp == null || !rp.getSearchActive())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
String key = rp.getSearchKey();
|
|
boolean caseSensitive = rp.getCaseSensitive();
|
|
List<SearchHit> hitlist = rp.retrieveSearchHits(key, caseSensitive);
|
|
|
|
rp.setSearchHits(hitlist);
|
|
rp.showSearchResult();
|
|
|
|
if (hitlist == null || hitlist.isEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
private boolean executeSingleInsert(String pRelName, Tuple pTuple, ListExpr ioLE)
|
|
{
|
|
if (pTuple == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
List<Tuple> li = new ArrayList<Tuple>();
|
|
li.add(pTuple);
|
|
RelationTypeInfo type = pTuple.getTypeInfo();
|
|
|
|
List<String> commands = this.commandGenerator.generateInsert(pRelName,
|
|
type.getAttributeNames(),
|
|
type.getAttributeTypes(),
|
|
li);
|
|
|
|
ListExpr tupleLE = this.executeInsert(commands.get(0));
|
|
if (tupleLE != null)
|
|
{
|
|
Reporter.debug("executeSingleInsert: resultLE=" + tupleLE.toString());
|
|
ioLE.setValueTo(tupleLE);
|
|
}
|
|
|
|
}
|
|
catch (InvalidFormatException e)
|
|
{
|
|
Reporter.debug(e);
|
|
Reporter.showError("InvalidFormatException: " + e.getMessage());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
private boolean executeSingleUpdate(String pRelName, List<String> pAttributeNames,
|
|
Map<Integer,HashMap<String, Change>> pChangesForUpdate)
|
|
{
|
|
try
|
|
{
|
|
List<String> commands = this.commandGenerator.generateUpdate(pRelName,
|
|
pAttributeNames,
|
|
pChangesForUpdate);
|
|
|
|
if (commands == null || commands.isEmpty())
|
|
{
|
|
Reporter.debug("UpdateViewerController.executeSingleUpdate: no update commands generated for relation " + pRelName);
|
|
return false;
|
|
}
|
|
|
|
if(! this.commandExecuter.executeCommand(commands.get(0), SecondoInterface.EXEC_COMMAND_LISTEXPR_SYNTAX))
|
|
{
|
|
String errorMessage = this.commandExecuter.getErrorMessage().toString();
|
|
Reporter.showError("Error trying to update a tuple: " + errorMessage);
|
|
return false;
|
|
}
|
|
ListExpr result = this.commandExecuter.getResultList();
|
|
if ( result.second().intValue() != 1)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
catch (InvalidFormatException e)
|
|
{
|
|
Reporter.debug(e);
|
|
Reporter.showError("InvalidFormatException: " + e.getMessage());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns true if relation exists in currently open database.
|
|
*/
|
|
private boolean existsInDb(String pObjectName)
|
|
{
|
|
if (!commandExecuter.executeCommand("(list objects)", SecondoInterface.EXEC_COMMAND_LISTEXPR_SYNTAX))
|
|
{
|
|
Reporter.showError("Error on command \"list objects\": "
|
|
+ this.commandExecuter.getErrorMessage().toString());
|
|
return false;
|
|
}
|
|
|
|
ListExpr inquiry = commandExecuter.getResultList();
|
|
ListExpr objectList = inquiry.second().second();
|
|
objectList.first();
|
|
ListExpr rest = objectList.rest();
|
|
ListExpr nextObject;
|
|
String name;
|
|
|
|
while (!rest.isEmpty())
|
|
{
|
|
nextObject = rest.first();
|
|
|
|
name = nextObject.second().symbolValue();
|
|
if (name.equals(pObjectName))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
rest = rest.rest();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
/*
|
|
* Retrieves the relation with specified name and restrictions.
|
|
*/
|
|
private ListExpr loadRelation(String pRelName, List<String> pFilter, List<String> pProject, List<String> pSort)
|
|
{
|
|
ListExpr result = null;
|
|
|
|
String command = this.commandGenerator.generateLoad(pRelName, pFilter, pProject, pSort);
|
|
|
|
Reporter.debug("loadRelation: command=" + command);
|
|
|
|
long millisStart = System.currentTimeMillis();
|
|
|
|
if (this.commandExecuter.executeCommand(command, SecondoInterface.EXEC_COMMAND_SOS_SYNTAX))
|
|
{
|
|
result = new ListExpr();
|
|
result.setValueTo(this.commandExecuter.getResultList());
|
|
//Reporter.debug("loadRelation: resultLE=" + result.toString());
|
|
}
|
|
else
|
|
{
|
|
String errorMessage = commandExecuter.getErrorMessage().toString();
|
|
Reporter.showError(errorMessage);
|
|
}
|
|
|
|
long millis = System.currentTimeMillis() - millisStart;
|
|
Reporter.debug("UpdateViewerController.processCommandLoadFromProfilet: secondo load time for relation "
|
|
+ pRelName + " (millis): " + millis);
|
|
|
|
return result;
|
|
}
|
|
|
|
public void mouseClicked(MouseEvent pEvent){;}
|
|
public void mouseEntered(MouseEvent pEvent){;}
|
|
public void mouseExited(MouseEvent pEvent){;}
|
|
public void mouseReleased(MouseEvent pEvent){;}
|
|
|
|
public void mousePressed(MouseEvent pEvent)
|
|
{
|
|
if (pEvent.getSource() instanceof DocumentPanel)
|
|
{
|
|
DocumentPanel doc = (DocumentPanel)pEvent.getSource();
|
|
RelationPosition pos = this.formatDialog.getCurrentPosition();
|
|
this.formatDialog.setCurrentPosition(pos);
|
|
this.formatDialog.showPositionInfo();
|
|
if (pos!=null)
|
|
{
|
|
this.processCommandGoToEdit();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
private boolean processCommandAddLoadProfile()
|
|
{
|
|
String name = JOptionPane.showInputDialog("Name the load profile " );
|
|
|
|
if (name == null || name.length() == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (this.loadDialog.getLoadProfile(name) != null)
|
|
{
|
|
Reporter.showError("Profile name already exists. Please choose a different name.");
|
|
return false;
|
|
}
|
|
|
|
this.loadDialog.showEditLoadProfile(name);
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Shows edit dialog for new relation profile.
|
|
*/
|
|
private boolean processCommandAddRelationProfile()
|
|
{
|
|
String relname = this.showChooseRelationDialog();
|
|
|
|
if (relname == null || relname.length() == 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
String profname = this.loadDialog.getCurrentLoadProfileName();
|
|
if (this.loadDialog.getRelationProfile(profname, relname) != null)
|
|
{
|
|
Reporter.showError("Relation already exists in this load profile. Please choose a different relation.");
|
|
return false;
|
|
}
|
|
|
|
this.loadDialog.showEditRelationProfile(profname, relname);
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Removes any relations from viewer panel and disposes of format window if open.
|
|
*/
|
|
private void processCommandClear()
|
|
{
|
|
this.viewer.clear();
|
|
this.loadProfile = null;
|
|
this.formatter = null;
|
|
if (this.formatDialog != null)
|
|
{
|
|
this.formatDialog.dispose();
|
|
this.formatDialog = null;
|
|
}
|
|
this.setState(States.INITIAL);
|
|
}
|
|
|
|
/**
|
|
* Resets search panels for all relations.
|
|
*/
|
|
private void processCommandClearSearch()
|
|
{
|
|
for (RelationPanel rp : this.viewer.getRelationPanels())
|
|
{
|
|
rp.clearSearch();
|
|
rp.setSearchActive(false);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Commits all changes (INSERT, DELETE or UPDATE) to database.
|
|
*/
|
|
private boolean processCommandCommit()
|
|
{
|
|
boolean result = false;
|
|
|
|
switch (state)
|
|
{
|
|
case States.INSERT:
|
|
{
|
|
result = this.executeBulkInsert();
|
|
break;
|
|
}
|
|
case States.DELETE:
|
|
{
|
|
result = this.executeBulkDelete();
|
|
break;
|
|
}
|
|
case States.UPDATE:
|
|
{
|
|
result = this.executeBulkUpdate();
|
|
break;
|
|
}
|
|
default: break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/**
|
|
* Load Dialog action:
|
|
* Show currently selected load profile in editor.
|
|
*/
|
|
private boolean processCommandEditLoadProfile()
|
|
{
|
|
String loadProfile = this.loadDialog.getCurrentLoadProfileName();
|
|
this.loadDialog.showEditLoadProfile(loadProfile);
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Shows the formatted document as specified in the load profile.
|
|
*/
|
|
private boolean processCommandFormat()
|
|
{
|
|
|
|
try
|
|
{
|
|
if (this.formatter== null)
|
|
{
|
|
// adapt query to sorting and filtering as specified in RelationProfiles
|
|
String query = this.loadProfile.getFormatQuery();
|
|
for (RelationProfile rp : this.loadProfile.getRelationProfiles())
|
|
{
|
|
query = this.commandGenerator.adaptFormatQuery(query, rp.getRelationName(),
|
|
rp.getFilterExpressions(),
|
|
rp.getSortExpressions());
|
|
}
|
|
|
|
// create formatter
|
|
this.formatter = DocumentFormatter.createFormatter(this.loadProfile.getFormatType());
|
|
|
|
this.formatter.initialize(this.loadProfile.getFormatAliases(),
|
|
query,
|
|
this.loadProfile.getOutputDirectory(),
|
|
this.loadProfile.getFormatScript(),
|
|
this.loadProfile.getFormatTemplateHead(),
|
|
this.loadProfile.getFormatTemplateBody(),
|
|
this.loadProfile.getFormatTemplateTail());
|
|
|
|
//Reporter.debug("UpdateViewerController.processCommandFormat: initialized " + formatter.toString());
|
|
|
|
if (!formatter.hasTemplates())
|
|
{
|
|
Reporter.showInfo("Format templates in load profile are not complete. \nWill use default templates. ");
|
|
}
|
|
}
|
|
|
|
// should document come as separate pages or single-paged?
|
|
boolean separatePages = this.formatDialog.getSeparatePages();
|
|
// is there a script to be executed on the output?
|
|
boolean applyScript = this.formatDialog.getApplyScript();
|
|
|
|
// let formatter get data and do the formatting
|
|
formatter.format(separatePages, applyScript);
|
|
|
|
List<Object> outputPages = formatter.getOutputPages();
|
|
if (outputPages == null || outputPages.isEmpty())
|
|
{
|
|
Reporter.showError("No output created.");
|
|
return false;
|
|
}
|
|
|
|
// display formatted page(s)
|
|
DocumentPanel docPanel = DocumentPanel.createDocumentPanel(formatter);
|
|
docPanel.load(formatter.getOutputPages());
|
|
this.formatDialog.setFormattedDocument(docPanel);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Reporter.debug(e);
|
|
Reporter.showError(e.getMessage());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
private boolean processCommandGoToEdit()
|
|
{
|
|
RelationPosition posInfo = this.formatDialog.getCurrentPosition();
|
|
|
|
if (posInfo == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
this.viewer.getMainFrame().toFront();
|
|
RelationPanel rp = this.viewer.getRelationPanel(posInfo.getRelationName());
|
|
|
|
if (rp == null)
|
|
{
|
|
Reporter.showError("Relation \"" + posInfo.getRelationName()
|
|
+ "\" is currently not loaded. \nPlease add relation to your load profile. ");
|
|
return false;
|
|
}
|
|
|
|
this.setState(States.UPDATE);
|
|
this.viewer.showRelationPanel(this.viewer.getRelationPanels().indexOf(rp));
|
|
rp.goTo(posInfo.getAttributeName(),
|
|
posInfo.getTupleId(),
|
|
posInfo.getOffset());
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Shows insert table with one empty tuple if INSERT was pressed for the first time,
|
|
* else adds an empty tuple to the insert table.
|
|
*/
|
|
private boolean processCommandInsert()
|
|
{
|
|
if (viewer.getCurrentRelationPanel().getState() != States.LOADED_READ_ONLY)
|
|
{
|
|
try
|
|
{
|
|
|
|
if (this.state != States.INSERT)
|
|
{
|
|
viewer.getCurrentRelationPanel().showInsertTable();
|
|
}
|
|
else
|
|
{
|
|
// User wants to insert one more tuple
|
|
viewer.getCurrentRelationPanel().takeOverLastEditing(false);
|
|
viewer.getCurrentRelationPanel().addInsertTuple();
|
|
}
|
|
}
|
|
catch(InvalidRelationException e)
|
|
{
|
|
Reporter.debug(e);
|
|
Reporter.showError(e.getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Loads all relations of the currently selected LoadProfile from database
|
|
* and shows them in the viewer.
|
|
*/
|
|
private boolean processCommandLoadDirect()
|
|
{
|
|
|
|
String relName = this.showChooseRelationDialog();
|
|
if (relName == null || relName.isEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ListExpr relationLE = this.loadRelation(relName, null, null, null);
|
|
|
|
if (relationLE == null)
|
|
{
|
|
Reporter.showError("Error while loading relation " + relName);
|
|
return false;
|
|
}
|
|
|
|
this.processCommandClear();
|
|
this.viewer.setRelationPanel(relName, relationLE, true);
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Loads all relations of the currently selected LoadProfile from database
|
|
* and shows them in the viewer.
|
|
*/
|
|
private boolean processCommandLoadFromProfile()
|
|
{
|
|
this.processCommandClear();
|
|
|
|
String profileName = this.loadDialog.getCurrentLoadProfileName();
|
|
this.loadProfile = this.loadDialog.getLoadProfile(profileName);
|
|
String errorMessage = "";
|
|
|
|
if (loadProfile == null)
|
|
{
|
|
errorMessage = "Please select or create a Load Profile.";
|
|
Reporter.showError(errorMessage);
|
|
return false;
|
|
}
|
|
|
|
for(RelationProfile relprof : loadProfile.getRelationProfiles())
|
|
{
|
|
ListExpr relationLE = this.loadRelation(relprof.getRelationName(),
|
|
relprof.getFilterExpressions(),
|
|
relprof.getProjectExpressions(),
|
|
relprof.getSortExpressions());
|
|
|
|
if (relationLE == null)
|
|
{
|
|
errorMessage += "Error while loading relation " + relprof.getRelationName() + ". ";
|
|
}
|
|
else
|
|
{
|
|
long millisStart = System.currentTimeMillis();
|
|
this.viewer.setRelationPanel(relprof.getRelationName(), relationLE, true);
|
|
long millis = System.currentTimeMillis() - millisStart;
|
|
Reporter.debug("UpdateViewerController.processCommandLoadFromProfile: setRelationPanel time for relation "
|
|
+ relprof.getRelationName() + " (millis): " + millis);
|
|
}
|
|
}
|
|
|
|
if (errorMessage != null && errorMessage.length()!=0)
|
|
{
|
|
Reporter.showError(errorMessage);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
*
|
|
*/
|
|
private boolean processCommandNext()
|
|
{
|
|
int hitIndex = this.viewer.getCurrentRelationPanel().getCurrentHitIndex()+1;
|
|
if (hitIndex<0 || hitIndex < this.viewer.getCurrentRelationPanel().getHitCount())
|
|
{
|
|
this.viewer.getCurrentRelationPanel().showHit(hitIndex);
|
|
}
|
|
else
|
|
{
|
|
int rpIndex = this.viewer.getRelationPanels().indexOf(this.viewer.getCurrentRelationPanel())+1;
|
|
boolean found = false;
|
|
while (rpIndex < this.viewer.getRelationPanels().size() && !found)
|
|
{
|
|
if (this.viewer.getRelationPanel(rpIndex).hasSearchHits())
|
|
{
|
|
found = true;
|
|
this.viewer.showRelationPanel(rpIndex);
|
|
this.viewer.getCurrentRelationPanel().showHit(0);
|
|
}
|
|
rpIndex++;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Shows the load dialog.
|
|
* Loads Profiles from DB.
|
|
* Creates Profile relations if not yet existent.
|
|
*/
|
|
private void processCommandOpenLoadDialog()
|
|
{
|
|
try
|
|
{
|
|
// test if client is connected to secondo and database is open
|
|
int connectionState = this.commandExecuter.testConnection();
|
|
if (connectionState != 0)
|
|
{
|
|
Reporter.showError(ServerErrorCodes.getErrorMessageText(connectionState));
|
|
return;
|
|
}
|
|
|
|
// test if profiles exist in database
|
|
boolean result = true;
|
|
|
|
if (!this.existsInDb(RELNAME_LOAD_PROFILES_HEAD))
|
|
{
|
|
result = this.createProfileRelations();
|
|
}
|
|
|
|
// load profiles
|
|
if (result)
|
|
{
|
|
try
|
|
{
|
|
ListExpr profilesLE = this.loadRelation(RELNAME_LOAD_PROFILES_HEAD, null, null, null);
|
|
ListExpr relationsLE = this.loadRelation(RELNAME_LOAD_PROFILES_POS, null, null, null);
|
|
|
|
if(profilesLE == null || relationsLE == null)
|
|
{
|
|
this.setState(States.INITIAL);
|
|
Reporter.showError(commandExecuter.getErrorMessage().toString());
|
|
}
|
|
else
|
|
{
|
|
this.loadDialog = new LoadDialog(this);
|
|
this.loadDialog.showProfiles(profilesLE, relationsLE);
|
|
this.loadDialog.setVisible(true);
|
|
}
|
|
}
|
|
catch (InvalidRelationException e)
|
|
{
|
|
Reporter.debug(e);
|
|
Reporter.showError(e.getMessage());
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
Reporter.debug(e);
|
|
Reporter.showError(e.getMessage());
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Shows the format dialog.
|
|
*/
|
|
private void processCommandOpenFormatDialog()
|
|
{
|
|
if (this.loadProfile == null)
|
|
{
|
|
Reporter.showInfo("No active load profile found. To format please load relation(s) from a load profile.");
|
|
return;
|
|
}
|
|
if (this.formatDialog == null)
|
|
{
|
|
this.formatDialog = new FormatDialog(this);
|
|
}
|
|
|
|
this.formatDialog.setVisible(true);
|
|
}
|
|
|
|
/**
|
|
* Skips to previous search hit, if any.
|
|
* If current search hit was first search hit in the current relation,
|
|
* skips to last search hit in a previous relation if there are search hits.
|
|
*/
|
|
private boolean processCommandPrevious()
|
|
{
|
|
int hitIndex = this.viewer.getCurrentRelationPanel().getCurrentHitIndex()-1;
|
|
if (hitIndex >= 0)
|
|
{
|
|
this.viewer.getCurrentRelationPanel().showHit(hitIndex);
|
|
}
|
|
else
|
|
{
|
|
int rpIndex = this.viewer.getRelationPanels().indexOf(this.viewer.getCurrentRelationPanel())-1;
|
|
boolean found = false;
|
|
while (rpIndex >= 0 && !found)
|
|
{
|
|
if (this.viewer.getRelationPanel(rpIndex).hasSearchHits())
|
|
{
|
|
found = true;
|
|
this.viewer.showRelationPanel(rpIndex);
|
|
this.viewer.getCurrentRelationPanel().showHit(this.viewer.getCurrentRelationPanel().getHitCount()-1);
|
|
}
|
|
rpIndex--;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Deletes all entries for specified load profile from the database.
|
|
*/
|
|
private boolean processCommandRemoveLoadProfile(String pProfileName)
|
|
{
|
|
String profileName = this.loadDialog.getCurrentLoadProfileName();
|
|
|
|
// remove dependent relation profiles
|
|
for (RelationProfile rp : this.loadDialog.getRelationProfiles(profileName))
|
|
{
|
|
this.processCommandRemoveRelationProfile(profileName, rp.getRelationName());
|
|
this.loadDialog.removeRelationProfile(profileName, rp.getRelationName());
|
|
}
|
|
|
|
// remove load profile
|
|
StringBuffer sb = new StringBuffer();
|
|
sb.append("query ").append(RELNAME_LOAD_PROFILES_HEAD);
|
|
sb.append(" feed filter[.ProfileName = \"");
|
|
sb.append(pProfileName);
|
|
sb.append("\"] consume feed ");
|
|
sb.append(RELNAME_LOAD_PROFILES_HEAD);
|
|
sb.append(" deletesearch consume");
|
|
|
|
if (!commandExecuter.executeCommand(sb.toString(), SecondoInterface.EXEC_COMMAND_LISTEXPR_SYNTAX))
|
|
{
|
|
Reporter.showError(commandExecuter.getErrorMessage().toString());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Deletes the entry for the specified relation profile from the database.
|
|
*/
|
|
private boolean processCommandRemoveRelationProfile(String pLoadProfileName, String pRelName)
|
|
{
|
|
StringBuffer sb = new StringBuffer();
|
|
sb.append("query ").append(RELNAME_LOAD_PROFILES_POS);
|
|
sb.append(" feed filter[.ProfileName = \"").append(pLoadProfileName);
|
|
sb.append("\"] filter[.RelName = \"").append(pRelName);
|
|
sb.append("\"] consume feed ");
|
|
sb.append(RELNAME_LOAD_PROFILES_POS);
|
|
sb.append(" deletesearch consume");
|
|
|
|
if (!commandExecuter.executeCommand(sb.toString(), SecondoInterface.EXEC_COMMAND_LISTEXPR_SYNTAX))
|
|
{
|
|
Reporter.debug(sb.toString());
|
|
Reporter.showError(commandExecuter.getErrorMessage().toString());
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Replaces search key at current SearchHit position and skips to next SearchHit.
|
|
* Displays confirmation dialog first.
|
|
*/
|
|
private boolean processCommandReplace()
|
|
{
|
|
RelationPanel rp = this.viewer.getCurrentRelationPanel();
|
|
|
|
if (rp.getState() == States.LOADED_READ_ONLY)
|
|
{
|
|
Reporter.showInfo("Replace not possible: relation \"" + rp.getName() + "\" is read-only.");
|
|
return false;
|
|
}
|
|
|
|
String key = rp.getSearchKey();
|
|
String replacement = rp.getReplacement();
|
|
|
|
if (replacement == null)
|
|
{
|
|
replacement = "";
|
|
}
|
|
|
|
if (rp.getCurrentHitIndex() >= 0)
|
|
{
|
|
int currHitIndex = rp.getCurrentHitIndex();
|
|
SearchHit hit = rp.getHit(currHitIndex);
|
|
rp.replace(hit);
|
|
rp.showSearchResult();
|
|
rp.showHit(currHitIndex);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Replaces search key in all loaded tuples of all (editable) relations.
|
|
* Displays confirmation dialog first.
|
|
*/
|
|
private boolean processCommandReplaceAll()
|
|
{
|
|
RelationPanel crp = this.viewer.getCurrentRelationPanel();
|
|
String replacement = crp.getReplacement();
|
|
String key = crp.getSearchKey();
|
|
boolean caseSensitive = crp.getCaseSensitive();
|
|
int count = 0;
|
|
|
|
StringBuilder msg = new StringBuilder();
|
|
msg.append("Really replace all search matches by \"").append(replacement).append("\" in all loaded relations?");
|
|
if (!caseSensitive)
|
|
{
|
|
msg.append("\n\n(Please note: current search mode is CASE-INSENSITIVE.)");
|
|
}
|
|
|
|
int option = JOptionPane.showConfirmDialog(crp
|
|
, msg.toString()
|
|
, "Replace all"
|
|
, JOptionPane.YES_NO_OPTION);
|
|
|
|
if (option == JOptionPane.YES_OPTION)
|
|
{
|
|
for (RelationPanel rp : this.viewer.getRelationPanels())
|
|
{
|
|
if (rp.getState() == States.LOADED_READ_ONLY)
|
|
{
|
|
Reporter.showInfo("Replace not possible: relation \"" + rp.getName() + "\" is read-only and will be skipped.");
|
|
}
|
|
else
|
|
{
|
|
rp.setReplacement(replacement);
|
|
|
|
while (rp.hasSearchHits())
|
|
{
|
|
rp.replace(rp.getHit(0));
|
|
count ++;
|
|
}
|
|
rp.showSearchResult();
|
|
}
|
|
}
|
|
}
|
|
|
|
Reporter.showInfo("Replaced " + count + " occurences.");
|
|
return true;
|
|
}
|
|
|
|
private boolean processCommandPrint(){
|
|
RelationPanel crp = this.viewer.getCurrentRelationPanel();
|
|
if(crp!=null){
|
|
return crp.print();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
/**
|
|
* Resets all uncommitted changes according to current state.
|
|
*/
|
|
private boolean processCommandReset()
|
|
{
|
|
switch(this.state)
|
|
{
|
|
case States.INSERT:
|
|
for (RelationPanel rp : this.viewer.getRelationPanels())
|
|
{
|
|
rp.resetInsert();
|
|
}
|
|
break;
|
|
case States.UPDATE:
|
|
for (RelationPanel rp : this.viewer.getRelationPanels())
|
|
{
|
|
rp.resetUpdateChanges();
|
|
}
|
|
break;
|
|
case States.DELETE:
|
|
for (RelationPanel rp : this.viewer.getRelationPanels())
|
|
{
|
|
rp.resetDeleteSelections();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
for (RelationPanel rp : this.viewer.getRelationPanels())
|
|
{
|
|
this.executeSearch(rp.getName());
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
private boolean processCommandSaveLoadProfile()
|
|
{
|
|
Tuple tuple = this.loadDialog.getEditTuple();
|
|
if (tuple== null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (tuple.getID() == null || tuple.getID().length() == 0) // tuple is to be inserted
|
|
{
|
|
ListExpr resultLE = new ListExpr();
|
|
if (!this.executeSingleInsert(RELNAME_LOAD_PROFILES_HEAD, tuple, resultLE))
|
|
{
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
this.loadDialog.addLoadProfile(resultLE);
|
|
}
|
|
catch (InvalidRelationException e)
|
|
{
|
|
Reporter.debug(e);
|
|
Reporter.showError(e.getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
else // tuple is to be updated
|
|
{
|
|
List<String> attributeNames = tuple.getTypeInfo().getAttributeNames();
|
|
Map<Integer, HashMap<String, Change>> changesForUpdate = this.loadDialog.getUpdateTuples();
|
|
|
|
if (!this.executeSingleUpdate(RELNAME_LOAD_PROFILES_HEAD, attributeNames, changesForUpdate))
|
|
{
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
this.loadDialog.updateLoadProfile(tuple);
|
|
}
|
|
catch (InvalidRelationException e)
|
|
{
|
|
Reporter.debug(e);
|
|
Reporter.showError(e.getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
*
|
|
*/
|
|
private boolean processCommandSaveRelationProfile()
|
|
{
|
|
Tuple tuple = this.loadDialog.getEditTuple();
|
|
if (tuple== null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (tuple.getID() == null || tuple.getID().length() == 0) // tuple is to be inserted
|
|
{
|
|
ListExpr resultLE = new ListExpr();
|
|
if (!this.executeSingleInsert(RELNAME_LOAD_PROFILES_POS, tuple, resultLE))
|
|
{
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
this.loadDialog.addRelationProfile(resultLE);
|
|
}
|
|
catch (InvalidRelationException e)
|
|
{
|
|
Reporter.debug(e);
|
|
Reporter.showError(e.getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
else // tuple is to be updated
|
|
{
|
|
List<String> attributeNames = tuple.getTypeInfo().getAttributeNames();
|
|
Map<Integer, HashMap<String, Change>> changesForUpdate = this.loadDialog.getUpdateTuples();
|
|
|
|
if (!this.executeSingleUpdate(RELNAME_LOAD_PROFILES_POS, attributeNames, changesForUpdate))
|
|
{
|
|
return false;
|
|
}
|
|
try
|
|
{
|
|
this.loadDialog.updateRelationProfile(tuple);
|
|
}
|
|
catch (InvalidRelationException e)
|
|
{
|
|
Reporter.debug(e);
|
|
Reporter.showError(e.getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Retrieves hits for keyword in search field and displays result in UpdateViewer2.
|
|
* @return TRUE if any hits were found
|
|
*/
|
|
private boolean processCommandSearch()
|
|
{
|
|
String key = this.viewer.getCurrentRelationPanel().getSearchKey();
|
|
boolean caseSensitive = this.viewer.getCurrentRelationPanel().getCaseSensitive();
|
|
|
|
// if at least one of the relations has hits then display search results in RelationPanel.
|
|
int first = -1;
|
|
for (RelationPanel rp : this.viewer.getRelationPanels())
|
|
{
|
|
rp.setSearchKey(key);
|
|
rp.setCaseSensitive(caseSensitive);
|
|
rp.setSearchActive(true);
|
|
|
|
long millisStart = System.currentTimeMillis();
|
|
|
|
if (this.executeSearch(rp.getName()) && first<0)
|
|
{
|
|
first = this.viewer.getRelationPanels().indexOf(rp);
|
|
}
|
|
|
|
long millis = System.currentTimeMillis() - millisStart;
|
|
Reporter.debug("UpdateViewerController.processCommandSearch: search time for relation "
|
|
+ rp.getName() + " (millis): " + millis);
|
|
}
|
|
|
|
// go to first hit in first RelationPanel with a hit (if there is any)
|
|
if (first < 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
this.viewer.showRelationPanel(first);
|
|
RelationPanel rp = this.viewer.getCurrentRelationPanel();
|
|
rp.showHit(0);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Undoes last uncommitted change (cell-wise), deletion or insertion.
|
|
*/
|
|
private void processCommandUndo()
|
|
{
|
|
if(this.state == States.INSERT)
|
|
{
|
|
this.viewer.getCurrentRelationPanel().removeLastInsertTuple();
|
|
}
|
|
if(this.state == States.UPDATE)
|
|
{
|
|
this.viewer.getCurrentRelationPanel().undoLastUpdateChange();
|
|
}
|
|
if(this.state == States.DELETE)
|
|
{
|
|
this.viewer.getCurrentRelationPanel().undoLastDeleteSelection();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns names of all non-nested relations in currently open database.
|
|
*/
|
|
private List<String> retrieveRelationNames()
|
|
{
|
|
List<String> result = new ArrayList<String>();
|
|
commandExecuter.executeCommand("(list objects)", SecondoInterface.EXEC_COMMAND_LISTEXPR_SYNTAX);
|
|
ListExpr inquiry = commandExecuter.getResultList();
|
|
ListExpr objectList = inquiry.second().second();
|
|
objectList.first();
|
|
ListExpr rest = objectList.rest();
|
|
ListExpr nextObject;
|
|
ListExpr type;
|
|
String name;
|
|
|
|
while (!rest.isEmpty())
|
|
{
|
|
nextObject = rest.first();
|
|
type = nextObject.fourth();
|
|
if (!(type.first().isAtom())){
|
|
if ((type.first().first().isAtom())){
|
|
String objectType = type.first().first().symbolValue();
|
|
if (objectType.equals("rel")
|
|
|| objectType.equals("trel")
|
|
|| objectType.equals("mrel")
|
|
|| objectType.equals("orel")){
|
|
name = nextObject.second().symbolValue();
|
|
result.add(name);
|
|
}
|
|
}
|
|
}
|
|
rest = rest.rest();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets state attribute of this controller and sets selection mode of UpdateViewer2.
|
|
*/
|
|
public void setState(int pState)
|
|
{
|
|
/*if (this.loadProfile == null)
|
|
{
|
|
this.state = States.LOADED_READ_ONLY;
|
|
this.viewer.setSelectionMode(States.LOADED_READ_ONLY);
|
|
}
|
|
else
|
|
{*/
|
|
this.state = pState;
|
|
this.viewer.setSelectionMode(pState);
|
|
//}
|
|
}
|
|
|
|
/**
|
|
* Shows input dialog with list of relations in open database.
|
|
*/
|
|
private String showChooseRelationDialog()
|
|
{
|
|
String result = "";
|
|
|
|
List<String> names = this.retrieveRelationNames();
|
|
|
|
if (names.isEmpty())
|
|
{
|
|
JOptionPane.showConfirmDialog(null, "Database contains no relations.", "", JOptionPane.OK_OPTION);
|
|
}
|
|
else
|
|
{
|
|
Object selection = JOptionPane.showInputDialog(null,
|
|
"Select a relation", "Select a relation",
|
|
JOptionPane.INFORMATION_MESSAGE, null,
|
|
names.toArray(), names.get(0));
|
|
if (selection != null)
|
|
{
|
|
result = (String)selection;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
}
|