diff options
Diffstat (limited to 'src/main/java/com/c2kernel/gui/tabs')
50 files changed, 7061 insertions, 0 deletions
diff --git a/src/main/java/com/c2kernel/gui/tabs/AgentPropertiesPane.java b/src/main/java/com/c2kernel/gui/tabs/AgentPropertiesPane.java new file mode 100644 index 0000000..f0ae533 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/AgentPropertiesPane.java @@ -0,0 +1,51 @@ +package com.c2kernel.gui.tabs;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/07/05 11:34:17 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+public class AgentPropertiesPane extends EntityTabPane {
+
+ JTable roleTable;
+ JTextField newPassword;
+ JTextField newPasswordConfirm;
+ JButton changePassword;
+
+ public AgentPropertiesPane() {
+ super("Properties", "Agent Details");
+ initPanel();
+ getGridBagConstraints();
+ c.gridy++;
+ JLabel roleHeader = new JLabel("Roles held");
+ roleHeader.setFont(titleFont);
+ roleHeader.setForeground(headingColor);
+ gridbag.setConstraints(roleHeader, c);
+ add(roleHeader);
+ roleTable = new JTable(1,1);
+ JScrollPane roleScroll = new JScrollPane(roleTable);
+ c.gridy++;
+ gridbag.setConstraints(roleScroll, c);
+ add(roleScroll);
+
+ //JLabel passHeader = new JLabel("Change password");
+ //TODO: Finish agent admin page
+ }
+
+ @Override
+ public void run() {
+
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/CloseTabIcon.java b/src/main/java/com/c2kernel/gui/tabs/CloseTabIcon.java new file mode 100644 index 0000000..a117df4 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/CloseTabIcon.java @@ -0,0 +1,70 @@ +package com.c2kernel.gui.tabs;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Graphics;
+import java.awt.Rectangle;
+
+import javax.swing.Icon;
+
+/**
+ * @author Developpement
+ *
+ * To change this generated comment edit the template variable "typecomment":
+ * Window>Preferences>Java>Templates.
+ * To enable and disable the creation of type comments go to
+ * Window>Preferences>Java>Code Generation.
+ */
+/** * The class which generates the 'X' icon for the tabs. The constructor * accepts an icon which is extra to the 'X' icon, so you can have tabs * like in JBuilder. This value is null if no extra icon is required. */
+class CloseTabIcon implements Icon
+{
+ private int x_pos;
+ private int y_pos;
+ private int width;
+ private int height;
+ private Icon fileIcon;
+ public CloseTabIcon(Icon fileIcon)
+ {
+ this.fileIcon = fileIcon;
+ width = 16;
+ height = 16;
+ }
+ @Override
+ public void paintIcon(Component c, Graphics g, int x, int y)
+ {
+ this.x_pos = x;
+ this.y_pos = y;
+ Color col = g.getColor();
+ g.setColor(Color.black);
+ int y_p = y + 2;
+ g.drawLine(x + 1, y_p, x + 12, y_p);
+ g.drawLine(x + 1, y_p + 13, x + 12, y_p + 13);
+ g.drawLine(x, y_p + 1, x, y_p + 12);
+ g.drawLine(x + 13, y_p + 1, x + 13, y_p + 12);
+ g.drawLine(x + 3, y_p + 3, x + 10, y_p + 10);
+ g.drawLine(x + 3, y_p + 4, x + 9, y_p + 10);
+ g.drawLine(x + 4, y_p + 3, x + 10, y_p + 9);
+ g.drawLine(x + 10, y_p + 3, x + 3, y_p + 10);
+ g.drawLine(x + 10, y_p + 4, x + 4, y_p + 10);
+ g.drawLine(x + 9, y_p + 3, x + 3, y_p + 9);
+ g.setColor(col);
+ if (fileIcon != null)
+ {
+ fileIcon.paintIcon(c, g, x + width, y_p);
+ }
+ }
+ @Override
+ public int getIconWidth()
+ {
+ return width + (fileIcon != null ? fileIcon.getIconWidth() : 0);
+ }
+ @Override
+ public int getIconHeight()
+ {
+ return height;
+ }
+ public Rectangle getBounds()
+ {
+ return new Rectangle(x_pos, y_pos, width, height);
+ }
+}
\ No newline at end of file diff --git a/src/main/java/com/c2kernel/gui/tabs/CollectionPane.java b/src/main/java/com/c2kernel/gui/tabs/CollectionPane.java new file mode 100644 index 0000000..4d9092e --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/CollectionPane.java @@ -0,0 +1,109 @@ +package com.c2kernel.gui.tabs;
+import java.awt.GridBagConstraints;
+
+import javax.swing.JTabbedPane;
+
+import com.c2kernel.collection.Aggregation;
+import com.c2kernel.collection.Collection;
+import com.c2kernel.collection.CollectionMember;
+import com.c2kernel.collection.Dependency;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.entity.proxy.MemberSubscription;
+import com.c2kernel.gui.tabs.collection.AggregationView;
+import com.c2kernel.gui.tabs.collection.CollectionView;
+import com.c2kernel.gui.tabs.collection.DependencyView;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+/**
+ * @version $Revision: 1.36 $ $Date: 2005/10/06 06:51:15 $
+ * @author $Author: abranson $
+ */
+public class CollectionPane extends EntityTabPane implements EntityProxyObserver<Collection<? extends CollectionMember>>
+{
+ JTabbedPane collTabs;
+
+ public CollectionPane()
+ {
+ super("Collection", "Item Collection");
+ createLayout();
+ }
+
+ @Override
+ public void add(Collection<? extends CollectionMember> contents)
+ {
+ Logger.msg(5, "Got "+contents.getName()+": "+contents.getClass().getName());
+ Logger.msg(7, "Looking for existing "+contents.getName());
+ CollectionView<? extends CollectionMember> thisCollView = findTabForCollName(contents.getName());
+ if (thisCollView == null){
+ if (contents instanceof Aggregation) {
+ AggregationView thisAggView = new AggregationView();
+ thisAggView.setCollection((Aggregation)contents);
+ thisCollView = thisAggView;
+ }
+ else if (contents instanceof Dependency) {
+ DependencyView thisDepView = new DependencyView();
+ thisDepView.setCollection((Dependency)contents);
+ thisCollView = thisDepView;
+ }
+ else {
+ Logger.error("Collection type "+contents.getClass().getName()+" not known");
+ return;
+ }
+ Logger.msg(3, "Adding new "+thisCollView.getClass().getName());
+ thisCollView.setItem((ItemProxy)sourceEntity.getEntity());
+ collTabs.add(contents.getName(), thisCollView);
+ }
+ }
+
+ @Override
+ public void remove(String id)
+ {
+
+ }
+
+ private CollectionView<? extends CollectionMember> findTabForCollName(String collName) {
+ CollectionView<? extends CollectionMember> thisCollView = null;
+ for (int i = 0; i < collTabs.getTabCount(); i++) {
+ String tabName = collTabs.getTitleAt(i);
+ if (tabName.equals(collName)) {
+ thisCollView = (CollectionView<? extends CollectionMember>)collTabs.getComponentAt(i);
+ }
+ }
+ return thisCollView;
+ }
+
+ protected void createLayout()
+ {
+ initPanel();
+ // Add the collection tab pane
+ getGridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 1;
+ c.fill = GridBagConstraints.BOTH;
+ c.weighty = 2.0;
+ collTabs = new JTabbedPane();
+ gridbag.setConstraints(collTabs, c);
+ add(collTabs);
+ }
+
+ @Override
+ public void run()
+ {
+ Thread.currentThread().setName("Collection Loader");
+ sourceEntity.getEntity().subscribe(new MemberSubscription<Collection<?>>(this, ClusterStorage.COLLECTION, true));
+ }
+
+ @Override
+ public void reload()
+ {
+ Gateway.getStorage().clearCache(sourceEntity.getSysKey(), ClusterStorage.COLLECTION);
+ collTabs.removeAll();
+ initForEntity(sourceEntity);
+ }
+
+ @Override
+ public void control(String control, String msg) {
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/DomainPathAdmin.java b/src/main/java/com/c2kernel/gui/tabs/DomainPathAdmin.java new file mode 100644 index 0000000..408a32c --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/DomainPathAdmin.java @@ -0,0 +1,174 @@ +package com.c2kernel.gui.tabs;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import javax.swing.Box;
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.3 $
+ * $Date: 2004/10/21 08:02:21 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class DomainPathAdmin extends Box implements ActionListener {
+
+ ItemProxy entity;
+ JTable table;
+ DomainPathTableModel model;
+ JButton addButton;
+ JButton removeButton;
+
+ public DomainPathAdmin() {
+ super(BoxLayout.Y_AXIS);
+
+ model = new DomainPathTableModel(this);
+ table = new JTable(model);
+ add(new JScrollPane(table));
+
+ add(Box.createVerticalGlue());
+ Box buttonBox = Box.createHorizontalBox();
+ addButton = new JButton("Add");
+ buttonBox.add(addButton);
+ buttonBox.add(Box.createHorizontalGlue());
+ removeButton = new JButton("Remove");
+ buttonBox.add(removeButton);
+ buttonBox.add(Box.createHorizontalGlue());
+ add(buttonBox);
+
+ addButton.setActionCommand("add");
+ addButton.addActionListener(this);
+ removeButton.setActionCommand("remove");
+ removeButton.addActionListener(this);
+ }
+
+ public void setEntity(ItemProxy entity) {
+ this.entity = entity;
+ model.loadPaths();
+ }
+
+ @Override
+public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("add")) {
+ String newPath = JOptionPane.showInputDialog(this, "Enter new path,", "Add Domain Path", JOptionPane.PLAIN_MESSAGE);
+ addDomainPath(new DomainPath(newPath));
+ model.loadPaths();
+ }
+ else if (e.getActionCommand().equals("remove")) {
+ if (table.getSelectedRow() > -1) {
+ DomainPath oldPath = model.getPath(table.getSelectedRow());
+ removeDomainPath(oldPath);
+ model.loadPaths();
+ }
+ }
+ }
+
+ public boolean removeDomainPath(DomainPath oldPath) {
+ return alterDomainPath(oldPath, "Remove");
+ }
+
+ public boolean addDomainPath(DomainPath newPath) {
+ return alterDomainPath(newPath, "Add");
+ }
+
+ public boolean alterDomainPath(DomainPath path, String action) {
+
+ if (JOptionPane.showConfirmDialog(this,
+ action+" "+path+"?",
+ action+" Domain Path",
+ JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION)
+ return false;
+
+ String[] params = new String[1];
+ params[0] = path.toString();
+ try {
+ MainFrame.userAgent.execute(entity, action+"DomainPath", params);
+ } catch (Exception e) {
+ Logger.exceptionDialog(e);
+ return false;
+ }
+ return true;
+ }
+
+ private class DomainPathTableModel extends AbstractTableModel {
+ ArrayList<DomainPath> domPaths;
+ DomainPathAdmin parent;
+ public DomainPathTableModel(DomainPathAdmin parent) {
+ this.parent = parent;
+ domPaths = new ArrayList<DomainPath>();
+ }
+
+ public void loadPaths() {
+ domPaths.clear();
+ for (Enumeration<?> currentPaths = Gateway.getLDAPLookup().search(new DomainPath(), entity.getName()); currentPaths.hasMoreElements();) {
+ DomainPath thisPath = (DomainPath)currentPaths.nextElement();
+ if (thisPath.getSysKey() == entity.getSystemKey())
+ domPaths.add(thisPath);
+ }
+ fireTableDataChanged();
+ }
+
+ public DomainPath getPath(int rowIndex) {
+ return domPaths.get(rowIndex);
+ }
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ DomainPath oldPath = domPaths.get(rowIndex);
+ DomainPath newPath = new DomainPath((String)aValue);
+ boolean success = parent.addDomainPath(newPath);
+ if (success)
+ success = parent.removeDomainPath(oldPath);
+ if (success) {
+ oldPath.setPath(newPath);
+ fireTableDataChanged();
+ }
+ }
+
+ @Override
+ public Class<?> getColumnClass(int columnIndex) {
+ return String.class;
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 1;
+ }
+
+ @Override
+ public String getColumnName(int column) {
+ return "Path";
+ }
+
+ @Override
+ public int getRowCount() {
+ return domPaths.size();
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ return domPaths.get(rowIndex).toString();
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/EntityTabPane.java b/src/main/java/com/c2kernel/gui/tabs/EntityTabPane.java new file mode 100644 index 0000000..0a8a0cd --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/EntityTabPane.java @@ -0,0 +1,197 @@ +/*
+ * TabbedPane.java
+ *
+ * Created on March 22, 2001, 11:39 AM
+ */
+package com.c2kernel.gui.tabs;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JToggleButton;
+import javax.swing.SwingConstants;
+
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.gui.EntityDetails;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.data.NodeEntity;
+import com.c2kernel.gui.tabs.outcome.OutcomeHandler;
+import com.c2kernel.gui.tabs.outcome.form.OutcomePanel;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+/**
+ * Generic item details tabbed pane.
+ *
+ * @version $Revision: 1.31 $ $Date: 2005/06/08 16:47:44 $
+ * @author $Author: abranson $
+ */
+public class EntityTabPane extends JPanel implements Runnable {
+
+ protected NodeEntity sourceEntity;
+ protected String titleText = null;
+ protected ImageIcon titleIcon = null;
+ private final String tabName;
+ protected GridBagLayout gridbag = new GridBagLayout();
+ protected GridBagConstraints c = null;
+ public static Font titleFont = null;
+ public static Color headingColor = new Color(0, 0, 185);
+ protected EntityDetails parent;
+ protected static ImageIcon mReloadIcon = null;
+ protected Box titleBox;
+ static {
+ try {
+ mReloadIcon = Resource.findImage("reload.gif");
+ } catch (Exception e) {
+ Logger.warning("Couldn't load images: " + e);
+ }
+ }
+
+ public void focusLost(FocusEvent e)
+ {
+ }
+
+ public EntityTabPane(String tabName, String titleText) {
+ this.tabName = Language.translate(tabName);
+ this.titleText =
+ titleText == null ? null : Language.translate(titleText);
+ if (titleFont == null)
+ titleFont =
+ new Font("SansSerif", Font.BOLD, this.getFont().getSize() + 5);
+ Logger.msg(2, "ItemTabPane.<init> - viewing " + tabName);
+ setLayout(gridbag);
+ }
+ public void setParent(EntityDetails parent) {
+ this.parent = parent;
+ }
+ public String getTabName() {
+ return tabName;
+ }
+ protected GridBagConstraints getGridBagConstraints() {
+ if (c == null)
+ c = new GridBagConstraints();
+ return c;
+ }
+ protected void initPanel() {
+ getGridBagConstraints().gridx = 0;
+ getGridBagConstraints().gridy = 0;
+ getGridBagConstraints().anchor = GridBagConstraints.NORTHWEST;
+ getGridBagConstraints().fill = GridBagConstraints.HORIZONTAL;
+ getGridBagConstraints().ipadx = 5;
+ getGridBagConstraints().weightx = 1.0;
+ getGridBagConstraints().ipady = 5;
+ // Help panel
+ if (titleText == null)
+ titleText = tabName;
+ if (titleIcon == null)
+ titleIcon = Resource.findImage("info.png");
+ JLabel title = new JLabel(titleText, titleIcon, SwingConstants.LEFT);
+ title.setFont(titleFont);
+ title.setForeground(headingColor);
+ JButton refreshButton = new JButton(mReloadIcon);
+ refreshButton.setToolTipText(Language.translate("Refresh"));
+ refreshButton.setMargin(new Insets(0, 0, 0, 0));
+ refreshButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ setCursor(new Cursor(Cursor.WAIT_CURSOR));
+ reload();
+ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ }
+ });
+ String defaultStartTab = MainFrame.getPref("DefaultStartTab", "Properties");
+ JToggleButton defaultStart =
+ new JToggleButton(Resource.findImage("graph/start.png"));
+ defaultStart.setMargin(new Insets(0, 0, 0, 0));
+ defaultStart.setToolTipText(
+ Language.translate("Select this tab to be the default one opened when you double click an item"));
+ defaultStart.setSelected(tabName.equals(defaultStartTab));
+ defaultStart.setActionCommand(tabName);
+ defaultStart.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (((JToggleButton)e.getSource()).isSelected())
+ MainFrame.setPref("DefaultStartTab", e.getActionCommand());
+ }
+ });
+ titleBox = Box.createHorizontalBox();
+ titleBox.add(title);
+ titleBox.add(Box.createHorizontalGlue());
+ titleBox.add(defaultStart);
+ titleBox.add(refreshButton);
+ gridbag.setConstraints(titleBox, c);
+ this.add(titleBox);
+ }
+ public void initForEntity(NodeEntity sourceEntity) {
+ this.sourceEntity = sourceEntity;
+ Thread loader = new Thread(this);
+ loader.start();
+ }
+ @Override
+ public void run() {
+ Thread.currentThread().setName("Default Entity Pane Builder");
+ getGridBagConstraints();
+ c.gridx = 0;
+ c.gridy = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.ipadx = 5;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.ipady = 5;
+ JLabel error = new JLabel("In Development");
+ gridbag.setConstraints(error, c);
+ this.add(error);
+ }
+ public void reload() {
+ }
+ public void runCommand(String command) {
+ }
+
+ public void destroy() {
+ if (sourceEntity != null && this instanceof EntityProxyObserver<?>) {
+ sourceEntity.getEntity().unsubscribe((EntityProxyObserver<?>)this);
+ }
+ parent = null;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ Logger.msg(7, "Reaping "+getClass().getName());
+ }
+
+ static public OutcomeHandler getOutcomeHandler(String schema, int version) {
+ String ohClassName = Gateway.getProperty("OutcomeHandler."+schema+"."+version);
+ try {
+ if (ohClassName != null && ohClassName.length() > 0) {
+ Class<?> ohClass = Class.forName(ohClassName);
+ return (OutcomeHandler) ohClass.newInstance();
+ }
+ } catch (Exception ex) {
+ Logger.error("Error creating handler "+ohClassName+". using default outcome editor");
+ }
+ ohClassName = Gateway.getProperty("OutcomeHandler.*");
+ try {
+ if (ohClassName != null && ohClassName.length() > 0) {
+ Class<?> ohClass = Class.forName(ohClassName);
+ return (OutcomeHandler) ohClass.newInstance();
+ }
+ } catch (Exception ex) {
+ Logger.error("Error creating handler "+ohClassName+". using default outcome editor");
+ Logger.error(ex);
+ }
+ return new OutcomePanel();
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/ExecutionPane.java b/src/main/java/com/c2kernel/gui/tabs/ExecutionPane.java new file mode 100644 index 0000000..a853695 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/ExecutionPane.java @@ -0,0 +1,208 @@ +package com.c2kernel.gui.tabs;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.swing.Box;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.entity.proxy.MemberSubscription;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.execution.ActivityItem;
+import com.c2kernel.gui.tabs.execution.ActivityViewer;
+import com.c2kernel.lifecycle.instance.Workflow;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+public class ExecutionPane extends EntityTabPane implements EntityProxyObserver<Workflow> {
+
+ ArrayList<Job> jobList = null;
+ Object jobLock = new Object();
+ ActivityItem emptyAct = new ActivityItem();
+ JLabel noActs = new JLabel(Language.translate("There are currently no activities that you can execute in this item."));
+ JPanel view = new JPanel(new GridLayout(1, 1));
+ ActivityViewer currentActView;
+ JComboBox activitySelector = new JComboBox();
+ Box activityBox = Box.createHorizontalBox();
+ String selAct = null;
+ ArrayList<ActivityItem> activities;
+ String autoRun = null;
+ boolean init = false;
+ boolean formIsActive = false;
+ public ExecutionPane() {
+ super("Execution", "Activity Execution");
+ super.initPanel();
+ // add view panel
+ c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 1; c.weightx = 1.0; c.weighty = 2.0;
+ c.insets = new Insets(5, 5, 5, 5);
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.BOTH;
+ gridbag.setConstraints(view, c);
+
+ add(view);
+ // create activity selection box
+ activityBox.add(new JLabel(Language.translate("Select Activity") + ": "));
+ activityBox.add(Box.createHorizontalStrut(5));
+ activitySelector.setEditable(false);
+ activityBox.add(activitySelector);
+ activitySelector.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent selection) {
+ if (selection.getStateChange() == ItemEvent.SELECTED) {
+ selectActivity(selection.getItem());
+ }
+ }
+ });
+ }
+ @Override
+ public void run() {
+ Thread.currentThread().setName("Execution Pane Builder");
+ sourceEntity.getEntity().subscribe(new MemberSubscription<Workflow>(this, ClusterStorage.LIFECYCLE, false));
+ loadJobList();
+ init = true;
+ if (autoRun != null) {
+ runCommand(autoRun);
+ autoRun = null;
+ }
+ }
+ private void loadJobList() {
+ synchronized (jobLock) {
+ activitySelector.removeAllItems();
+ view.removeAll();
+ activities = new ArrayList<ActivityItem>();
+ try {
+ jobList = ((ItemProxy)sourceEntity.getEntity()).getJobList(MainFrame.userAgent);
+ activitySelector.addItem(emptyAct);
+ for (Job thisJob : jobList) {
+ Logger.msg(7, "ExecutionPane - loadJobList " + thisJob.isOutcomeUsed() + "|" + thisJob.getSchemaType() + "|" + thisJob.getSchemaVersion() + "|");
+ ActivityItem newAct = new ActivityItem(thisJob);
+ if (activities.contains(newAct)) {
+ int actIndex = activities.indexOf(newAct);
+ activities.get(actIndex).addJob(thisJob);
+ } else {
+ Logger.msg(2, "ExecutionPane - Adding activity " + thisJob.getStepPath());
+ addActivity(newAct);
+ }
+ }
+ } catch (Exception e) {
+ Logger.debug("Error fetching joblist");
+ Logger.error(e);
+ }
+
+ switch (activities.size()) {
+ case 0 :
+ view.add(noActs);
+ break;
+ case 1 :
+ currentActView = new ActivityViewer(activities.get(0), (ItemProxy)sourceEntity.getEntity(), this);
+ c.fill = GridBagConstraints.BOTH;
+ gridbag.setConstraints(view, c);
+ view.add(currentActView);
+ currentActView.init();
+ break;
+ default :
+ c.fill = GridBagConstraints.HORIZONTAL;
+ gridbag.setConstraints(view, c);
+ view.add(activityBox);
+ }
+ }
+ revalidate();
+ updateUI();
+ }
+ @Override
+ public void reload() {
+ loadJobList();
+ }
+ private void addActivity(ActivityItem newAct) {
+ if (activities.contains(newAct)) {
+ Logger.msg(6, "ExecutionPane.addActivity(): Already in " + newAct.getStepPath());
+ int actIndex = activities.indexOf(newAct);
+ activitySelector.removeItemAt(actIndex);
+ activitySelector.insertItemAt(newAct, actIndex);
+ activities.set(actIndex, newAct);
+ } else {
+ Logger.msg(6, "ExecutionPane.addActivity(): New " + newAct.getStepPath());
+ activities.add(newAct);
+ activitySelector.addItem(newAct);
+ }
+ }
+ private void selectActivity(Object selObj) {
+ if (selObj.equals(emptyAct))
+ return;
+ view.removeAll();
+ c.fill = GridBagConstraints.BOTH;
+ gridbag.setConstraints(view, c);
+ currentActView = new ActivityViewer((ActivityItem)selObj, (ItemProxy)sourceEntity.getEntity(), this);
+ view.add(currentActView);
+ revalidate();
+ updateUI();
+ currentActView.init();
+ }
+ @Override
+ public void runCommand(String command) {
+ if (init) {
+ for (ActivityItem act : activities) {
+ if (act.name.equals(command)) {
+ selectActivity(act);
+ }
+ }
+ } else
+ autoRun = command;
+ }
+ /**
+ * when the workflow changes, reload this pane.
+ */
+ @Override
+ public void add(Workflow contents) {
+ if (!formIsActive)
+ reload();
+ else { // look to see if this form is now invalid
+ // get the new joblist
+ try {
+ jobList = ((ItemProxy)sourceEntity.getEntity()).getJobList(MainFrame.userAgent);
+ } catch (Exception ex) {
+ return;
+ }
+ // compare to currently editing jobs
+ ArrayList<?> currentActJobs = currentActView.getActivity().getJobs();
+ boolean allValid = true;
+ for (Iterator<?> iter = currentActJobs.iterator(); iter.hasNext() && allValid;) {
+ Job thisJob = (Job)iter.next();
+ boolean stillValid = false;
+ for (Job newJob : jobList) {
+ if (thisJob.equals(newJob)) {
+ stillValid = true;
+ break;
+ }
+ }
+ allValid &= stillValid;
+ }
+ if (!allValid) { // not all transitions are now valid
+ reload(); // refresh the execution pane
+ }
+ }
+ }
+ /**
+ * Not pertinent for this one
+ */
+ @Override
+ public void remove(String id) {
+ }
+ @Override
+ public void control(String control, String msg) {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/HistoryPane.java b/src/main/java/com/c2kernel/gui/tabs/HistoryPane.java new file mode 100644 index 0000000..5b3d536 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/HistoryPane.java @@ -0,0 +1,270 @@ +/*
+ * StatusPane.java
+ *
+ * Created on March 20, 2001, 3:30 PM
+ */
+
+package com.c2kernel.gui.tabs;
+
+/**
+ * @author abranson
+ * @version
+ */
+import java.awt.GridBagConstraints;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.MemberSubscription;
+import com.c2kernel.events.Event;
+import com.c2kernel.events.History;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Pane to display all work orders that this agent can execute, and activate
+ * them on request from the user. Subscribes to NodeItem for WorkOrder objects.
+ * @version $Revision: 1.22 $ $Date: 2005/04/26 06:48:13 $
+ * @author $Author: abranson $
+ */
+public class HistoryPane extends EntityTabPane implements ActionListener, EntityProxyObserver<Event> {
+
+ History history;
+ HistoryTableModel model;
+ JTable eventTable;
+ JButton startButton = new JButton("<<");
+ JButton prevButton = new JButton("<");
+ JButton nextButton = new JButton(">");
+ JButton endButton = new JButton(">>");
+ public static final int SIZE = 30;
+ int currentSize = SIZE;
+
+ public HistoryPane() {
+ super("History", "Event History");
+ initPanel();
+
+ // add buttons
+ Box navBox = Box.createHorizontalBox();
+ navBox.add(startButton); navBox.add(prevButton);
+ navBox.add(nextButton); navBox.add(endButton);
+
+ // setup buttons
+ //startButton.setEnabled(false); nextButton.setEnabled(false);
+ //prevButton.setEnabled(false); endButton.setEnabled(false);
+ startButton.setActionCommand("start");
+ startButton.addActionListener(this);
+ prevButton.setActionCommand("prev");
+ prevButton.addActionListener(this);
+ nextButton.setActionCommand("next");
+ nextButton.addActionListener(this);
+ endButton.setActionCommand("end");
+ endButton.addActionListener(this);
+ getGridBagConstraints();
+ c.gridx = 0; c.gridy = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill=GridBagConstraints.NONE;
+ c.weightx=0; c.weighty=0;
+ gridbag.setConstraints(navBox, c);
+ add(navBox);
+
+
+ // Create table
+ eventTable = new JTable();
+ JScrollPane eventScroll= new JScrollPane(eventTable);
+ c.weightx = 1.0; c.weighty = 1.0;
+ c.fill = GridBagConstraints.BOTH; c.gridy++;
+ gridbag.setConstraints(eventScroll, c);
+ add(eventScroll);
+
+ }
+
+ @Override
+ public void reload() {
+ history.clear();
+ jumpToEnd();
+ }
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName("History Pane Builder");
+ try {
+ history = (History)sourceEntity.getEntity().getObject(ClusterStorage.HISTORY);
+ sourceEntity.getEntity().subscribe(new MemberSubscription<Event>(this, ClusterStorage.HISTORY, false));
+ } catch (ObjectNotFoundException e) {
+ Logger.error(e);
+ }
+ model = new HistoryTableModel();
+ eventTable.setModel(model);
+ jumpToEnd();
+ }
+
+ public void jumpToEnd() {
+ int lastEvent = history.getLastId();
+ int firstEvent = 0; currentSize = SIZE;
+ if (lastEvent > currentSize) firstEvent = lastEvent - currentSize + 1;
+ if (lastEvent < currentSize) currentSize = lastEvent + 1;
+ Logger.msg(5, "HistoryPane.run() - init table start "+firstEvent+" for "+currentSize);
+ model.setView(firstEvent, currentSize);
+ }
+
+ @Override
+ public void add(Event contents) {
+ jumpToEnd();
+ }
+
+ @Override
+ public void remove(String id) {
+ // don't have to deal with this normally
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("end")) {
+ jumpToEnd();
+ return;
+ }
+
+ int lastEvent = history.getLastId();
+ int startEvent = model.getStartId();
+ if (e.getActionCommand().equals("start")) {
+ currentSize = SIZE;
+ startEvent = 0;
+ }
+
+ else if (e.getActionCommand().equals("prev")) {
+ currentSize = SIZE;
+ startEvent-=currentSize;
+ if (startEvent<0) startEvent = 0;
+ }
+ else if (e.getActionCommand().equals("next")) {
+ currentSize = SIZE;
+ startEvent+=currentSize;
+ if (startEvent > lastEvent)
+ startEvent = lastEvent - currentSize +1;
+ }
+ else { // unknown action
+ return;
+ }
+
+ model.setView(startEvent, currentSize);
+ }
+
+ private class HistoryTableModel extends AbstractTableModel {
+ Event[] event;
+ Integer[] ids;
+ int loaded = 0;
+ int startId = 0;
+
+ public HistoryTableModel() {
+ event = new Event[0];
+ ids = new Integer[0];
+ }
+
+ public int getStartId() {
+ return startId;
+ }
+
+ public void setView(int startId, int size) {
+ event = new Event[size];
+ ids = new Integer[size];
+ this.startId = startId;
+ for (int i=0; i<size; i++) {
+ event[i] = history.getEvent(startId+i);
+ ids[i] = new Integer(startId+i);
+ loaded = i+1;
+ }
+ fireTableStructureChanged();
+ }
+ /**
+ * @see javax.swing.table.TableModel#getColumnClass(int)
+ */
+ @Override
+ public Class<?> getColumnClass(int columnIndex) {
+ switch(columnIndex) {
+ case 0:
+ return Integer.class;
+ default:
+ return String.class;
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getColumnCount()
+ */
+ @Override
+ public int getColumnCount() {
+ return 6;
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getColumnName(int)
+ */
+ @Override
+ public String getColumnName(int columnIndex) {
+ switch(columnIndex) {
+ case 0: return Language.translate("ID");
+ case 1: return Language.translate("Activity");
+ case 2: return Language.translate("Transition");
+ case 3: return Language.translate("Date");
+ case 4: return Language.translate("Agent Name");
+ case 5: return Language.translate("Agent Role");
+ default: return "";
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getRowCount()
+ */
+ @Override
+ public int getRowCount() {
+ return loaded;
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getValueAt(int, int)
+ */
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ if (event.length <= rowIndex || event[rowIndex] == null)
+ return "";
+ try {
+ switch (columnIndex) {
+ case 0: return ids[rowIndex];
+ case 1: return event[rowIndex].getStepName();
+ case 2: return Transitions.getTransitionName(event[rowIndex].getTransition());
+ case 3: return event[rowIndex].getTimeString();
+ case 4: return event[rowIndex].getAgentName();
+ case 5: return event[rowIndex].getAgentRole();
+ default: return "";
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#isCellEditable(int, int)
+ */
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return false;
+ }
+
+ }
+
+ @Override
+ public void control(String control, String msg) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/JTabbedPaneWithCloseIcons.java b/src/main/java/com/c2kernel/gui/tabs/JTabbedPaneWithCloseIcons.java new file mode 100644 index 0000000..8f047ca --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/JTabbedPaneWithCloseIcons.java @@ -0,0 +1,96 @@ +package com.c2kernel.gui.tabs;
+import java.awt.Component;
+import java.awt.Rectangle;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+
+import javax.swing.Icon;
+import javax.swing.JTabbedPane;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import com.c2kernel.gui.EntityDetails;
+
+/**
+ * @author Developpement
+ *
+ * Allows a close icone in JTabbePane
+ */
+public class JTabbedPaneWithCloseIcons extends JTabbedPane implements MouseListener, ChangeListener
+{
+ /**
+ *
+ */
+ public JTabbedPaneWithCloseIcons()
+ {
+ super();
+ addMouseListener(this);
+ addChangeListener(this);
+ }
+ /**
+ * @see javax.swing.JTabbedPane#addTab(String, Icon, Component, String)
+ */
+ @Override
+ public void addTab(String title, Icon arg2, Component component, String arg3)
+ {
+ super.addTab(title, new CloseTabIcon(arg2), component, arg3);
+ }
+ /**
+ * @see java.awt.event.MouseListener#mouseClicked(MouseEvent)
+ */
+ @Override
+ public void mouseClicked(MouseEvent e)
+ {
+ int tabNumber = getUI().tabForCoordinate(this, e.getX(), e.getY());
+ Component cp = null;
+ if (tabNumber < 0)
+ return;
+ Rectangle rect = ((CloseTabIcon) getIconAt(tabNumber)).getBounds();
+ if (rect.contains(e.getX(), e.getY())||(e.getModifiers()& InputEvent.CTRL_MASK) != 0)
+ { //the tab is being closed
+ cp = this.getComponent(tabNumber);
+ //if (getComponentCount() != 1)
+ if (cp instanceof EntityDetails)
+ {
+ ((EntityDetails) cp).closeTab();
+ remove(cp);
+ }
+ }
+ stateChanged(new ChangeEvent(this));
+ }
+ /**
+ * @see java.awt.event.MouseListener#mouseEntered(MouseEvent)
+ */
+ @Override
+ public void mouseEntered(MouseEvent e)
+ {
+ }
+ /**
+ * @see java.awt.event.MouseListener#mouseExited(MouseEvent)
+ */
+ @Override
+ public void mouseExited(MouseEvent e)
+ {
+ }
+ /**
+ * @see java.awt.event.MouseListener#mousePressed(MouseEvent)
+ */
+ @Override
+ public void mousePressed(MouseEvent e)
+ {
+ }
+ /**
+ * @see java.awt.event.MouseListener#mouseReleased(MouseEvent)
+ */
+ @Override
+ public void mouseReleased(MouseEvent e)
+ {
+ }
+ @Override
+ public void stateChanged(ChangeEvent e)
+ {
+ if (getSelectedComponent()!= null)
+ ((EntityDetails) getSelectedComponent()).refresh();
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/JobListPane.java b/src/main/java/com/c2kernel/gui/tabs/JobListPane.java new file mode 100644 index 0000000..619a589 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/JobListPane.java @@ -0,0 +1,312 @@ +/*
+ * StatusPane.java
+ *
+ * Created on March 20, 2001, 3:30 PM
+ */
+
+package com.c2kernel.gui.tabs;
+
+/**
+ * @author abranson
+ * @version
+ */
+import java.awt.GridBagConstraints;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.Iterator;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JOptionPane;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.agent.JobList;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.MemberSubscription;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Pane to display all work orders that this agent can execute, and activate
+ * them on request from the user. Subscribes to NodeItem for WorkOrder objects.
+ * @version $Revision: 1.4 $ $Date: 2004/10/21 08:02:21 $
+ * @author $Author: abranson $
+ */
+public class JobListPane extends EntityTabPane implements ActionListener, EntityProxyObserver<Job> {
+
+ JobList joblist;
+ JoblistTableModel model;
+ JTable eventTable;
+ JButton startButton = new JButton("<<");
+ JButton prevButton = new JButton("<");
+ JButton nextButton = new JButton(">");
+ JButton endButton = new JButton(">>");
+ public static final int SIZE = 30;
+ int currentSize = SIZE;
+
+ public JobListPane() {
+ super("Job List", "Agent Job List");
+ initPanel();
+
+ // add buttons
+ Box navBox = Box.createHorizontalBox();
+ navBox.add(startButton); navBox.add(prevButton);
+ navBox.add(nextButton); navBox.add(endButton);
+
+ // setup buttons
+ //startButton.setEnabled(false); nextButton.setEnabled(false);
+ //prevButton.setEnabled(false); endButton.setEnabled(false);
+ startButton.setActionCommand("start");
+ startButton.addActionListener(this);
+ prevButton.setActionCommand("prev");
+ prevButton.addActionListener(this);
+ nextButton.setActionCommand("next");
+ nextButton.addActionListener(this);
+ endButton.setActionCommand("end");
+ endButton.addActionListener(this);
+ getGridBagConstraints();
+ c.gridx = 0; c.gridy = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill=GridBagConstraints.NONE;
+ c.weightx=0; c.weighty=0;
+ gridbag.setConstraints(navBox, c);
+ add(navBox);
+
+
+ // Create table
+ eventTable = new JTable();
+ JScrollPane eventScroll= new JScrollPane(eventTable);
+ c.weightx = 1.0; c.weighty = 1.0;
+ c.fill = GridBagConstraints.BOTH; c.gridy++;
+ gridbag.setConstraints(eventScroll, c);
+ add(eventScroll);
+
+ // detect double clicked jobs
+ eventTable.addMouseListener(new JobListMouseListener());
+ }
+
+ @Override
+ public void reload() {
+ joblist.clear();
+ jumpToEnd();
+ }
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName("Joblist Pane Builder");
+ try {
+ joblist = (JobList)sourceEntity.getEntity().getObject(ClusterStorage.JOB);
+ sourceEntity.getEntity().subscribe(new MemberSubscription<Job>(this, ClusterStorage.JOB, false));
+ } catch (ObjectNotFoundException e) {
+ Logger.error(e);
+ }
+ model = new JoblistTableModel(joblist);
+ eventTable.setModel(model);
+ jumpToEnd();
+ }
+
+
+ public void jumpToEnd() {
+ int lastEvent = joblist.getLastId();
+ int firstEvent = 0; currentSize = SIZE;
+ if (lastEvent > currentSize) firstEvent = lastEvent - currentSize + 1;
+ if (lastEvent < currentSize) currentSize = lastEvent + 1;
+ Logger.msg(5, "JobListPane.run() - init table start "+firstEvent+" for "+currentSize);
+ model.setView(firstEvent, currentSize);
+ }
+
+ @Override
+ public void add(Job contents) {
+ reload();
+ }
+
+ @Override
+ public void remove(String id) {
+ reload();
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("end")) {
+ jumpToEnd();
+ return;
+ }
+
+ int lastEvent = joblist.getLastId();
+ int startEvent = model.getStartId();
+ if (e.getActionCommand().equals("start")) {
+ currentSize = SIZE;
+ startEvent = 0;
+ }
+
+ else if (e.getActionCommand().equals("prev")) {
+ currentSize = SIZE;
+ startEvent-=currentSize;
+ if (startEvent<0) startEvent = 0;
+ }
+ else if (e.getActionCommand().equals("next")) {
+ currentSize = SIZE;
+ startEvent+=currentSize;
+ if (startEvent > lastEvent)
+ startEvent = lastEvent - currentSize +1;
+ }
+ else { // unknown action
+ return;
+ }
+
+ model.setView(startEvent, currentSize);
+ }
+
+ private class JoblistTableModel extends AbstractTableModel {
+ Job[] job;
+ Integer[] ids;
+ String[] itemNames;
+ int loaded = 0;
+ int startId = 0;
+
+ public JoblistTableModel(JobList joblist) {
+ job = new Job[0];
+ ids = new Integer[0];
+ }
+
+ public int getStartId() {
+ return startId;
+ }
+
+ public void setView(int startId, int size) {
+ job = new Job[size];
+ ids = new Integer[size];
+ itemNames = new String[size];
+ this.startId = startId;
+ int count = 0;
+ for (Iterator<?> i = joblist.keySet().iterator(); i.hasNext();) {
+ Integer thisJobId = new Integer((String)i.next());
+ if (count >= startId) {
+ int idx = count-startId;
+ ids[idx] = thisJobId;
+ job[idx] = joblist.getJob(thisJobId.intValue());
+ itemNames[idx] = "Item Not Found";
+ try {
+ itemNames[idx] = ((Property)Gateway.getStorage().get(job[count-startId].getItemSysKey(), ClusterStorage.PROPERTY+"/Name", null)).getValue();
+ } catch (Exception ex) {
+ Logger.error(ex);
+ }
+
+ }
+ count++;
+ loaded = count-startId;
+ if (count > (startId + size)) break;
+ }
+ fireTableStructureChanged();
+ }
+ /**
+ * @see javax.swing.table.TableModel#getColumnClass(int)
+ */
+ @Override
+ public Class<?> getColumnClass(int columnIndex) {
+ switch(columnIndex) {
+ case 0:
+ return Integer.class;
+ default:
+ return String.class;
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getColumnCount()
+ */
+ @Override
+ public int getColumnCount() {
+ return 4;
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getColumnName(int)
+ */
+ @Override
+ public String getColumnName(int columnIndex) {
+ switch(columnIndex) {
+ case 0: return Language.translate("ID");
+ case 1: return Language.translate("Subject");
+ case 2: return Language.translate("Activity");
+ case 3: return Language.translate("Transition");
+ default: return "";
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getRowCount()
+ */
+ @Override
+ public int getRowCount() {
+ return loaded;
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#getValueAt(int, int)
+ */
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ if (job.length <= rowIndex || job[rowIndex] == null)
+ return "";
+ try {
+ switch (columnIndex) {
+ case 0: return ids[rowIndex];
+ case 1: return itemNames[rowIndex];
+ case 2: return job[rowIndex].getStepName();
+ case 3: return Transitions.getTransitionName(job[rowIndex].getPossibleTransition());
+ default: return "";
+ }
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ /**
+ * @see javax.swing.table.TableModel#isCellEditable(int, int)
+ */
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return false;
+ }
+
+ public Job getJobAtRow(int rowIndex) {
+ return job[rowIndex];
+ }
+
+ }
+
+ private class JobListMouseListener extends MouseAdapter {
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ super.mouseClicked(e);
+ if (e.getClickCount() == 2) {
+ Job selectedJob = model.getJobAtRow(eventTable.getSelectedRow());
+ try {
+ MainFrame.itemFinder.pushNewKey(selectedJob.getItemProxy().getName());
+ } catch (Exception ex) {
+ Logger.error(ex);
+ JOptionPane.showMessageDialog(null, "No Item Found", "Job references an unknown item", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void control(String control, String msg) {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/PropertiesPane.java b/src/main/java/com/c2kernel/gui/tabs/PropertiesPane.java new file mode 100644 index 0000000..2411296 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/PropertiesPane.java @@ -0,0 +1,200 @@ +/*
+ * StatusPane.java
+ *
+ * Created on March 20, 2001, 3:30 PM
+ */
+
+package com.c2kernel.gui.tabs;
+
+/**
+ * @author abranson
+ * @version
+ */
+import java.awt.GridBagConstraints;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.HashMap;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.entity.proxy.MemberSubscription;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.data.NodeAgent;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.property.Property;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+/**
+ * Pane to display all work orders that this agent can execute, and activate
+ * them on request from the user. Subscribes to NodeItem for Property objects.
+ * @version $Revision: 1.44 $ $Date: 2005/08/31 07:21:20 $
+ * @author $Author: abranson $
+ */
+public class PropertiesPane extends EntityTabPane implements EntityProxyObserver<Property>, ActionListener {
+
+ Box propertyBox;
+ boolean subbed = false;
+ HashMap<String, JLabel> loadedProps = new HashMap<String, JLabel>();
+ JLabel domTitle;
+ DomainPathAdmin domAdmin;
+
+ public PropertiesPane() {
+ super("Properties", "Properties");
+ initPanel();
+
+ // Create box container for properties
+ getGridBagConstraints();
+ c.gridx = 0; c.gridy = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.NONE;
+ c.weightx = 1.0; c.weighty = 2.0;
+ propertyBox = Box.createVerticalBox();
+ gridbag.setConstraints(propertyBox, c);
+ add(propertyBox);
+ if (MainFrame.isAdmin) { // edit dompath
+ c.gridy++;
+ c.fill = GridBagConstraints.NONE;
+ c.weighty=0.0;
+ domTitle = new JLabel("Domain Paths", titleIcon, SwingConstants.LEFT);
+ domTitle.setFont(titleFont);
+ domTitle.setForeground(headingColor);
+ gridbag.setConstraints(domTitle, c);
+ add(domTitle);
+
+ c.gridy++;
+ c.fill = GridBagConstraints.BOTH;
+ c.weighty=1.0;
+ domAdmin = new DomainPathAdmin();
+ gridbag.setConstraints(domAdmin, c);
+ add(domAdmin);
+
+
+ if ("true".equals(Gateway.getProperty("EnableItemErase"))) {
+ c.gridy++;
+ c.fill = GridBagConstraints.NONE;
+ JButton eraseButton = new JButton(Language.translate("Erase!"));
+ eraseButton.addActionListener(this);
+ eraseButton.setActionCommand("Erase Item");
+ gridbag.setConstraints(eraseButton, c);
+ add(eraseButton);
+ }
+ }
+ }
+
+ @Override
+ public void reload() {
+ Gateway.getStorage().clearCache(sourceEntity.getSysKey(), ClusterStorage.PROPERTY);
+ loadedProps = new HashMap<String, JLabel>();
+ initForEntity(sourceEntity);
+ }
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName("Property Pane Builder");
+ if (sourceEntity instanceof NodeAgent) {
+ remove(domAdmin);
+ remove(domTitle);
+ }
+ else if (domAdmin != null)
+ domAdmin.setEntity((ItemProxy)sourceEntity.getEntity());
+ propertyBox.removeAll();
+ propertyBox.add(Box.createGlue());
+ revalidate();
+ sourceEntity.getEntity().subscribe(new MemberSubscription<Property>(this, ClusterStorage.PROPERTY, true));
+
+ }
+ /**
+ *
+ */
+ @Override
+ public void add(Property newProp) {
+ JLabel propLabel = loadedProps.get(newProp.getName());
+ if (propLabel == null) { // new prop
+ JPanel summaryPanel = new JPanel(new GridLayout(0,2));
+ summaryPanel.add(new JLabel(Language.translate(newProp.getName()) + ":"));
+ Box valueBox = Box.createHorizontalBox();
+ propLabel = new JLabel(newProp.getValue());
+ loadedProps.put(newProp.getName(), propLabel);
+ valueBox.add(propLabel);
+ if (MainFrame.isAdmin) {
+ JButton editButton = new JButton("...");
+ editButton.setMargin(new Insets(0,0,0,0));
+ editButton.setActionCommand(newProp.getName());
+ editButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e){
+ String oldVal = loadedProps.get(e.getActionCommand()).getText();
+ String newVal = (String)JOptionPane.showInputDialog(null, "Enter new value for "+e.getActionCommand(), "Edit Property",
+ JOptionPane.QUESTION_MESSAGE, null, null, oldVal);
+ if (newVal!=null && !(newVal.equals(oldVal))) {
+ try {
+ ((ItemProxy)sourceEntity.getEntity()).setProperty(MainFrame.userAgent, e.getActionCommand(), newVal);
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+ }
+ }
+ });
+ valueBox.add(Box.createVerticalStrut(7));
+ valueBox.add(editButton);
+
+ }
+ summaryPanel.add(valueBox);
+ propertyBox.add(Box.createVerticalStrut(7));
+ propertyBox.add(summaryPanel);
+ }
+ propLabel.setText(newProp.getValue());
+ revalidate();
+ }
+
+ @Override
+ public void remove(String id) {
+ String propName = id.substring(id.lastIndexOf("/")+1);
+ JLabel propbox = loadedProps.get(propName);
+ if (propbox!= null) propbox.setText("DELETED");
+ revalidate();
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String[] params;
+ String predefStep;
+
+ if (JOptionPane.showConfirmDialog(this,
+ "Are you sure?",
+ e.getActionCommand(),
+ JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION)
+ return;
+
+ if (e.getActionCommand().equals("Erase Item")) {
+ params = new String[0];
+ predefStep = "Erase";
+ }
+ else
+ return;
+
+ try {
+ MainFrame.userAgent.execute((ItemProxy)sourceEntity.getEntity(), predefStep, params);
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+ }
+
+ @Override
+ public void control(String control, String msg) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/ViewpointPane.java b/src/main/java/com/c2kernel/gui/tabs/ViewpointPane.java new file mode 100644 index 0000000..52c9cb3 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/ViewpointPane.java @@ -0,0 +1,515 @@ +
+package com.c2kernel.gui.tabs;
+import java.awt.GridBagConstraints;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.C2KLocalObject;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.entity.proxy.MemberSubscription;
+import com.c2kernel.events.Event;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.OutcomeHandler;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.persistency.outcome.Viewpoint;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+
+public class ViewpointPane extends EntityTabPane implements ItemListener, ActionListener, EntityProxyObserver<C2KLocalObject> {
+
+ JComboBox schemas;
+ JComboBox views;
+ JComboBox events;
+ JLabel eventDetails;
+ JButton exportButton;
+ JButton viewButton;
+
+ ArrayList<String> schemaList;
+ ArrayList<Viewpoint> viewpointList;
+ ArrayList<EventItem> eventList;
+ String currentSchema = null;
+ Outcome currentOutcome = null;
+ OutcomeHandler thisOutcome;
+ boolean suspendSelection = false;
+
+ JPanel dataView = new JPanel(new GridLayout(1,1));
+
+ public ViewpointPane() {
+
+ super("Data Viewer", "Outcome Browser");
+ initialize();
+ }
+
+ public void initialize() {
+ initPanel();
+
+ getGridBagConstraints();
+
+ c.gridx = 0; c.gridy = 1;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.ipadx = 5; c.weightx = 1.0;
+ c.ipady = 5;
+
+ // Set up view box
+
+ Box viewBox = Box.createHorizontalBox();
+
+ JLabel label = new JLabel(Language.translate("Outcome Type")+":", SwingConstants.LEFT);
+ viewBox.add(label);
+ viewBox.add(Box.createHorizontalStrut(7));
+
+ schemas = new JComboBox();
+ viewBox.add(schemas);
+ viewBox.add(Box.createHorizontalGlue());
+ schemas.addItemListener(this);
+
+ label = new JLabel(Language.translate("View")+":", SwingConstants.LEFT);
+ viewBox.add(label);
+ viewBox.add(Box.createHorizontalStrut(7));
+
+ views = new JComboBox();
+ viewBox.add(views);
+ viewBox.add(Box.createHorizontalGlue());
+ views.addItemListener(this);
+
+ gridbag.setConstraints(viewBox, c);
+ this.add(viewBox);
+
+ // Set up event details box
+ c.gridy++;
+ Box eventBox = Box.createHorizontalBox();
+
+ label = new JLabel(Language.translate("Event")+":", SwingConstants.LEFT);
+ eventBox.add(label);
+ eventBox.add(Box.createHorizontalStrut(7));
+
+ events = new JComboBox();
+ eventBox.add(events);
+ eventBox.add(Box.createHorizontalStrut(7));
+ events.addItemListener(this);
+
+ eventDetails = new JLabel();
+ eventBox.add(eventDetails);
+ eventBox.add(Box.createHorizontalGlue());
+
+ if (MainFrame.isAdmin) {
+ viewButton = new JButton(Language.translate("Write View"));
+ viewButton.setMargin(new Insets(0, 0, 0, 0));
+ viewButton.setActionCommand("setview");
+ eventBox.add(viewButton);
+ eventBox.add(Box.createHorizontalStrut(14));
+ viewButton.addActionListener(this);
+ }
+
+ exportButton = new JButton(Language.translate("Export"));
+ exportButton.setMargin(new Insets(0, 0, 0, 0));
+ exportButton.setActionCommand("export");
+ exportButton.addActionListener(this);
+ eventBox.add(exportButton);
+
+ gridbag.setConstraints(eventBox, c);
+ this.add(eventBox);
+
+ // data pane
+ c.gridx = 0; c.gridy = 3;
+ c.anchor = GridBagConstraints.NORTHWEST; c.fill = GridBagConstraints.BOTH;
+ c.weighty = 1.0; c.weightx = 1.0;
+ gridbag.setConstraints(dataView, c);
+ this.add(dataView);
+ }
+
+ @Override
+ public void reload() {
+ // reset boxes
+ schemas.removeAllItems();
+ views.removeAllItems();
+ events.removeAllItems();
+ eventDetails.setText("");
+
+ clearView();
+
+ // reload
+ initForEntity(sourceEntity);
+ }
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName("Viewpoint Pane Builder");
+ //Local object subscriptions
+ sourceEntity.getEntity().subscribe(new MemberSubscription<C2KLocalObject>(this, ClusterStorage.VIEWPOINT, false));
+ sourceEntity.getEntity().subscribe(new MemberSubscription<C2KLocalObject>(this, ClusterStorage.OUTCOME, false));
+ clearView();
+ schemas.addItem("--");
+ currentSchema = null;
+ schemaList = new ArrayList<String>();
+ try {
+ String outcomeTypes = sourceEntity.getEntity().queryData(ClusterStorage.VIEWPOINT+"/all");
+ StringTokenizer tok = new StringTokenizer(outcomeTypes, ",");
+ while (tok.hasMoreTokens()) {
+ String thisType = tok.nextToken();
+ schemas.addItem(thisType);
+ schemaList.add(thisType);
+ }
+ } catch (Exception e) {
+ Logger.msg(2, "No viewpoints found");
+ }
+ }
+
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+
+ Object selectedItem = e.getItem();
+ if (e.getStateChange() == ItemEvent.DESELECTED) return;
+ if (suspendSelection) return;
+ if (e.getItem().equals("--")) return;
+
+ if (e.getItemSelectable() == schemas)
+ switchSchema((String)selectedItem);
+ else if (e.getItemSelectable() == views)
+ switchView((Viewpoint)selectedItem);
+ else if (e.getItemSelectable() == events)
+ showEvent((EventItem)selectedItem);
+ }
+
+ public void switchSchema(String schemaName) {
+ clearView();
+ suspendSelection = true;
+ views.removeAllItems();
+ events.removeAllItems();
+ viewpointList = new ArrayList<Viewpoint>();
+ eventList = new ArrayList<EventItem>();
+
+ currentSchema = schemaName;
+
+ try {
+ // populate views
+ String viewNames = sourceEntity.getEntity().queryData(ClusterStorage.VIEWPOINT+"/"+schemaName+"/all");
+ StringTokenizer tok = new StringTokenizer(viewNames, ",");
+ Viewpoint lastView = null;
+ while(tok.hasMoreTokens()) {
+ String viewName = tok.nextToken();
+ Viewpoint thisView = (Viewpoint)sourceEntity.getEntity().getObject(ClusterStorage.VIEWPOINT+"/"+schemaName+"/"+viewName);
+ views.addItem(thisView);
+ if (lastView == null) lastView = thisView;
+ if (thisView.getName().equals("last")) //select
+ lastView = thisView;
+ viewpointList.add(thisView);
+ }
+
+ String ocVersions = sourceEntity.getEntity().queryData(ClusterStorage.OUTCOME+"/"+schemaName+"/all");
+ tok = new StringTokenizer(ocVersions, ",");
+ while(tok.hasMoreTokens()) {
+ int schemaVersion = Integer.parseInt(tok.nextToken());
+ String ocEvents = sourceEntity.getEntity().queryData(ClusterStorage.OUTCOME+"/"+schemaName+"/"+schemaVersion+"/all");
+ StringTokenizer tok2 = new StringTokenizer(ocEvents, ",");
+ while(tok2.hasMoreTokens()) {
+ int eventId = Integer.parseInt(tok2.nextToken());
+ EventItem newEvent = new EventItem(eventId, schemaVersion);
+ for (Viewpoint thisView : viewpointList) {
+ if (thisView.getEventId() == eventId)
+ newEvent.addView(thisView.getName());
+ }
+ eventList.add(newEvent);
+ }
+ Collections.sort(eventList, new Comparator<EventItem>() {
+ @Override
+ public int compare(EventItem o1, EventItem o2) {
+ return o1.compareTo(o2);
+ }
+ });
+ for (EventItem eventItem : eventList)
+ events.addItem(eventItem);
+ }
+
+ if (lastView != null) {
+ suspendSelection = false;
+ views.setSelectedItem(lastView);
+ switchView(lastView);
+ }
+
+ } catch (Exception e) {
+ Logger.error(e);
+ JOptionPane.showMessageDialog(this,
+ "The data structures of this item are incorrect.\nPlease contact your administrator.",
+ "Viewpoint Error" , JOptionPane.ERROR_MESSAGE);
+ }
+ suspendSelection = false;
+ }
+
+ public void switchView(Viewpoint newView) {
+ for (EventItem thisEvent : eventList) {
+ if (thisEvent.eventId == newView.getEventId()) {
+ suspendSelection = true;
+ events.setSelectedItem(thisEvent);
+ showEvent(thisEvent);
+ suspendSelection = false;
+ break;
+ }
+ }
+ }
+
+ public void showEvent(EventItem thisEvent) {
+ eventDetails.setText(thisEvent.getEventDesc());
+ try {
+ setView((Outcome)sourceEntity.getEntity().getObject(
+ ClusterStorage.OUTCOME+"/"+currentSchema+"/"+thisEvent.schemaVersion+"/"+thisEvent.eventId));
+ } catch (Exception ex) {
+ Logger.error(ex);
+ JOptionPane.showMessageDialog(this,
+ "Could not retrieve requested outcome.\nPlease contact your administrator.",
+ "Viewpoint Error" , JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ public void setView(Outcome data) {
+ Logger.msg(6, "ViewpointPane: got outcome type: "+data.getSchemaType()+" version: "+data.getSchemaVersion());
+ String schema;
+ currentOutcome = data;
+ dataView.removeAll();
+ String error = null;
+ try {
+ schema = LocalObjectLoader.getSchema(data.getSchemaType(), data.getSchemaVersion()).schema;
+ thisOutcome = EntityTabPane.getOutcomeHandler(data.getSchemaType(), data.getSchemaVersion());
+ thisOutcome.setDescription(schema);
+ thisOutcome.setOutcome(data.getData());
+ thisOutcome.setReadOnly(true);
+ Thread builder = new Thread(thisOutcome);
+ builder.start();
+ dataView.add(thisOutcome.getPanel());
+ exportButton.setEnabled(true);
+ if (viewButton!=null) viewButton.setEnabled(true);
+ return;
+ } catch (ObjectNotFoundException ex) {
+ error = "Schema not found";
+ } catch (OutcomeException ex) {
+ error = "Outcome was not valid. See log for details: "+ex.getMessage();
+ Logger.error(ex);
+ }
+
+ dataView.add(new JLabel(error));
+ }
+
+ public void clearView() {
+ dataView.removeAll();
+ exportButton.setEnabled(false);
+ if (viewButton!=null) viewButton.setEnabled(false);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("export") && currentOutcome != null)
+ saveOutcomeToFile();
+ if (e.getActionCommand().equals("setview") && currentOutcome != null)
+ overrideView();
+ }
+
+ private void saveOutcomeToFile() {
+
+ MainFrame.xmlChooser.setSelectedFile(new File(currentOutcome.getSchemaType()+".xml"));
+ int returnVal = MainFrame.xmlChooser.showSaveDialog(this);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File targetFile = MainFrame.xmlChooser.getSelectedFile();
+ if (!(targetFile.getAbsolutePath().endsWith(".xml")))
+ targetFile = new File(targetFile.getAbsolutePath()+".xml");
+
+ Logger.msg(2, "ViewpointPane.actionPerformed() - Exporting outcome to file " + targetFile.getName());
+ try {
+ thisOutcome.export(targetFile);
+ }
+ catch (Exception ex) {
+ Logger.error(ex);
+ Logger.exceptionDialog(ex);
+ }
+ }
+
+ }
+
+ private void overrideView() {
+
+ Viewpoint oldView = (Viewpoint)views.getSelectedItem();
+ EventItem newEvent = (EventItem)events.getSelectedItem();
+
+ if (oldView.getEventId() == newEvent.eventId) {
+ JOptionPane.showMessageDialog(this,
+ "View '"+oldView.getName()+"' is already set to event "+newEvent.eventId,
+ "Viewpoint Already Set" , JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ if (JOptionPane.showConfirmDialog(this,
+ "Are you sure you want to set the '"+oldView.getName()+
+ "' view to event " + newEvent.eventId+ "?",
+ "Overwrite view",
+ JOptionPane.YES_NO_OPTION) != JOptionPane.YES_OPTION)
+ return;
+
+ oldView.setEventId(newEvent.eventId);
+ try {
+ String[] predefParams = new String[1];
+ predefParams[0] = CastorXMLUtility.marshall(oldView);
+ MainFrame.userAgent.execute((ItemProxy)sourceEntity.getEntity(), "AddC2KObject", predefParams);
+ } catch (Exception e) {
+ Logger.error(e);
+ Logger.exceptionDialog(e);
+ }
+ }
+
+ @Override
+ public void add(C2KLocalObject contents) {
+ if (contents instanceof Viewpoint)
+ addViewpoint((Viewpoint)contents);
+ else if (contents instanceof Outcome)
+ addOutcome((Outcome)contents);
+
+ }
+
+ public void addViewpoint(Viewpoint newView) {
+ String schemaName = newView.getSchemaName();
+ Logger.msg(3, "Viewpoint "+newView.getName()+" now points to "+newView.getEventId());
+ if (!(schemaList.contains(schemaName))) {
+ schemaList.add(schemaName);
+ schemas.addItem(schemaName);
+ return;
+ }
+
+
+ if (!(schemaName.equals(schemas.getSelectedItem())))
+ return;
+
+ for (EventItem thisEvent : eventList) {
+ if (thisEvent.eventId == newView.getEventId())
+ thisEvent.addView(newView.getName());
+ else
+ thisEvent.removeView(newView.getName());
+ }
+
+ boolean isSelected = false;
+ for (Viewpoint thisView : viewpointList) {
+ if (thisView.getName().equals(newView.getName())) {
+ isSelected = thisView.equals(views.getSelectedItem());
+ views.removeItem(thisView);
+ viewpointList.remove(thisView);
+ break;
+ }
+ }
+
+ views.addItem(newView);
+ viewpointList.add(newView);
+ if (isSelected) {
+ views.setSelectedItem(newView);
+ }
+
+ }
+
+ public void addOutcome(Outcome contents) {
+ if (!(contents.getSchemaType().equals(currentSchema))) // not interested
+ return;
+ Logger.msg(3, "Adding event "+contents.getID());
+ EventItem newEvent = new EventItem(contents.getID(), contents.getSchemaVersion());
+ eventList.add(newEvent);
+ events.addItem(newEvent);
+ }
+
+ @Override
+ public void remove(String id) {
+ // we don't really remove viewpoints
+ }
+
+ class EventItem implements Comparable<EventItem> {
+ public int eventId;
+ public int schemaVersion;
+ public ArrayList<String> viewNames = new ArrayList<String>();
+ public String viewList = "";
+
+ public EventItem(int eventId, int schemaVersion) {
+ this.eventId = eventId;
+ this.schemaVersion = schemaVersion;
+ }
+
+ public void addView(String viewName) {
+ if (!(viewNames.contains(viewName))) {
+ viewNames.add(viewName);
+ buildViewLabel();
+ }
+ }
+
+ public void removeView(String viewName) {
+ viewNames.remove(viewName);
+ buildViewLabel();
+ }
+
+ private void buildViewLabel() {
+ if (viewNames.size() == 0) {
+ viewList = "";
+ return;
+ }
+
+ StringBuffer newLabel = new StringBuffer(" (");
+ for (Iterator<String> iter = viewNames.iterator(); iter.hasNext();) {
+ String viewName = iter.next();
+ newLabel.append(viewName);
+ if (iter.hasNext())
+ newLabel.append(", ");
+ }
+
+ viewList = newLabel.append(")").toString();
+ }
+
+ @Override
+ public String toString() {
+ return eventId+viewList;
+
+ }
+
+ public String getEventDesc() {
+ try {
+ Event myEvent = (Event)sourceEntity.getEntity().getObject(ClusterStorage.HISTORY+"/"+eventId);
+ return (Language.translate("Recorded on")+" "+myEvent.getTimeString()+" "+
+ Language.translate("by")+" "+myEvent.getAgentName()+" "+
+ Language.translate("using schema v")+schemaVersion);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ return ("Error retrieving event details");
+ }
+ }
+
+ @Override
+ public int compareTo(EventItem other) {
+ if (other.eventId < eventId) return 1;
+ if (other.eventId > eventId) return -1;
+ return 0;
+ }
+ }
+
+ @Override
+ public void control(String control, String msg) {
+ // TODO Auto-generated method stub
+
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/WorkflowPane.java b/src/main/java/com/c2kernel/gui/tabs/WorkflowPane.java new file mode 100644 index 0000000..e4acd8d --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/WorkflowPane.java @@ -0,0 +1,286 @@ +package com.c2kernel.gui.tabs;
+import java.awt.Cursor;
+import java.awt.GridBagConstraints;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JSplitPane;
+
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.entity.proxy.MemberSubscription;
+import com.c2kernel.graph.layout.DefaultGraphLayoutGenerator;
+import com.c2kernel.graph.model.EdgeFactory;
+import com.c2kernel.graph.model.Selection;
+import com.c2kernel.graph.model.VertexFactory;
+import com.c2kernel.graph.view.EditorPanel;
+import com.c2kernel.graph.view.VertexPropertyPanel;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lifecycle.instance.CompositeActivity;
+import com.c2kernel.lifecycle.instance.Workflow;
+import com.c2kernel.lifecycle.instance.gui.model.WfEdgeFactory;
+import com.c2kernel.lifecycle.instance.gui.model.WfGraphPanel;
+import com.c2kernel.lifecycle.instance.gui.model.WfVertexFactory;
+import com.c2kernel.lifecycle.instance.gui.model.WfVertexOutlineCreator;
+import com.c2kernel.lifecycle.instance.gui.view.TransitionPanel;
+import com.c2kernel.lifecycle.instance.gui.view.WfDirectedEdgeRenderer;
+import com.c2kernel.lifecycle.instance.gui.view.WfVertexRenderer;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+public class WorkflowPane extends EntityTabPane implements EntityProxyObserver<Workflow>
+{
+ // Only for the purpose of loading and saving
+ protected Workflow mWorkflow = null;
+ boolean init = false;
+ TransitionPanel transPanel;
+ protected JButton mLoadButton = new JButton(Resource.findImage("graph/load.png"));
+ protected JButton mSaveButton = new JButton(Resource.findImage("graph/save.png"));
+ protected JButton mLayoutButton = new JButton(Resource.findImage("graph/autolayout.png"));
+ protected JButton mZoomOutButton = new JButton(Resource.findImage("graph/zoomout.png"));
+ protected JButton[] mOtherToolBarButtons;
+ // Workflow factories
+ protected EdgeFactory mWfEdgeFactory;
+ protected VertexFactory mWfVertexFactory;
+ // Graph editor panel
+ protected EditorPanel mEditorPanel;
+ // Objects to view/modify the properties of the selected activity
+ protected VertexPropertyPanel mPropertyPanel;
+ protected JSplitPane mSplitPane;
+
+ // Graph editor panel
+ // Objects to view/modify the properties of the selected activity
+ public WorkflowPane()
+ {
+ super("Workflow", "Workflow Viewer");
+ // Workflow factories
+ mWfEdgeFactory = new WfEdgeFactory();
+ mWfVertexFactory = new WfVertexFactory();
+ mZoomOutButton.setToolTipText(Language.translate("Zoom Out"));
+ mLayoutButton.setToolTipText(Language.translate("Auto Layout"));
+ mLoadButton.setToolTipText(Language.translate("Load"));
+ mSaveButton.setToolTipText(Language.translate("Save"));
+ mOtherToolBarButtons = new JButton[] { mZoomOutButton, mLayoutButton, mLoadButton, mSaveButton };
+
+ }
+
+ protected void createListeners()
+ {
+ /**
+ *
+ */
+ mLoadButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent ae)
+ {
+ loadWorkflow();
+ }
+ });
+ /**
+ *
+ */
+ mSaveButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent ae)
+ {
+ setCursor(new Cursor(Cursor.WAIT_CURSOR));
+ saveWorkflow();
+ setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
+ }
+ });
+ /**
+ *
+ */
+ mLayoutButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent ae)
+ {
+ DefaultGraphLayoutGenerator.layoutGraph(mEditorPanel.mGraphModelManager.getModel());
+ }
+ });
+ /**
+ *
+ */
+ mZoomOutButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent ae)
+ {
+ mEditorPanel.mGraphModelManager.zoomOut();
+ }
+ });
+ }
+ /**
+ * Return a single ref on mEditorPanel
+ *
+ * @return EditorPanel
+ */
+ public EditorPanel getEditorPanel()
+ {
+ if (mEditorPanel == null)
+ mEditorPanel =
+ new EditorPanel(
+ mWfEdgeFactory,
+ mWfVertexFactory,
+ new WfVertexOutlineCreator(),
+ true,
+ mOtherToolBarButtons,
+ new WfGraphPanel(new WfDirectedEdgeRenderer(), new WfVertexRenderer()));
+ return mEditorPanel;
+ }
+ public JSplitPane getJSplitPane()
+ {
+ if (mSplitPane == null)
+ {
+ mSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, getEditorPanel(), getPropertyPanel());
+ mSplitPane.setDividerSize(5);
+ mSplitPane.setDividerLocation(800);
+ }
+ return mSplitPane;
+ }
+ @Override
+ public void add(Workflow contents)
+ {
+ mWorkflow = contents;
+ addActivity((CompositeActivity) mWorkflow.search("workflow/domain"));
+ }
+ @Override
+ public void remove(String id)
+ {
+ }
+ protected void addActivity(CompositeActivity cAct)
+ {
+ // Resolve any undefined references in the workflow
+ mEditorPanel.mGraphModelManager.replace(cAct.getChildrenGraphModel());
+ // Give the editor panel the edge and vertex types
+ mEditorPanel.updateVertexTypes(cAct.getWf().getVertexTypeNameAndConstructionInfo());
+ mEditorPanel.updateEdgeTypes(cAct.getWf().getEdgeTypeNameAndConstructionInfo());
+ mEditorPanel.enterSelectMode();
+ mWfVertexFactory.setCreationContext(cAct);
+ }
+ @Override
+ public void run()
+ {
+ Thread.currentThread().setName("Workflow Pane Builder");
+ if (!init)
+ {
+ getEditorPanel();
+ createLayout();
+ createListeners();
+ mPropertyPanel.setGraphModelManager(mEditorPanel.mGraphModelManager);
+ mEditorPanel.setEditable(MainFrame.isAdmin);
+ init = true;
+ }
+ sourceEntity.getEntity().subscribe(new MemberSubscription<Workflow>(this, ClusterStorage.LIFECYCLE, true));
+ transPanel.setItem((ItemProxy) sourceEntity.getEntity());
+ }
+ @Override
+ public void reload()
+ {
+ Gateway.getStorage().clearCache(sourceEntity.getSysKey(), ClusterStorage.LIFECYCLE);
+ initForEntity(sourceEntity);
+ }
+ protected void createLayout()
+ {
+ initPanel();
+ // Add the editor pane
+ getGridBagConstraints().gridx = 0;
+ getGridBagConstraints().gridy = 1;
+ getGridBagConstraints().fill = GridBagConstraints.BOTH;
+ getGridBagConstraints().weighty = 2.0;
+ gridbag.setConstraints(getJSplitPane(), getGridBagConstraints());
+ add(getJSplitPane());
+ validate();
+ }
+ protected void loadWorkflow()
+ {
+ File selectedFile = null;
+ int returnValue = MainFrame.xmlChooser.showOpenDialog(null);
+ switch (returnValue)
+ {
+ case JFileChooser.APPROVE_OPTION :
+ selectedFile = MainFrame.xmlChooser.getSelectedFile();
+ try
+ {
+ String newWf = FileStringUtility.file2String(selectedFile);
+ add((Workflow) CastorXMLUtility.unmarshall(newWf));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ case JFileChooser.CANCEL_OPTION :
+ case JFileChooser.ERROR_OPTION :
+ default :
+ }
+ }
+ protected String marshall() throws Exception
+ {
+ return com.c2kernel.utils.CastorXMLUtility.marshall(mWorkflow.getWf());
+ }
+ protected void saveWorkflow()
+ {
+ try
+ {
+ CompositeActivity cact = (CompositeActivity)mWorkflow.getWf().search("workflow/domain");
+ MainFrame.userAgent.execute(
+ (ItemProxy)sourceEntity.getEntity(),
+ "ReplaceDomainWorkflow",
+ new String[] { com.c2kernel.utils.CastorXMLUtility.marshall(cact)});
+ cact.getChildrenGraphModel().setSelection(new Selection(null,null,0,0,0,0));
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ }
+ }
+
+ public VertexPropertyPanel getPropertyPanel()
+ {
+ if (mPropertyPanel == null) {
+ setNewPropertyPanel();
+ transPanel = new TransitionPanel();
+ mPropertyPanel.createLayout(transPanel);
+ mPropertyPanel.setGraphModelManager(mEditorPanel.mGraphModelManager);
+ mPropertyPanel.setEditable(MainFrame.isAdmin);
+ }
+ return mPropertyPanel;
+ }
+
+ public void setNewPropertyPanel()
+ {
+ String wfPanelClass = Gateway.getProperty("WfPropertyPanel");
+ if (wfPanelClass != null)
+ {
+ try
+ {
+ Class<?> panelClass = Class.forName(wfPanelClass);
+ mPropertyPanel = (VertexPropertyPanel) panelClass.newInstance();
+ return;
+ }
+ catch (Exception ex)
+ {
+ Logger.error("Could not load wf props panel:" + wfPanelClass);
+ Logger.error(ex);
+ }
+ }
+ mPropertyPanel = new VertexPropertyPanel();
+ }
+
+ @Override
+ public void control(String control, String msg) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/collection/AggregationView.java b/src/main/java/com/c2kernel/gui/tabs/collection/AggregationView.java new file mode 100644 index 0000000..b6578bb --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/collection/AggregationView.java @@ -0,0 +1,90 @@ +package com.c2kernel.gui.tabs.collection;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JSplitPane;
+
+import com.c2kernel.collection.Aggregation;
+import com.c2kernel.collection.AggregationMember;
+import com.c2kernel.collection.Collection;
+import com.c2kernel.collection.gui.model.AggregationVertexFactory;
+import com.c2kernel.collection.gui.model.AggregationVertexOutlineCreator;
+import com.c2kernel.collection.gui.view.AggregationMemberRenderer;
+import com.c2kernel.collection.gui.view.PropertyPanel;
+import com.c2kernel.collection.gui.view.SelectedMemberPanel;
+import com.c2kernel.graph.view.EditorPanel;
+import com.c2kernel.graph.view.GraphPanel;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Resource;
+/**
+ * @version $Revision: 1.5 $ $Date: 2006/09/15 15:02:24 $
+ * @author $Author: abranson $
+ */
+public class AggregationView extends CollectionView<AggregationMember>
+{
+ protected JButton mSaveButton = new JButton(Resource.findImage("graph/save.png"));
+ protected JButton mHistoryButton = new JButton(Resource.findImage("graph/history.png"));
+ protected JButton[] mOtherToolBarButtons = { mSaveButton, mHistoryButton };
+ // Graph editor panel
+ protected EditorPanel mEditorPanel;
+ // Objects to view/modify the properties of the selected activity
+ protected PropertyPanel mPropertyPanel;
+ protected JSplitPane mSplitPane;
+ private final AggregationVertexFactory mAggregationVertexFactory = new AggregationVertexFactory();
+ private final AggregationMemberRenderer mAggregationMemberRenderer = new AggregationMemberRenderer();
+ public AggregationView()
+ {
+ super();
+ setLayout(new GridLayout(1,1));
+ mPropertyPanel = new PropertyPanel();
+ mEditorPanel = new EditorPanel(null, mAggregationVertexFactory, new AggregationVertexOutlineCreator(), false, mOtherToolBarButtons, new GraphPanel(null, mAggregationMemberRenderer));
+ createLayout();
+ createListeners();
+ mPropertyPanel.setGraphModelManager(mEditorPanel.mGraphModelManager);
+ mPropertyPanel.createLayout(new SelectedMemberPanel());
+ mEditorPanel.setEditable(MainFrame.isAdmin);
+ }
+
+ @Override
+ public void setCollection(Collection<AggregationMember> contents)
+ {
+ thisColl = contents;
+ Aggregation agg = (Aggregation)thisColl;
+ mPropertyPanel.setCollection(agg);
+ mAggregationMemberRenderer.setAggregation(agg);
+ mEditorPanel.mGraphModelManager.setModel(agg.getLayout());
+ mEditorPanel.updateVertexTypes(agg.getVertexTypeNameAndConstructionInfo());
+ mEditorPanel.enterSelectMode();
+ mAggregationVertexFactory.setCreationContext(agg);
+ }
+ public void createLayout()
+ {
+ mSaveButton.setToolTipText(Language.translate("Save Layout Changes"));
+ mSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, mEditorPanel, mPropertyPanel);
+ mSplitPane.setDividerSize(5);
+ add(mSplitPane);
+ }
+
+ protected void createListeners()
+ {
+ mSaveButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent ae)
+ {
+ saveCollection();
+ }
+ });
+ mHistoryButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent ae)
+ {
+ new CollectionHistoryWindow(item, (Aggregation)thisColl);
+ }
+ });
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/collection/CollectionHistoryWindow.java b/src/main/java/com/c2kernel/gui/tabs/collection/CollectionHistoryWindow.java new file mode 100644 index 0000000..673f3ac --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/collection/CollectionHistoryWindow.java @@ -0,0 +1,192 @@ +package com.c2kernel.gui.tabs.collection;
+
+import java.awt.HeadlessException;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+
+import javax.swing.JFrame;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.table.AbstractTableModel;
+
+import com.c2kernel.collection.Aggregation;
+import com.c2kernel.collection.Collection;
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.EntityProxy;
+import com.c2kernel.entity.proxy.EntityProxyObserver;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.entity.proxy.MemberSubscription;
+import com.c2kernel.events.Event;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.lifecycle.instance.predefined.PredefinedStep;
+import com.c2kernel.lookup.EntityPath;
+import com.c2kernel.lookup.InvalidEntityPathException;
+import com.c2kernel.persistency.ClusterStorage;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+public class CollectionHistoryWindow extends JFrame {
+
+ JTable historyTable;
+ HistoryTableModel historyModel;
+
+ public CollectionHistoryWindow(ItemProxy item, Aggregation coll) throws HeadlessException {
+ super("Collection History");
+ historyModel = new HistoryTableModel(item, coll);
+ historyTable = new JTable(historyModel);
+ this.getContentPane().add(new JScrollPane(historyTable));
+ historyTable.addMouseListener(new HistoryTableListener(item));
+ this.pack();
+ super.toFront();
+ this.validate();
+ this.setVisible(true);
+ }
+
+ private class HistoryTableModel extends AbstractTableModel implements EntityProxyObserver<Event> {
+
+ ItemProxy item;
+ ArrayList<Event> collEvents;
+ ArrayList<Object> collEventData;
+ Aggregation coll;
+ public HistoryTableModel(ItemProxy item, Aggregation coll) {
+ this.item = item;
+ this.coll = coll;
+ collEvents = new ArrayList<Event>();
+ collEventData = new ArrayList<Object>();
+ item.subscribe(new MemberSubscription<Event>(this, ClusterStorage.HISTORY, true));
+ }
+ @Override
+ public int getColumnCount() {
+ return 4;
+ }
+
+ @Override
+ public String getColumnName(int columnIndex) {
+ switch(columnIndex) {
+ case 0: return Language.translate("Date");
+ case 1: return Language.translate("Operation");
+ case 2: return Language.translate("Slot");
+ case 3: return Language.translate("Child");
+ default: return "";
+ }
+ }
+ @Override
+ public int getRowCount() {
+ return collEvents.size();
+ }
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ Event ev = collEvents.get(rowIndex);
+ switch (columnIndex) {
+ case 0:
+ return ev.getTimeString();
+ case 1:
+ if (ev.getStepName().equals("AssignItemToSlot"))
+ return "Item Assigned";
+ else
+ return "Collection replaced";
+ case 2:
+ if (ev.getStepName().equals("AssignItemToSlot"))
+ return ((String[])collEventData.get(rowIndex))[1];
+ return "";
+ case 3:
+ if (ev.getStepName().equals("AddC2KObject"))
+ return "Click to view";
+ String name;
+ try {
+ EntityProxy childItem = Gateway.getProxyManager().getProxy(new EntityPath(Integer.parseInt(((String[])collEventData.get(rowIndex))[2])));
+ name = childItem.getName();
+ } catch (NumberFormatException e) {
+ name = "Invalid entity key: "+((String[])collEventData.get(rowIndex))[2];
+ } catch (ObjectNotFoundException e) {
+ name = "Item deleted: "+((String[])collEventData.get(rowIndex))[2];
+ } catch (InvalidEntityPathException e) {
+ name = "Invalid entity key: "+((String[])collEventData.get(rowIndex))[2];
+ }
+ return name;
+ default:
+ return "";
+ }
+ }
+ public Object getEventData(int row) {
+ return collEventData.get(row);
+ }
+ @Override
+ public void add(Event thisEv) {
+ if (thisEv.getStepName().equals("AssignItemToSlot") || thisEv.getStepName().equals("AddC2KObject")) {
+ String[] params;
+ try {
+ Outcome oc = (Outcome)item.getObject(ClusterStorage.OUTCOME+"/PredefinedStepOutcome/0/"+thisEv.getID());
+ params = PredefinedStep.getDataList(oc.getData());
+ } catch (ObjectNotFoundException ex) { return; }
+ if (thisEv.getStepName().equals("AssignItemToSlot")) {
+ if (params[0].equals(coll.getName()))
+ collEventData.add(params);
+ else return;
+ }
+ else {
+ Object obj;
+ try {
+ obj = CastorXMLUtility.unmarshall(params[0]);
+ } catch (Exception e) {
+ Logger.error(e);
+ return;
+ }
+ if (obj instanceof Collection)
+ collEventData.add(obj);
+ else return;
+
+ }
+ }
+ else return;
+ collEvents.add(thisEv);
+ fireTableRowsInserted(collEvents.size()-1, collEvents.size()-1);
+ }
+ @Override
+ public void remove(String id) { }
+ @Override
+ public void control(String control, String msg) {
+ }
+ }
+
+ private class HistoryTableListener extends MouseAdapter {
+
+ ItemProxy item;
+ public HistoryTableListener(ItemProxy item) {
+ this.item = item;
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (e.getClickCount()==2) {
+ int row = historyTable.getSelectedRow();
+ Object data = historyModel.getEventData(row);
+ if (data instanceof Aggregation) {
+ showColl((Aggregation)data);
+ }
+ else {
+ String[] params = (String[])data;
+ try {
+ EntityProxy childItem = Gateway.getProxyManager().getProxy(new EntityPath(Integer.parseInt(params[2])));
+ MainFrame.itemFinder.pushNewKey(childItem.getName());
+ } catch (Exception ex) { }
+ }
+ }
+ }
+ public void showColl(Aggregation coll) {
+ JFrame newFrame = new JFrame();
+ AggregationView newView = new AggregationView();
+ newView.setCollection(coll);
+ newView.setItem(item);
+ newFrame.getContentPane().add(newView);
+ newFrame.pack();
+ newFrame.toFront();
+ newFrame.validate();
+ newFrame.setVisible(true);
+ }
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/collection/CollectionView.java b/src/main/java/com/c2kernel/gui/tabs/collection/CollectionView.java new file mode 100644 index 0000000..c698430 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/collection/CollectionView.java @@ -0,0 +1,49 @@ +package com.c2kernel.gui.tabs.collection;
+
+import javax.swing.JPanel;
+
+import com.c2kernel.collection.Collection;
+import com.c2kernel.collection.CollectionMember;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2004/08/10 07:56:08 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+public abstract class CollectionView<M extends CollectionMember> extends JPanel {
+
+ protected Collection<M> thisColl;
+ protected ItemProxy item;
+
+ public CollectionView() {
+ super();
+ }
+
+ public void setItem(ItemProxy entity) {
+ this.item = entity;
+ }
+
+ public abstract void setCollection(Collection<M> coll);
+
+ protected void saveCollection()
+ {
+ try
+ {
+ String[] params = new String[1];
+ params[0] = com.c2kernel.utils.CastorXMLUtility.marshall(thisColl);
+ MainFrame.userAgent.execute(item, "AddC2KObject", params);
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ }
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/collection/DependencyView.java b/src/main/java/com/c2kernel/gui/tabs/collection/DependencyView.java new file mode 100644 index 0000000..e068bdc --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/collection/DependencyView.java @@ -0,0 +1,34 @@ +package com.c2kernel.gui.tabs.collection;
+import java.awt.GridLayout;
+
+import javax.swing.JLabel;
+
+import com.c2kernel.collection.Collection;
+import com.c2kernel.collection.DependencyMember;
+/**
+ * @version $Revision: 1.2 $ $Date: 2005/06/02 12:17:22 $
+ * @author $Author: abranson $
+ */
+public class DependencyView extends CollectionView<DependencyMember>
+{
+ // Objects to view/modify the properties of the selected activity
+
+ public DependencyView()
+ {
+ super();
+ setLayout(new GridLayout(1,1));
+ createLayout();
+ }
+
+ @Override
+ public void setCollection(Collection<DependencyMember> contents)
+ {
+ thisColl = contents;
+ }
+ public void createLayout()
+ {
+ // TODO: design a nice dependency view, with property viewing and modification
+ add(new JLabel("Dependency view not yet implemented. Please browse the tree instead."));
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/execution/ActivityItem.java b/src/main/java/com/c2kernel/gui/tabs/execution/ActivityItem.java new file mode 100644 index 0000000..6a8f2f7 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/execution/ActivityItem.java @@ -0,0 +1,55 @@ +package com.c2kernel.gui.tabs.execution;
+import java.util.ArrayList;
+
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.lifecycle.instance.stateMachine.States;
+
+public class ActivityItem {
+ public String stepPath;
+ public int state;
+ public String name;
+ ArrayList<Job> jobs = new ArrayList<Job>();
+
+ public ActivityItem() {
+ stepPath = "";
+ state = -1;
+ name = "--";
+ }
+
+ public ActivityItem(Job thisJob) {
+ stepPath = thisJob.getStepPath();
+ state = thisJob.getCurrentState();
+ name = thisJob.getStepName();
+ jobs.add(thisJob);
+ }
+
+ public void addJob(Job newJob) {
+ jobs.add(newJob);
+ }
+
+ public ArrayList<Job> getJobs() {
+ return jobs;
+ }
+
+ public String getStepPath() {
+ return stepPath;
+ }
+
+ @Override
+ public String toString() {
+ return name+(state>-1?" ("+States.getStateName(state)+")":"");
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof ActivityItem)
+ return hashCode() == ((ActivityItem)other).hashCode();
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return stepPath.hashCode();
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/execution/ActivityViewer.java b/src/main/java/com/c2kernel/gui/tabs/execution/ActivityViewer.java new file mode 100644 index 0000000..707f311 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/execution/ActivityViewer.java @@ -0,0 +1,296 @@ +package com.c2kernel.gui.tabs.execution;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.GridLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.util.ArrayList;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.EntityTabPane;
+import com.c2kernel.gui.tabs.ExecutionPane;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.OutcomeHandler;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.LocalObjectLoader;
+import com.c2kernel.utils.Logger;
+
+public class ActivityViewer extends JPanel implements Runnable {
+
+ ItemProxy item;
+ Box outcomeButtons = Box.createHorizontalBox();
+ OutcomeHandler outcomePanel;
+ JPanel outcomeView = new JPanel(new GridLayout(1,1));
+ ActivityItem thisAct;
+ ArrayList<RequestButton> requestButtons = new ArrayList<RequestButton>();
+ JLabel noOutcome = new JLabel(Language.translate("No outcome data is required for this activity"));
+ ExecutionPane parent;
+ JLabel status;
+ JComboBox executors;
+ JButton saveButton = new JButton("Save");
+ JButton loadButton = new JButton("Load");
+ GridBagLayout gridbag = new GridBagLayout();
+ Job executingJob = null;
+ static JFileChooser chooser = new JFileChooser();
+ static {
+ chooser.addChoosableFileFilter(
+ new javax.swing.filechooser.FileFilter() {
+ @Override
+ public String getDescription() {
+ return "XML Files";
+ }
+ @Override
+ public boolean accept(File f) {
+ if (f.isDirectory() || (f.isFile() && f.getName().endsWith(".xml"))) {
+ return true;
+ }
+ return false;
+ }
+ });
+ }
+
+ public ActivityViewer (ActivityItem newAct, ItemProxy item, ExecutionPane parent){
+ thisAct = newAct;
+ this.item = item;
+ this.parent = parent;
+ setLayout(gridbag);
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx=0; c.gridy=1; c.weightx=1.0; c.weighty=0.0;
+ c.insets = new Insets(5,5,5,5);
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.HORIZONTAL;
+
+// activity title
+ JLabel actTitle = new JLabel(Language.translate("Activity")+": "+newAct.name);
+ actTitle.setFont(EntityTabPane.titleFont);
+ gridbag.setConstraints(actTitle, c);
+ add(actTitle);
+
+ Job firstJob = (thisAct.getJobs().get(0));
+// desc
+ String desc = firstJob.getDescription();
+ if (desc != null && desc.length() > 0) {
+ Box descBox = Box.createHorizontalBox();
+
+ String chopDesc = null;
+ if(desc.length() >= 40) chopDesc = desc.substring(0,40);
+ else chopDesc = desc;
+
+ descBox.add(new JLabel("Description: "+chopDesc));
+ if (desc.length()>chopDesc.length()) {
+ descBox.add(new JLabel(" ..."));
+ descBox.add(Box.createHorizontalStrut(7));
+ JButton descButton = new JButton("View");
+ descButton.setMargin(new Insets(0,0,0,0));
+ descButton.setActionCommand(desc);
+ descButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JTextArea descArea = new JTextArea(e.getActionCommand());
+ descArea.setLineWrap(true);
+ descArea.setWrapStyleWord(true);
+ JScrollPane descScroll = new JScrollPane(descArea);
+ descScroll.setPreferredSize(new Dimension(400,150));
+ JOptionPane.showMessageDialog(null, descScroll, "Activity Description", JOptionPane.PLAIN_MESSAGE);
+ }
+ });
+ descBox.add(descButton);
+ }
+
+ c.gridy++;
+ gridbag.setConstraints(descBox, c);
+ add(descBox);
+ }
+
+
+// agentid
+ String roleName = firstJob.getAgentRole();
+ if (roleName!= null && roleName.length()>0) {
+ c.gridy++;
+ JLabel role = new JLabel(Language.translate("Agent Role")+": "+roleName);
+ gridbag.setConstraints(role, c);
+ add(role);
+ }
+
+ c.gridy++;
+ c.anchor = GridBagConstraints.EAST;
+ gridbag.setConstraints(outcomeButtons, c);
+ add(outcomeButtons);
+
+ executors = MainFrame.getExecutionPlugins();
+ if (executors.getItemCount() > 1) {
+ c.gridx++;
+ gridbag.setConstraints(executors, c);
+ add(executors);
+ c.gridx--;
+ }
+
+ c.gridy++;
+
+ status = new JLabel(Language.translate("Waiting for request"));
+ status.setFont(EntityTabPane.titleFont);
+ gridbag.setConstraints(status, c);
+ add(status);
+
+ c.gridx++;
+ Box fileBox = Box.createHorizontalBox();
+ fileBox.add(saveButton); fileBox.add(Box.createHorizontalGlue()); fileBox.add(loadButton);
+ gridbag.setConstraints(fileBox, c);
+ add(fileBox);
+ saveButton.setEnabled(false);
+ loadButton.setEnabled(false);
+ c.gridx--;
+ c.gridwidth = 2;
+ boolean outcomeEmpty = true;
+ for (Object name2 : thisAct.getJobs()) {
+ Job thisJob = (Job)name2;
+ RequestButton newButton = new RequestButton(thisJob, this);
+ requestButtons.add(newButton);
+ outcomeButtons.add(newButton);
+ outcomeButtons.add(Box.createHorizontalStrut(5));
+
+ if (thisJob.isOutcomeUsed()) {
+ String schema;
+ if (outcomeEmpty) {
+ try {
+ schema = LocalObjectLoader.getSchema(thisJob.getSchemaType(), thisJob.getSchemaVersion()).schema;
+ outcomePanel = EntityTabPane.getOutcomeHandler(thisJob.getSchemaType(), thisJob.getSchemaVersion());
+ outcomePanel.setReadOnly(false);
+ outcomePanel.setDescription(schema);
+ String outcomeString = thisJob.getOutcomeString();
+ if ( outcomeString!= null && outcomeString.length() > 0)
+ outcomePanel.setOutcome(outcomeString);
+ outcomeView = outcomePanel.getPanel();
+ } catch (ObjectNotFoundException ex) {
+ outcomeView.add(new JLabel(Language.translate("Schema not found:")+" "+thisJob.getSchemaType()+" v"+thisJob.getSchemaVersion()));
+ outcomePanel = null;
+ } catch (Exception ex) {
+ outcomeView.add(new JLabel(Language.translate("ERROR loading outcome editor: ")
+ +ex.getClass().getName()+" ("+ex.getMessage()+")"));
+ Logger.error(ex);
+ outcomePanel = null;
+ }
+ }
+ outcomeEmpty = false;
+ if (outcomePanel == null) newButton.setEnabled(false);
+ else {
+ saveButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String output;
+ try {
+ output = outcomePanel.getOutcome();
+ int returnVal = chooser.showSaveDialog(null);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File targetFile = chooser.getSelectedFile();
+ if (!(targetFile.getAbsolutePath().endsWith(".xml")))
+ targetFile = new File(targetFile.getAbsolutePath()+".xml");
+
+ Logger.msg(2, "ExecutionPane - Exporting outcome to file " + targetFile.getName());
+ FileStringUtility.string2File(targetFile, output);
+ }
+ } catch (Exception ex) {
+ Logger.error(ex);
+ Logger.exceptionDialog(ex);
+ }
+ }
+ });
+ saveButton.setEnabled(true);
+
+ loadButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ try {
+ int returnVal = chooser.showOpenDialog(null);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File targetFile = chooser.getSelectedFile();
+
+ Logger.msg(2, "ViewpointPane.actionPerformed() - Reading outcome from file " + targetFile.getName());
+ String outcome = FileStringUtility.file2String(targetFile);
+ outcomePanel.setOutcome(outcome);
+ new Thread(outcomePanel).start();
+ }
+ } catch (Exception ex) {
+ Logger.error(ex);
+ Logger.exceptionDialog(ex);
+ }
+ }
+ });
+ loadButton.setEnabled(true);
+ }
+ }
+ }
+ if (outcomeEmpty)
+ outcomeView.add(noOutcome);
+ c.gridy++; c.weighty=1.0;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.BOTH;
+ gridbag.setConstraints(outcomeView, c);
+ add(outcomeView);
+
+ }
+
+ public void init() {
+ if (outcomePanel != null)
+ new Thread(outcomePanel).start();
+ }
+
+ public void execute(Job thisJob) {
+ try{
+ if (thisJob.isOutcomeUsed() && thisJob.getSchemaType().length() > 0)
+ thisJob.setOutcome(outcomePanel.getOutcome());
+ executingJob = thisJob;
+ new Thread(this).start();
+ } catch (OutcomeException ex) {
+ Logger.exceptionDialog(ex);
+ }
+
+ }
+
+ /**
+ * Submits the job to the database
+ */
+ @Override
+ public void run() {
+ Thread.currentThread().setName("Activity Execution");
+ enableAllButtons(false);
+ try {
+ Executor selectedExecutor = (Executor)executors.getSelectedItem();
+ selectedExecutor.execute(executingJob, status);
+ } catch (Exception e) {
+ Logger.error(e);
+ status.setText(Language.translate("Error during execution"));
+ Logger.exceptionDialog(e);
+ }
+ enableAllButtons(true);
+ }
+
+ private void enableAllButtons(boolean enabled) {
+
+ for (RequestButton thisButton : requestButtons) {
+ thisButton.setEnabled(enabled);
+ }
+ }
+
+ public ActivityItem getActivity() {
+ return thisAct;
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/execution/DefaultExecutor.java b/src/main/java/com/c2kernel/gui/tabs/execution/DefaultExecutor.java new file mode 100644 index 0000000..378cc2e --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/execution/DefaultExecutor.java @@ -0,0 +1,35 @@ +package com.c2kernel.gui.tabs.execution;
+
+import javax.swing.JLabel;
+
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.utils.Language;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2003/11/04 14:31:30 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class DefaultExecutor implements Executor {
+
+ public DefaultExecutor() {
+ super();
+ }
+
+ @Override
+ public void execute(Job job, JLabel status) throws Exception {
+ status.setText(Language.translate("Requesting, please wait."));
+ MainFrame.userAgent.execute(job);
+ status.setText(Language.translate("Execution complete. Waiting for joblist update."));
+ }
+
+ @Override
+ public String toString() {
+ return "Normal";
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/execution/Executor.java b/src/main/java/com/c2kernel/gui/tabs/execution/Executor.java new file mode 100644 index 0000000..6fbde17 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/execution/Executor.java @@ -0,0 +1,22 @@ +package com.c2kernel.gui.tabs.execution;
+
+import javax.swing.JLabel;
+
+import com.c2kernel.entity.agent.Job;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2003/09/25 10:28:02 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public interface Executor {
+
+ @Override
+ public String toString();
+
+ public void execute(Job job, JLabel status) throws Exception;
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/execution/RequestButton.java b/src/main/java/com/c2kernel/gui/tabs/execution/RequestButton.java new file mode 100644 index 0000000..e1372a2 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/execution/RequestButton.java @@ -0,0 +1,34 @@ +package com.c2kernel.gui.tabs.execution;
+import java.awt.Color;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+
+import com.c2kernel.entity.agent.Job;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+/**
+ * Each job gets a RequestButton
+ */
+
+ public class RequestButton extends JButton implements ActionListener {
+
+ Job myJob;
+ ActivityViewer parent;
+
+ public RequestButton(Job myJob, ActivityViewer parent) {
+ super();
+ this.myJob = myJob;
+ this.parent = parent;
+ String label = Transitions.getTransitionName(myJob.getPossibleTransition());
+ label = Character.toUpperCase(label.charAt(0))+label.substring(1);
+ if (myJob.isOutcomeUsed()) setBackground(Color.white);
+ super.setText(label);
+ addActionListener(this);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ parent.execute(myJob);
+ }
+ }
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/BasicOutcomeEditor.java b/src/main/java/com/c2kernel/gui/tabs/outcome/BasicOutcomeEditor.java new file mode 100644 index 0000000..5ab5245 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/BasicOutcomeEditor.java @@ -0,0 +1,112 @@ +package com.c2kernel.gui.tabs.outcome;
+
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.io.File;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import javax.swing.text.PlainDocument;
+
+import com.c2kernel.utils.FileStringUtility;
+
+/**************************************************************************
+ *
+ * $Revision: 1.4 $
+ * $Date: 2005/09/07 13:46:31 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+
+public class BasicOutcomeEditor extends JPanel implements OutcomeHandler {
+
+ PlainDocument doc;
+ JTextArea textarea;
+ boolean unsaved;
+
+ public BasicOutcomeEditor() {
+ super();
+ this.setLayout(new GridLayout(1,1));
+ doc = new PlainDocument();
+ textarea = new JTextArea(doc);
+ textarea.setTabSize(2);
+ textarea.setFont(Font.decode("monospaced"));
+ add(new JScrollPane(textarea));
+ doc.addDocumentListener(new DocumentListener() {
+ @Override
+ public void changedUpdate(DocumentEvent e) { unsaved = true; }
+ @Override
+ public void insertUpdate(DocumentEvent e) { unsaved = true; }
+ @Override
+ public void removeUpdate(DocumentEvent e) { unsaved = true; }
+
+ });
+ }
+
+ @Override
+ public void setOutcome(String outcome) throws InvalidOutcomeException {
+ try {
+ doc.insertString(0, outcome, null);
+ unsaved = false;
+ } catch (Exception ex) {
+ throw new InvalidOutcomeException(ex.getMessage());
+ }
+ }
+
+ @Override
+ public void setDescription(String description) throws InvalidSchemaException { }
+
+ @Override
+ public void setReadOnly(boolean readOnly) {
+ textarea.setEditable(!readOnly);
+ }
+
+
+ @Override
+ public JPanel getPanel() throws OutcomeNotInitialisedException {
+ return this;
+ }
+
+ /**
+ *
+ */
+
+ @Override
+ public String getOutcome() throws OutcomeException {
+ try {
+ return doc.getText(0, doc.getLength());
+ } catch (Exception ex) {
+ throw new OutcomeException(ex.getMessage());
+ }
+ }
+
+ /**
+ *
+ */
+
+ @Override
+ public void run() {
+ }
+
+
+ @Override
+ public boolean isUnsaved() {
+ return unsaved;
+ }
+
+ @Override
+ public void saved() {
+ unsaved = false;
+ }
+
+ @Override
+ public void export(File targetFile) throws Exception {
+ FileStringUtility.string2File(targetFile, getOutcome());
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/InvalidOutcomeException.java b/src/main/java/com/c2kernel/gui/tabs/outcome/InvalidOutcomeException.java new file mode 100644 index 0000000..bab9050 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/InvalidOutcomeException.java @@ -0,0 +1,11 @@ +package com.c2kernel.gui.tabs.outcome;
+
+public class InvalidOutcomeException extends OutcomeException {
+
+ public InvalidOutcomeException() {
+ super();
+ }
+ public InvalidOutcomeException(String ex) {
+ super(ex);
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/InvalidSchemaException.java b/src/main/java/com/c2kernel/gui/tabs/outcome/InvalidSchemaException.java new file mode 100644 index 0000000..5edbcbf --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/InvalidSchemaException.java @@ -0,0 +1,11 @@ +package com.c2kernel.gui.tabs.outcome;
+
+public class InvalidSchemaException extends OutcomeException {
+
+ public InvalidSchemaException() {
+ super();
+ }
+ public InvalidSchemaException(String ex) {
+ super(ex);
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/OutcomeException.java b/src/main/java/com/c2kernel/gui/tabs/outcome/OutcomeException.java new file mode 100644 index 0000000..fd608d0 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/OutcomeException.java @@ -0,0 +1,11 @@ +package com.c2kernel.gui.tabs.outcome;
+
+public class OutcomeException extends Exception {
+
+ public OutcomeException() {
+ super();
+ }
+ public OutcomeException(String ex) {
+ super(ex);
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/OutcomeHandler.java b/src/main/java/com/c2kernel/gui/tabs/outcome/OutcomeHandler.java new file mode 100644 index 0000000..0d6dc74 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/OutcomeHandler.java @@ -0,0 +1,16 @@ +package com.c2kernel.gui.tabs.outcome;
+import java.io.File;
+
+import javax.swing.JPanel;
+
+public interface OutcomeHandler extends Runnable {
+
+ public void setOutcome(String outcome) throws InvalidOutcomeException;
+ public void setDescription(String description) throws InvalidSchemaException;
+ public void setReadOnly(boolean readOnly);
+ public JPanel getPanel() throws OutcomeNotInitialisedException;
+ public boolean isUnsaved();
+ public void saved();
+ public String getOutcome() throws OutcomeException;
+ public void export(File targetFile) throws Exception;
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/OutcomeNotInitialisedException.java b/src/main/java/com/c2kernel/gui/tabs/outcome/OutcomeNotInitialisedException.java new file mode 100644 index 0000000..7b54f33 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/OutcomeNotInitialisedException.java @@ -0,0 +1,11 @@ +package com.c2kernel.gui.tabs.outcome;
+
+public class OutcomeNotInitialisedException extends OutcomeException {
+
+ public OutcomeNotInitialisedException() {
+ super();
+ }
+ public OutcomeNotInitialisedException(String ex) {
+ super(ex);
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/AttributeList.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/AttributeList.java new file mode 100644 index 0000000..7d15452 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/AttributeList.java @@ -0,0 +1,160 @@ +package com.c2kernel.gui.tabs.outcome.form;
+
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import org.exolab.castor.xml.schema.AttributeDecl;
+import org.exolab.castor.xml.schema.ComplexType;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+
+import com.c2kernel.gui.tabs.outcome.form.field.StringEditField;
+import com.c2kernel.utils.Logger;
+
+public class AttributeList extends JPanel {
+
+ ArrayList<StringEditField> attrSet = new ArrayList<StringEditField>();
+ ElementDecl model;
+ Element myElement;
+ boolean readOnly;
+ static Font labelFont;
+
+ public AttributeList(ElementDecl model, boolean readOnly, HelpPane helpPane) {
+ super();
+ AttributeDecl thisDecl;
+ this.model = model;
+ this.readOnly = readOnly;
+
+ // set up panel
+ GridBagLayout gridbag = new java.awt.GridBagLayout();
+ setLayout(gridbag);
+ if (labelFont == null)
+ labelFont = this.getFont().deriveFont((float)(this.getFont().getSize()-3.0));
+ // retrieve attributes
+ if (!model.getType().isComplexType()) {
+ // simple types have no attributes
+ return;
+ }
+
+ ComplexType content = (ComplexType)model.getType();
+
+ // place on panel
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = 1.0; c.weighty = 1.0; c.gridx = 0;
+ c.ipadx = 5; c.ipady = 0;
+
+ for (Enumeration<?> fields = content.getAttributeDecls(); fields.hasMoreElements();) {
+ c.gridy = 0;
+ thisDecl = (AttributeDecl)fields.nextElement();
+ Logger.msg(8, "Includes Attribute "+thisDecl.getName());
+
+ // Add Label
+ JLabel heading = new JLabel(thisDecl.getName());
+ heading.setFont(labelFont);
+ heading.setVerticalAlignment(SwingConstants.BOTTOM);
+ gridbag.setConstraints(heading, c);
+ this.add(heading);
+
+ // read help
+ String helpText;
+ String doc = OutcomeStructure.extractHelp(thisDecl);
+ if (doc.length() > 0)
+ helpText = doc.toString();
+ else
+ helpText = "<i>No help is available for this attribute</i>";
+
+
+ c.gridy++;
+
+ // Add entry
+ try {
+ StringEditField entry = StringEditField.getEditField(thisDecl);
+ entry.setHelp(helpPane, helpText);
+ attrSet.add(entry);
+ if (readOnly) entry.setEditable(false);
+ gridbag.setConstraints(entry.getControl(), c);
+ this.add(entry.getControl());
+ } catch (StructuralException e) {
+ JLabel entry = new JLabel("Error");
+ entry.setToolTipText(e.getMessage());
+ gridbag.setConstraints(entry, c);
+ this.add(entry);
+ }
+
+
+ c.gridx++;
+ }
+ }
+
+ public void setInstance(Element data) throws StructuralException {
+ this.myElement = data;
+ for (StringEditField thisField : attrSet) {
+ Logger.msg(8, "Populating Attribute "+thisField.getName());
+ Attr thisAttr = myElement.getAttributeNode(thisField.getName());
+ if (thisAttr == null)
+ thisAttr = newAttribute(myElement, (AttributeDecl)thisField.getModel());
+ thisField.setData(thisAttr);
+ }
+ }
+
+ public Attr newAttribute(Element parent, AttributeDecl attr) {
+
+ parent.setAttribute(attr.getName(), attr.getFixedValue()!=null?attr.getFixedValue():attr.getDefaultValue());
+ return parent.getAttributeNode(attr.getName());
+ }
+
+ public String validateAttributes() {
+ if (model.getType().isComplexType()) {
+ ComplexType content = (ComplexType)model.getType();
+ for (Enumeration<?> fields = content.getAttributeDecls(); fields.hasMoreElements();) {
+ AttributeDecl thisDecl = (AttributeDecl)fields.nextElement();
+ String attrVal = myElement.getAttribute(thisDecl.getName());
+ if (attrVal.length() == 0 && thisDecl.isOptional()) {
+ myElement.removeAttribute(thisDecl.getName());
+ }
+ }
+ }
+ return null;
+ }
+
+ public void initNew(Element parent) {
+ AttributeDecl thisDecl;
+ StringEditField thisField;
+ Attr thisAttr;
+ this.myElement = parent;
+
+ if (model.getType().isSimpleType()) return; // no attributes in simple types
+
+ ComplexType content = (ComplexType)model.getType();
+
+ for (Iterator<StringEditField> e = attrSet.iterator(); e.hasNext();) {
+ thisField = e.next();
+
+ thisDecl = content.getAttributeDecl(thisField.getName());
+ // HACK: if we don't resolve the reference, the type will be null
+ if (thisDecl.isReference()) thisDecl = thisDecl.getReference();
+ thisAttr = newAttribute(myElement, thisDecl);
+ // add into parent - fill in field
+ try {
+ thisField.setData(thisAttr);
+ } catch (Exception ex) { } // impossible name mismatch
+ }
+ }
+ @Override
+ public void grabFocus() {
+ if (attrSet.size() > 0)
+ attrSet.get(0).grabFocus();
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/CardinalException.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/CardinalException.java new file mode 100644 index 0000000..bb6d039 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/CardinalException.java @@ -0,0 +1,14 @@ +package com.c2kernel.gui.tabs.outcome.form;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+
+public class CardinalException extends OutcomeException {
+
+ public CardinalException() {
+ super();
+ }
+
+ public CardinalException(String ex) {
+ super(ex);
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/DataRecord.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/DataRecord.java new file mode 100644 index 0000000..3bfe3fd --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/DataRecord.java @@ -0,0 +1,252 @@ +package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.JLabel;
+import javax.swing.JTabbedPane;
+import javax.swing.SwingUtilities;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.exolab.castor.xml.schema.ComplexType;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.utils.Logger;
+
+public class DataRecord extends OutcomeStructure implements ChangeListener {
+
+ AttributeList myAttributes;
+ JTabbedPane DRPanel = null;
+ boolean deferred;
+ Document parentDoc;
+ GridBagConstraints position;
+ GridBagLayout gridbag;
+
+ public DataRecord(ElementDecl model, boolean readOnly, HelpPane help, boolean deferred) throws OutcomeException {
+ super(model, readOnly, help);
+ this.deferred = deferred;
+ if (!deferred) setupPanel();
+ }
+
+ public synchronized void activate() {
+ deferred = false;
+ try {
+ setupPanel();
+ if (myElement!=null) populateInstance();
+ } catch (OutcomeException ex) {
+ removeAll();
+ setLayout(new FlowLayout());
+ add(new JLabel("Error displaying outcome segment: "+ex.getMessage()));
+ }
+ validate();
+ }
+
+ private void setupPanel() throws OutcomeException {
+ // set up panel
+ gridbag = new java.awt.GridBagLayout();
+ setLayout(gridbag);
+ position = new GridBagConstraints();
+ position.anchor = GridBagConstraints.NORTHWEST;
+ position.fill = GridBagConstraints.NONE;
+ position.weightx = 1.0; position.weighty = 1.0;
+ position.gridx = 0; position.gridy = 0;
+ position.ipadx = 5; position.ipady = 5;
+ position.insets = new Insets(5,5,0,0);
+
+ // attributes at the top
+ myAttributes = new AttributeList(model, readOnly, helpPane);
+ position.gridwidth=3;
+ gridbag.setConstraints(myAttributes, position);
+ add(myAttributes);
+
+ ComplexType elementType;
+ try {
+ elementType = (ComplexType)model.getType();
+ }
+ catch (ClassCastException e) {
+ throw new StructuralException("DataRecord created with non-ComplexType");
+ }
+
+ //loop through all schema sub-elements
+ try {
+ enumerateElements(elementType);
+ } catch (OutcomeException e) {
+ throw new OutcomeException("Element "+model.getName()+" could not be created: "+e.getMessage());
+ }
+ }
+
+ @Override
+ public void addStructure(OutcomeStructure newElement) throws OutcomeException {
+ super.addStructure(newElement);
+ if (newElement == null) return;
+ if (newElement instanceof DataRecord) {
+ DataRecord newRecord = (DataRecord)newElement;
+ // set up enclosing tabbed pane for child drs
+ if (DRPanel == null) {
+ DRPanel = new JTabbedPane();
+ position.gridy++;
+ position.weightx=1.0;
+ position.fill=GridBagConstraints.HORIZONTAL;
+ position.gridwidth=3;
+ gridbag.setConstraints(DRPanel, position);
+ add(DRPanel);
+ // defer further tabs in this pane
+ deferChild = true;
+ }
+ DRPanel.addTab(newRecord.getName(), newRecord);
+ DRPanel.addChangeListener(newRecord);
+ }
+ else {
+ DRPanel = null;// have to make a new tabbed pane now
+ deferChild = false;
+ if (newElement instanceof Field) {
+ Field newField = (Field)newElement;
+ // make some nice columns
+ position.gridwidth=1;
+ position.gridy++;
+ position.gridx=0;
+ position.weightx=2;
+ position.weighty=0;
+ position.fill=GridBagConstraints.NONE;
+ gridbag.setConstraints(newField.getLabel(), position);
+ this.add(newField.getLabel());
+ position.gridy++;
+ position.weighty=1;
+ position.fill = GridBagConstraints.HORIZONTAL;
+ gridbag.setConstraints(newField.getCData(), position);
+ this.add(newField.getCData());
+ position.gridx++;
+ position.gridy--;
+ position.gridheight=2;
+ position.weightx=0;
+ position.fill=GridBagConstraints.NONE;
+ gridbag.setConstraints(newField.getAttributes(), position);
+ this.add(newField.getAttributes());
+ position.gridx=0;
+ position.gridheight=1;
+ position.gridy++;
+ }
+ else {
+ position.fill=GridBagConstraints.HORIZONTAL;
+ position.gridwidth=3;
+ position.weightx=1.0;
+ position.gridy++;
+ position.weighty=1.0;
+ gridbag.setConstraints(newElement, position);
+ add(newElement);
+ }
+ }
+ }
+
+ @Override
+ public void addInstance(Element myElement, Document parentDoc) throws OutcomeException {
+ Logger.msg(8, "Accepting DR "+myElement.getTagName());
+
+ if (this.myElement != null) throw new CardinalException("DataRecord "+this.getName()+" cannot repeat.");
+ this.myElement = myElement;
+ this.parentDoc = parentDoc;
+
+ if (!deferred)
+ populateInstance();
+ }
+
+ public void populateInstance() throws OutcomeException {
+ myAttributes.setInstance(myElement);
+
+ NodeList childElements = myElement.getChildNodes();
+
+ for (int i=0; i<childElements.getLength();i++) {
+ if (!(childElements.item(i) instanceof Element)) // ignore chardata here
+ continue;
+ Element thisElement = (Element) childElements.item(i);
+
+ // find the child structure with this name
+ OutcomeStructure thisStructure = subStructure.get(thisElement.getTagName());
+ if (thisStructure == null)
+ throw new StructuralException("DR "+model.getName()+" not expecting "+thisElement.getTagName());
+ thisStructure.addInstance(thisElement, parentDoc);
+ }
+
+ // make sure any dimensions have the minimum
+ for (Object name2 : subStructure.keySet()) {
+ String structureName = (String)name2;
+ OutcomeStructure thisStructure = subStructure.get(structureName);
+ int count = 0;
+
+ if (thisStructure instanceof Dimension) {
+ Dimension thisDimension = (Dimension)thisStructure;
+ thisDimension.setParentElement(myElement);
+ count = thisDimension.getChildCount();
+ }
+ else
+ count = thisStructure.getElement()==null?0:1;
+
+ int total = thisStructure.getModel().getMinOccurs();
+ //if (total == 0) total++;
+ for (int i = count;i<total;i++) {
+ myElement.appendChild(thisStructure.initNew(parentDoc));
+ }
+ }
+ }
+
+ @Override
+ public Element initNew(Document parent) {
+ Logger.msg(6, "Creating DR "+model.getName());
+ if (deferred) activate();
+
+ // make a new Element
+ myElement = parent.createElement(model.getName());
+ // populate
+ for (Object name2 : order) {
+ String structureName = (String)name2;
+ OutcomeStructure thisStructure = subStructure.get(structureName);
+ if (thisStructure instanceof Dimension)
+ ((Dimension)thisStructure).setParentElement(myElement);
+ int count = 0;
+ while (count < thisStructure.getModel().getMinOccurs()) {
+ myElement.appendChild(thisStructure.initNew(parent));
+ count++;
+ }
+ }
+
+ // set up attributes
+ myAttributes.initNew(myElement);
+
+ return myElement;
+
+ }
+
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ JTabbedPane targetPane = (JTabbedPane)e.getSource();
+ DataRecord targetTab = (DataRecord)targetPane.getSelectedComponent();
+ if (targetTab == this) {
+ helpPane.setHelp(getName(), getHelp());
+ if (deferred) SwingUtilities.invokeLater(
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ activate();
+ }
+ }
+ ));
+ }
+ }
+
+ /**
+ * sets focus to first editable child
+ */
+ @Override
+ public void grabFocus() {
+ if (myAttributes.attrSet.size() > 0)
+ myAttributes.grabFocus();
+ else if (order.size()> 0)
+ subStructure.get(order.get(0)).grabFocus();
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/Dimension.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/Dimension.java new file mode 100644 index 0000000..c91c5df --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/Dimension.java @@ -0,0 +1,395 @@ +package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import javax.swing.BorderFactory;
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.border.EtchedBorder;
+import javax.swing.table.JTableHeader;
+
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Particle;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.c2kernel.gui.DomainKeyConsumer;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.utils.Logger;
+
+public class Dimension extends OutcomeStructure implements ActionListener {
+
+ DimensionTableModel tableModel;
+ Element parent;
+ GridBagConstraints position;
+ GridBagLayout gridbag;
+ JTabbedPane tabs;
+ JLabel msg;
+ DomKeyPushTable table;
+ Box tableBox;
+ ArrayList<DimensionInstance> instances = new ArrayList<DimensionInstance>(); // stores DimensionInstances if tabs
+ ArrayList<Element> elements = new ArrayList<Element>(); // stores current children
+
+ JButton addButton;
+ JButton delButton;
+
+ short mode;
+ protected static final short TABLE = 1;
+ protected static final short TABS = 2;
+
+
+ public Dimension(ElementDecl model, boolean readOnly, HelpPane help) {
+ super(model, readOnly, help);
+ // set up panel
+ gridbag = new java.awt.GridBagLayout();
+ setLayout(gridbag);
+ position = new GridBagConstraints();
+ position.anchor = GridBagConstraints.NORTHWEST;
+ position.fill = GridBagConstraints.HORIZONTAL;
+ position.weightx = 1.0; position.weighty = 0.0;
+ position.gridx = 0; position.gridy = 0;
+ position.ipadx = 0; position.ipady = 0;
+ position.insets = new Insets(0,0,0,0);
+
+ // TODO: an element or attribute of the dimension can be flagged as an index, so it can be used as a title for a tab
+
+ // set up the border
+ setBorder(BorderFactory.createTitledBorder(
+ BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), model.getName()));
+
+ msg = new JLabel("No elements");
+ msg.setFont(new Font("SansSerif", Font.ITALIC, msg.getFont().getSize()));
+ gridbag.setConstraints(msg, position);
+ add(msg);
+ position.gridy++;
+
+ // decide whether a table or tabs
+ try {
+ tableModel = new DimensionTableModel(model, readOnly);
+ Logger.msg(8, "DIM "+model.getName()+" - Will be a table");
+ mode = TABLE;
+ tableBox = Box.createVerticalBox();
+ table = new DomKeyPushTable(tableModel, this);
+ new MultiLinePasteAdapter(table, this);
+ if (readOnly) table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
+ table.setColumnSelectionAllowed(readOnly);
+ JTableHeader tableHeader = table.getTableHeader();
+ tableHeader.setReorderingAllowed(false);
+ tableBox.add(tableHeader);
+ tableBox.add(table);
+ gridbag.setConstraints(tableBox, position);
+ add(tableBox);
+ tableBox.setVisible(false);
+
+ } catch (StructuralException e) {
+ // use tabs
+ Logger.msg(8, "DIM "+model.getName()+" - Will be tabs: "+e.getMessage());
+ mode = TABS;
+ tabs = new JTabbedPane();
+ gridbag.setConstraints(tabs, position);
+ add(tabs);
+ tabs.setVisible(false);
+ }
+ if (!readOnly) {
+ JPanel rowAdjust = new JPanel(new FlowLayout());
+ addButton = new JButton("+");
+ addButton.setActionCommand("add");
+ addButton.addActionListener(this);
+ rowAdjust.add(addButton);
+
+ delButton = new JButton("-");
+ delButton.setActionCommand("del");
+ delButton.addActionListener(this);
+ delButton.setEnabled(false);
+ rowAdjust.add(delButton);
+
+
+ position.gridy++; position.weighty=0; position.weightx=0;
+ gridbag.setConstraints(rowAdjust, position);
+ this.add(rowAdjust);
+ }
+
+ }
+
+ public void setParentElement(Element parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public void addInstance(Element myElement, Document parentDoc) throws OutcomeException {
+ if (Logger.doLog(6))
+ Logger.msg(6, "DIM - adding instance "+ (elements.size()+1) +" for "+myElement.getTagName());
+ if (parent == null) setParentElement((Element)myElement.getParentNode());
+ // if table, pass to table model
+ if (mode == TABLE) {
+ tableModel.addInstance(myElement, -1);
+ elements.add(myElement);
+ }
+ else {
+ DimensionInstance target;
+ elements.add(myElement);
+ if (instances.size() < elements.size())
+ target = newInstance();
+ else
+ target = instances.get(elements.size()-1);
+ target.addInstance(myElement, parentDoc);
+ }
+ checkButtons();
+ }
+
+ public int getChildCount() {
+ return elements.size();
+ }
+
+ public DimensionInstance newInstance() {
+ DimensionInstance newInstance = null;
+ try {
+ newInstance = new DimensionInstance(model, readOnly, helpPane, deferChild);
+ instances.add(newInstance);
+ newInstance.setTabNumber(instances.size());
+ newInstance.setParent(this);
+ deferChild = true;
+ tabs.addTab(newInstance.getName(), newInstance);
+ tabs.addChangeListener(newInstance);
+ } catch (OutcomeException e) {
+ // shouldn't happen, we've already done it once
+ Logger.error(e);
+ }
+ return newInstance;
+ }
+
+ @Override
+ public String validateStructure() {
+ if (mode == TABLE)
+ return table.validateStructure();
+ else {
+ StringBuffer errors = new StringBuffer();
+ for (Iterator<DimensionInstance> iter = instances.iterator(); iter.hasNext();) {
+ OutcomeStructure element = iter.next();
+ errors.append(element.validateStructure());
+ }
+ return errors.toString();
+ }
+ }
+
+ public void checkButtons() {
+ // check if data visible
+ boolean dataVisible = elements.size() > 0;
+ if (mode == TABS) tabs.setVisible(dataVisible);
+ else tableBox.setVisible(dataVisible);
+ msg.setVisible(!dataVisible);
+
+ if (readOnly) return;
+
+ if (elements.size() <= model.getMinOccurs() || elements.size() == 0) {
+ delButton.setEnabled(false);
+ delButton.setToolTipText("Minimum row count of "+model.getMinOccurs()+" reached.");
+ } else {
+ delButton.setEnabled(true);
+ delButton.setToolTipText(null);
+ }
+
+ if (elements.size() < model.getMaxOccurs() || model.getMaxOccurs() == Particle.UNBOUNDED) {
+ addButton.setEnabled(true);
+ addButton.setToolTipText(null);
+ } else {
+ addButton.setEnabled(false);
+ addButton.setToolTipText("Maximum row count of "+model.getMaxOccurs()+" reached.");
+ }
+ }
+
+ @Override
+ public Element initNew(Document parent) {
+ Element newElement;
+
+ if (mode == TABLE) {
+ newElement = tableModel.initNew(parent, -1);
+ elements.add(newElement);
+ checkButtons();
+ return newElement;
+ }
+ else {
+ DimensionInstance newTab = null;
+ if (instances.size() < elements.size()+1)
+ newTab = newInstance();
+ else
+ newTab = instances.get(elements.size()-1);
+ newElement = newTab.initNew(parent);
+ elements.add(newElement);
+ checkButtons();
+ return newElement;
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ int index;
+ if (mode == TABS) index = tabs.getSelectedIndex();
+ else {
+ index = table.getSelectedRow();
+ if (index == -1) index = tableModel.getRowCount();
+ }
+ try {
+ if (table == null || table.getCellEditor() == null || table.getCellEditor().stopCellEditing()) {
+ if (e.getActionCommand().equals("add"))
+ addRow(index);
+ else if (e.getActionCommand().equals("del"))
+ removeRow(index);
+ }
+ } catch (CardinalException ex) {
+ JOptionPane.showMessageDialog(null, ex.getMessage(), "Table error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ public void addRow(int index) throws CardinalException {
+ if (elements.size() == model.getMaxOccurs())
+ throw new CardinalException("Maximum size of table reached");
+
+ if (mode == TABLE) {
+ Element newRow = tableModel.initNew(parent.getOwnerDocument(), index);
+ elements.add(index, newRow);
+ try {
+ Element following = elements.get(index+1);
+ parent.insertBefore(newRow, following);
+ } catch (IndexOutOfBoundsException ex) {
+ parent.appendChild(newRow);
+ }
+ table.clearSelection();
+ table.setRowSelectionInterval(index, index);
+ }
+ else {
+ Element newTab = initNew(parent.getOwnerDocument());
+ parent.appendChild(newTab);
+ }
+ checkButtons();
+
+ }
+
+ public void removeRow(int index) throws CardinalException {
+ if (elements.size() <= model.getMinOccurs())
+ throw new CardinalException("Minimum size of table reached");
+ if (mode == TABLE) {
+ parent.removeChild(tableModel.removeRow(index));
+ int selectRow = index;
+ if (index >= tableModel.getRowCount()) selectRow--;
+ if (tableModel.getRowCount() > 0) {
+ table.clearSelection();
+ table.setRowSelectionInterval(selectRow, selectRow);
+ }
+ }
+ else {
+ Element elementToGo = elements.get(index);
+ parent.removeChild(elementToGo);
+ instances.remove(index);
+ tabs.remove(index);
+ for (int i = index; i<instances.size(); i++) {
+ DimensionInstance thisInstance = instances.get(i);
+ thisInstance.setTabNumber(i+1);
+ tabs.setTitleAt(i, thisInstance.getName());
+ }
+ }
+ elements.remove(index);
+ checkButtons();
+ }
+
+ private class DomKeyPushTable extends JTable implements DomainKeyConsumer, FocusListener {
+
+ Dimension dim;
+ public DomKeyPushTable(DimensionTableModel model, Dimension parent) {
+ super(model);
+ addFocusListener(this);
+ this.dim = parent;
+ }
+
+ @Override
+ public void push(DomainPath key) {
+ push(key.getName());
+ }
+
+ @Override
+ public void push(String name) {
+ int col = getSelectedColumn();
+ int row = getSelectedRow();
+ if (cellEditor != null)
+ cellEditor.stopCellEditing();
+ Logger.msg(8, "Pushing "+name+" to table at "+row+","+col);
+ if (col > -1 && row > -1) {
+ if (dataModel.getValueAt(row, col).toString().length()==0)
+ dataModel.setValueAt(name, row, col);
+ else {
+ if (row+1 == getRowCount()) {
+ try {
+ dim.addRow(row+1);
+ dataModel.setValueAt(name, row+1, col);
+ } catch (CardinalException ex) {
+ JOptionPane.showMessageDialog(null, ex.getMessage(), "Table error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ if (row+1 < getRowCount()) {
+ Logger.msg(8, "Shifting selection to row "+(row+1));
+ changeSelection(row+1, col, false, false);
+ }
+ }
+ }
+
+ @Override
+ public void focusGained(FocusEvent e) {
+ if (!readOnly)
+ MainFrame.itemFinder.setConsumer(this, "Insert");
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ // release the itemFinder
+ if (!readOnly)
+ MainFrame.itemFinder.clearConsumer(this);
+ }
+
+ public String validateStructure() {
+ if (cellEditor != null)
+ cellEditor.stopCellEditing();
+ return null;
+ }
+
+ @Override
+ public void changeSelection( int rowIndex, int columnIndex, boolean toggle, boolean extend) {
+ super.changeSelection(rowIndex, columnIndex, toggle, extend);
+ DimensionTableModel dimModel = (DimensionTableModel)dataModel;
+ helpPane.setHelp(dimModel.getColumnName(columnIndex), dimModel.getHelp(columnIndex));
+ }
+
+ }
+
+ @Override
+ public void grabFocus() {
+ if (mode == TABLE) {
+ if (table.getSelectedRow() == -1 && table.getRowCount() > 0) {
+ table.changeSelection(0, 0, false, false);
+ table.editCellAt(0,0);
+ }
+ table.requestFocus();
+ }
+ else if (instances.size()> 0)
+ instances.get(0).grabFocus();
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/DimensionInstance.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/DimensionInstance.java new file mode 100644 index 0000000..649886b --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/DimensionInstance.java @@ -0,0 +1,33 @@ +package com.c2kernel.gui.tabs.outcome.form;
+import org.exolab.castor.xml.schema.ElementDecl;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+
+public class DimensionInstance extends DataRecord {
+
+ //probably will be needed to synch edits later
+ Dimension parentDimension;
+ int tabNumber;
+ String tabName = null;
+
+ public DimensionInstance(ElementDecl model, boolean readOnly , HelpPane help, boolean deferred) throws OutcomeException {
+ super(model, readOnly, help, deferred);
+ }
+
+ public void setTabNumber(int tabNumber) {
+ this.tabNumber=tabNumber;
+ }
+
+ public void setParent(Dimension parent) {
+ this.parentDimension = parent;
+ }
+
+ @Override
+ public String getName() {
+ //TODO appinfo for picking out attributes or child elements for tab name
+ if (tabName == null)
+ return Integer.toString(tabNumber);
+ else
+ return tabName;
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/DimensionTableModel.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/DimensionTableModel.java new file mode 100644 index 0000000..ac6a9f2 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/DimensionTableModel.java @@ -0,0 +1,332 @@ +package com.c2kernel.gui.tabs.outcome.form;
+import java.util.ArrayList;
+import java.util.Enumeration;
+
+import javax.swing.table.AbstractTableModel;
+
+import org.exolab.castor.xml.schema.Annotated;
+import org.exolab.castor.xml.schema.AttributeDecl;
+import org.exolab.castor.xml.schema.ComplexType;
+import org.exolab.castor.xml.schema.ContentModelGroup;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Group;
+import org.exolab.castor.xml.schema.Order;
+import org.exolab.castor.xml.schema.Particle;
+import org.exolab.castor.xml.schema.SimpleType;
+import org.exolab.castor.xml.schema.SimpleTypesFactory;
+import org.exolab.castor.xml.schema.XMLType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+public class DimensionTableModel extends AbstractTableModel {
+
+ ElementDecl model;
+ ArrayList<String> columnHeadings = new ArrayList<String>();
+ ArrayList<Class<?>> columnClasses = new ArrayList<Class<?>>();
+ ArrayList<Annotated> columnDecls = new ArrayList<Annotated>();
+ ArrayList<Boolean> colReadOnly = new ArrayList<Boolean>();
+ ArrayList<String> colHelp = new ArrayList<String>();
+ ArrayList<Object[]> rows = new ArrayList<Object[]>();
+ ArrayList<Element> elements = new ArrayList<Element>();
+ boolean readOnly;
+
+ public DimensionTableModel(ElementDecl model, boolean readOnly) throws StructuralException {
+ XMLType modelContent = model.getType();
+ this.model = model;
+ this.readOnly = readOnly;
+ // use text node for simple types
+ if (modelContent.isSimpleType()) {
+ SimpleType elementType = (SimpleType)modelContent;
+ SimpleType baseType = elementType.getBuiltInBaseType();
+ addColumn(model.getName(), baseType, baseType.getTypeCode(), new Boolean(model.getFixedValue() != null));
+ }
+ else if (modelContent.isComplexType()) { // if complex type, process child elements
+ ComplexType elementType = (ComplexType)modelContent;
+
+ // find out if a CDATA type is used for this complex type
+ XMLType baseType = elementType.getBaseType();
+ while (!(baseType instanceof SimpleType) && baseType != null) {
+ baseType = baseType.getBaseType();
+ }
+ if (baseType != null) {
+ int typeCode = ((SimpleType)baseType).getTypeCode();
+ addColumn(model.getName(), baseType, typeCode, new Boolean(model.getFixedValue() != null));
+ }
+ // process attributes
+ for (Enumeration<?> e = elementType.getAttributeDecls(); e.hasMoreElements();) {
+ AttributeDecl thisAttr = (AttributeDecl)e.nextElement();
+ // HACK: if we don't resolve the reference, the type will be null
+ if (thisAttr.isReference()) thisAttr = thisAttr.getReference();
+ if (thisAttr.getSimpleType() == null)
+ throw new StructuralException("Attribute "+thisAttr.getName()+" in "+model.getName()+" has no type");
+ addColumn(thisAttr.getName(), thisAttr, thisAttr.getSimpleType().getTypeCode(), new Boolean(thisAttr.isFixed()));
+ }
+
+ // enumerate child elements
+ enumerateElements(elementType);
+ }
+ }
+
+ public synchronized void addColumn(String heading, Annotated decl, int typeCode, Boolean readOnly) {
+ Logger.msg(8, "Column "+heading+" contains "+decl.getClass().getName()+" readOnly="+readOnly.toString());
+ columnHeadings.add(heading);
+ columnDecls.add(decl);
+ columnClasses.add(OutcomeStructure.getJavaClass(typeCode));
+ colReadOnly.add(readOnly);
+
+ // read help
+ String helpText;
+ if (decl instanceof SimpleType)
+ helpText = OutcomeStructure.extractHelp(model);
+ else
+ helpText = OutcomeStructure.extractHelp(decl);
+
+ if (helpText.length() == 0)
+ helpText = "<i>"+Language.translate("No help is available for this cell")+"</i>";
+
+ colHelp.add(helpText);
+
+ }
+
+
+ public void enumerateElements(ContentModelGroup group) throws StructuralException {
+ for (Enumeration<?> childElements = group.enumerate(); childElements.hasMoreElements(); ) {
+ Particle thisParticle = (Particle)childElements.nextElement();
+ String extraHeader = "";
+ if (thisParticle instanceof Group) {
+ Group thisGroup = (Group)thisParticle;
+ Order order = thisGroup.getOrder();
+ if (order == Order.sequence || order == Order.all)
+ enumerateElements(thisGroup);
+ else // we only support sequences in data structures such as these
+ throw new StructuralException("Element "+thisGroup.getName()+". Expecting sequence or all. Got "+thisGroup.getOrder());
+ }
+ else if (thisParticle instanceof ElementDecl) {
+ ElementDecl thisElement = (ElementDecl)thisParticle;
+ int typeCode = SimpleTypesFactory.INVALID_TYPE;
+ //make sure not too complex
+ if (thisElement.getType() != null) {
+ if (thisElement.getType().isComplexType()) {
+ ComplexType elementType = (ComplexType)thisElement.getType();
+ if (elementType.getParticleCount() > 0 ||
+ thisElement.getMaxOccurs() > 1)
+ throw new StructuralException("Too deep for a table");
+ for (Enumeration<?> attrs = elementType.getAttributeDecls(); attrs.hasMoreElements();) {
+ AttributeDecl thisAttr = (AttributeDecl)attrs.nextElement();
+ if (!thisAttr.isFixed())
+ throw new StructuralException("Non-fixed attributes of child elements not supported in tables.");
+ else
+ extraHeader=extraHeader+" ("+thisAttr.getName()+":"+(thisAttr.getFixedValue()!=null?thisAttr.getFixedValue():thisAttr.getDefaultValue())+")";
+ }
+ // find type
+ XMLType parentType = thisElement.getType();
+ while (!(parentType instanceof SimpleType) && parentType != null) {
+ parentType = parentType.getBaseType();
+ if (parentType != null) typeCode = ((SimpleType)parentType).getTypeCode();
+ }
+ }
+ else
+ typeCode = ((SimpleType)thisElement.getType()).getTypeCode();
+ }
+
+ //add to list
+ addColumn(thisElement.getName()+extraHeader, thisElement, typeCode, new Boolean(thisElement.getFixedValue() != null));
+ }
+ else throw new StructuralException("Particle "+thisParticle.getClass()+" not implemented");
+ }
+ }
+
+ public void addInstance(Element myElement, int index) throws OutcomeException {
+ if (index == -1) index = elements.size();
+ Object[] newRow = new Object[columnHeadings.size()];
+ for (int i=0; i<columnDecls.size(); i++) {
+ if (columnDecls.get(i) instanceof ElementDecl) { // sub element - get the node from it
+ ElementDecl thisElementDecl = (ElementDecl)columnDecls.get(i);
+ NodeList childElements = myElement.getElementsByTagName(thisElementDecl.getName());
+ switch (childElements.getLength()) {
+ case 1: // element exists - read the contents
+ Element childElement = (Element)childElements.item(0);
+ if (childElement.hasChildNodes()) {
+ Node thisNode = childElement.getFirstChild();
+ if (thisNode.getNodeType() == Node.TEXT_NODE)
+ newRow[i] = OutcomeStructure.getTypedValue(((Text)thisNode).getData(), columnClasses.get(i));
+ else
+ throw new StructuralException("First child of Field " + thisElementDecl.getName() + " was not Text. (NodeType:"+thisNode.getNodeType()+")");
+ }
+ else { // create text node
+ newRow[i] = this.setupDefaultElement(thisElementDecl, childElement, columnClasses.get(i));
+ }
+ break;
+ case 0: // element is missing - create it
+ Element newElement = myElement.getOwnerDocument().createElement(thisElementDecl.getName());
+ myElement.appendChild(newElement); //TODO: not in the right place in sequence. should insert it
+ newRow[i] = setupDefaultElement(thisElementDecl, newElement, columnClasses.get(i));
+ break;
+ default:
+ throw new CardinalException("Element "+thisElementDecl.getName()+" appeared more than once.");
+ }
+ }
+ else if (columnDecls.get(i) instanceof AttributeDecl) { //attribute
+ AttributeDecl thisAttrDecl = (AttributeDecl)columnDecls.get(i);
+ newRow[i] = OutcomeStructure.getTypedValue(myElement.getAttribute(thisAttrDecl.getName()), columnClasses.get(i));
+ }
+ else { // first child node
+ Node thisNode = myElement.getFirstChild();
+ if (thisNode == null) {
+ thisNode = myElement.getOwnerDocument().createTextNode("");
+ myElement.appendChild(thisNode);
+ }
+ if (thisNode.getNodeType() == Node.TEXT_NODE || thisNode.getNodeType() == Node.CDATA_SECTION_NODE)
+ newRow[i] = OutcomeStructure.getTypedValue(((Text)thisNode).getData(), columnClasses.get(i));
+ else
+ throw new StructuralException("First child of Column " + myElement.getTagName() + " was not Text");
+ }
+ }
+ elements.add(index, myElement);
+ rows.add(index, newRow);
+ fireTableRowsInserted(index, index);
+ }
+ @Override
+ public Class<?> getColumnClass(int columnIndex) {
+ return columnClasses.get(columnIndex);
+ }
+
+ @Override
+ public String getColumnName(int columnIndex) {
+ return columnHeadings.get(columnIndex);
+ }
+
+ @Override
+ public int getRowCount() {
+ return rows.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return columnHeadings.size();
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ boolean isReadOnly = readOnly || colReadOnly.get(columnIndex).booleanValue();
+ return !isReadOnly;
+ }
+
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ Object[] thisRow = rows.get(rowIndex);
+ thisRow[columnIndex]=aValue;
+ Element myElement = elements.get(rowIndex);
+ // update node
+ if (columnDecls.get(columnIndex) instanceof ElementDecl) { // sub element
+ ElementDecl thisDecl = (ElementDecl)columnDecls.get(columnIndex);
+ NodeList childElements = myElement.getElementsByTagName(thisDecl.getName());
+ // depend on one element with a Text child - this should have been enforced on init.
+ Text childNode = (Text)(childElements.item(0).getFirstChild());
+ childNode.setData(aValue.toString());
+ }
+ else if (columnDecls.get(columnIndex) instanceof AttributeDecl) { //attribute
+ AttributeDecl thisDecl = (AttributeDecl) columnDecls.get(columnIndex);
+ myElement.setAttribute(thisDecl.getName(), aValue.toString());
+ }
+ else { // first child node
+ Text textNode = (Text)myElement.getFirstChild();
+ textNode.setData(aValue.toString());
+ }
+ fireTableCellUpdated(rowIndex, columnIndex);
+ }
+
+ public Element removeRow(int rowIndex) {
+ Element elementToGo = elements.get(rowIndex);
+ elements.remove(rowIndex);
+ rows.remove(rowIndex);
+ fireTableRowsDeleted(rowIndex,rowIndex);
+ return elementToGo;
+ }
+
+ public Object setupDefaultElement(ElementDecl thisDecl, Element parent, Class<?> type) {
+ Object newValue;
+ String defaultValue = thisDecl.getFixedValue();
+ if (defaultValue == null)
+ defaultValue = thisDecl.getDefaultValue();
+ if (readOnly)
+ newValue = "";
+ else
+ newValue = OutcomeStructure.getTypedValue(defaultValue, type);
+
+ Text newNode = parent.getOwnerDocument().createTextNode(newValue.toString());
+ parent.appendChild(newNode);
+ // fixed attributes
+ try {
+ ComplexType content = (ComplexType)thisDecl.getType();
+ for (Enumeration<?> attrs = content.getAttributeDecls(); attrs.hasMoreElements();) {
+ AttributeDecl thisAttr = (AttributeDecl)attrs.nextElement();
+ parent.setAttribute(thisAttr.getName(), thisAttr.getFixedValue()!=null?thisAttr.getFixedValue():thisAttr.getDefaultValue());
+ }
+ } catch (ClassCastException ex) { } // only complex types have attributes
+ return newValue;
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ Object[] thisRow = rows.get(rowIndex);
+ if (!(getColumnClass(columnIndex).equals(thisRow[columnIndex].getClass())))
+ Logger.warning(thisRow[columnIndex]+" should be "+getColumnClass(columnIndex)+" is a "+thisRow[columnIndex].getClass().getName());
+ return thisRow[columnIndex];
+ }
+
+ public String validateStructure() { // remove empty rows
+ for (int j=0; j < rows.size(); j++) {
+ Object[] elems = rows.get(j);
+ boolean empty = true;
+ for (int i = 0; i < elems.length && empty; i++)
+ empty &= OutcomeStructure.isEmpty(elems[i]);
+ if (empty)
+ if (model.getMinOccurs() < rows.size())
+ removeRow(j);
+ else
+ return "Too many empty rows in table "+model.getName();
+ }
+ return null;
+ }
+
+ public Element initNew(Document parent, int index) {
+ if (index == -1) index = elements.size();
+ Object[] newRow = new Object[columnHeadings.size()];
+ Element myElement = parent.createElement(model.getName());
+ for (int i=0; i<columnDecls.size(); i++) {
+ if (columnDecls.get(i) instanceof ElementDecl) { // sub element
+ ElementDecl childElementDecl = (ElementDecl)columnDecls.get(i);
+ Element childElement = parent.createElement(childElementDecl.getName());
+ Object newValue = setupDefaultElement(childElementDecl, childElement, columnClasses.get(i));
+ myElement.appendChild(childElement);
+ newRow[i] = newValue;
+ }
+ else if (columnDecls.get(i) instanceof AttributeDecl) { //attribute
+ AttributeDecl thisAttrDecl = (AttributeDecl)columnDecls.get(i);
+ String newValue = thisAttrDecl.getFixedValue()!=null?thisAttrDecl.getFixedValue():thisAttrDecl.getDefaultValue();
+ newRow[i] = OutcomeStructure.getTypedValue(newValue, columnClasses.get(i));
+ myElement.setAttribute(thisAttrDecl.getName(), newRow[i].toString());
+ }
+ else { // first child node
+ newRow[i] = setupDefaultElement(model, myElement, columnClasses.get(i));
+ }
+ }
+ elements.add(index,myElement);
+ rows.add(index, newRow);
+ fireTableRowsInserted(index,index);
+ return myElement;
+ }
+
+ public String getHelp(int i) {
+ return colHelp.get(i);
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/Field.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/Field.java new file mode 100644 index 0000000..9d21c97 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/Field.java @@ -0,0 +1,142 @@ +package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.Component;
+
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.SwingConstants;
+
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.form.field.StringEditField;
+import com.c2kernel.utils.Logger;
+
+
+public class Field extends OutcomeStructure {
+
+ StringEditField myElementPanel = null;
+ AttributeList myAttributes;
+ JLabel tagName;
+ Text textNode;
+ boolean fixed;
+ public static final JPanel nullPanel = new JPanel();
+
+ public Field(ElementDecl model, boolean readOnly, HelpPane helpPane) {
+ super(model, readOnly, helpPane);
+
+ try {
+ myElementPanel = StringEditField.getEditField(model);
+ Logger.msg(6, "Field type: "+myElementPanel.getClass().getName());
+ myElementPanel.setHelp(helpPane, help);
+ if (readOnly) myElementPanel.setEditable(false);
+
+ } catch (StructuralException e) { // no base type for field - only attributes
+ myElementPanel = null;
+ }
+
+ myAttributes = new AttributeList(model, readOnly, helpPane);
+
+ tagName = new JLabel(model.getName());
+ tagName.setVerticalAlignment(SwingConstants.BOTTOM);
+ }
+
+ public JComponent getLabel() {
+ return tagName;
+ }
+
+ public Component getCData() {
+ if (myElementPanel == null)
+ return nullPanel;
+ return myElementPanel.getControl();
+ }
+
+ public JComponent getAttributes() {
+ return myAttributes;
+ }
+
+ @Override
+ public void addStructure(OutcomeStructure newElement) throws StructuralException {
+ throw new StructuralException("Field "+model.getName()+" cannot have child structures");
+ }
+
+ @Override
+ public void addInstance(Element myElement, Document parentDoc) throws OutcomeException {
+ Logger.msg(6, "Accepting Field "+myElement.getTagName());
+ if (this.myElement != null) throw new CardinalException("Field "+this.getName()+" cannot repeat");
+ this.myElement = myElement;
+
+ try {
+ if (myElementPanel == null)
+ Logger.error("Field should be empty. Discarding contents.");
+ else {
+ if (myElement.hasChildNodes())
+ textNode = (Text)myElement.getFirstChild();
+ else {
+ textNode = parentDoc.createTextNode(getDefaultValue());
+ myElement.appendChild(textNode);
+ }
+
+ myElementPanel.setData(textNode);
+ }
+ } catch (ClassCastException ex) {
+ throw new StructuralException("First child node of Field " + this.getName() + " was not Text: "+myElement.getFirstChild().getNodeType());
+ }
+ myAttributes.setInstance(myElement);
+ }
+
+ // check if valid
+
+ @Override
+ public String validateStructure() {
+ myAttributes.validateAttributes();
+ if (myElementPanel != null) myElementPanel.updateNode();
+ Text contents = (Text)myElement.getFirstChild();
+ if (!myElement.hasAttributes() && model.getMinOccurs() < 1 &&
+ (contents == null || contents.getData().length() == 0))
+ // empty - should remove if optional
+ myElement.getParentNode().removeChild(myElement);
+ return null;
+ }
+
+ @Override
+ public Element initNew(Document parent) {
+ Logger.msg(6, "Creating Field "+this.getName());
+
+ // make a new Element
+ myElement = parent.createElement(this.getName());
+
+ // see if there is a default/fixed value
+ if (myElementPanel != null) {
+ // populate
+ String defaultVal = readOnly?"":getDefaultValue();
+ textNode = parent.createTextNode(defaultVal);
+ myElement.appendChild(textNode);
+ myElementPanel.setData(textNode);
+ }
+
+ // set up attributes
+ myAttributes.initNew(myElement);
+
+ return myElement;
+ }
+
+ private String getDefaultValue() {
+ String defaultValue = model.getFixedValue();
+ if (defaultValue == null) defaultValue = model.getDefaultValue();
+ if (defaultValue == null) defaultValue = myElementPanel.getDefaultValue();
+ return defaultValue;
+ }
+
+ @Override
+ public void grabFocus() {
+ if (myElementPanel != null)
+ myElementPanel.grabFocus();
+ else
+ myAttributes.grabFocus();
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/HelpPane.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/HelpPane.java new file mode 100644 index 0000000..aa8e13e --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/HelpPane.java @@ -0,0 +1,55 @@ +package com.c2kernel.gui.tabs.outcome.form;
+
+import javax.swing.JEditorPane;
+import javax.swing.text.html.HTMLEditorKit;
+
+import com.c2kernel.utils.Language;
+
+/**************************************************************************
+ *
+ * $Revision: 1.3 $
+ * $Date: 2004/08/24 12:44:02 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class HelpPane extends JEditorPane {
+
+ public static final String header = "<h2><font color=\"blue\">"+Language.translate("Help")+"</font></h2>";
+
+ public HelpPane() {
+ super();
+ setEditable(false);
+ setEditorKit(new HTMLEditorKit());
+ setContentType("text/html");
+ setPreferredSize(new java.awt.Dimension(200,400));
+ }
+
+ public void setHelp(String title, String helpText) {
+ setText(header+"<h3>"+title+"</h3><br>"+toHTML(helpText));
+ }
+
+
+ /**
+ * Unfortunately JEditorPane will only display HTML3.2, whereas to embed HTML in an xsd we must
+ * use XHTML so it will be valid XML. This method does a quick and dirty removal of stuff that
+ * the JEditorPane cannot display
+ *
+ * @param xhtml
+ * @return
+ */
+ public static String toHTML(String xhtml) {
+ int startPos, endPos;
+ //remove xml header
+ while((startPos = xhtml.indexOf("<?")) != -1 &&
+ (endPos = xhtml.indexOf("?>")) != -1) {
+ xhtml = xhtml.substring(0,startPos)+xhtml.substring(endPos+2);
+ }
+ // remove slash in <tags/>
+ while ((startPos = xhtml.indexOf("/>")) != -1) {
+ xhtml = xhtml.substring(0, startPos)+xhtml.substring(startPos+1);
+ }
+ return xhtml;
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/MultiLinePasteAdapter.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/MultiLinePasteAdapter.java new file mode 100644 index 0000000..3c5da27 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/MultiLinePasteAdapter.java @@ -0,0 +1,141 @@ +package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.Toolkit;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.StringSelection;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyEvent;
+import java.util.StringTokenizer;
+
+import javax.swing.JComponent;
+import javax.swing.JOptionPane;
+import javax.swing.JTable;
+import javax.swing.KeyStroke;
+
+import com.c2kernel.utils.Logger;
+/**
+* ExcelAdapter enables Copy-Paste Clipboard functionality on JTables.
+* The clipboard data format used by the adapter is compatible with
+* the clipboard format used by Excel. This provides for clipboard
+* interoperability between enabled JTables and Excel.
+*/
+public class MultiLinePasteAdapter implements ActionListener {
+ private String rowstring, value;
+ private Clipboard system;
+ private StringSelection stsel;
+ private JTable jTable1;
+ private Dimension parent;
+ /**
+ * The Excel Adapter is constructed with a
+ * JTable on which it enables Copy-Paste and acts
+ * as a Clipboard listener.
+ */
+ public MultiLinePasteAdapter(JTable myJTable, Dimension parent) {
+ jTable1 = myJTable;
+ this.parent = parent;
+ KeyStroke copy =
+ KeyStroke.getKeyStroke(KeyEvent.VK_C, ActionEvent.CTRL_MASK, false);
+ // Identifying the copy KeyStroke user can modify this
+ // to copy on some other Key combination.
+ KeyStroke paste =
+ KeyStroke.getKeyStroke(KeyEvent.VK_V, ActionEvent.CTRL_MASK, false);
+ // Identifying the Paste KeyStroke user can modify this
+ //to copy on some other Key combination.
+ jTable1.registerKeyboardAction(
+ this,
+ "Copy",
+ copy,
+ JComponent.WHEN_FOCUSED);
+ jTable1.registerKeyboardAction(
+ this,
+ "Paste",
+ paste,
+ JComponent.WHEN_FOCUSED);
+ system = Toolkit.getDefaultToolkit().getSystemClipboard();
+ }
+ /**
+ * Public Accessor methods for the Table on which this adapter acts.
+ */
+ public JTable getJTable() {
+ return jTable1;
+ }
+ public void setJTable(JTable jTable1) {
+ this.jTable1 = jTable1;
+ }
+ /**
+ * This method is activated on the Keystrokes we are listening to
+ * in this implementation. Here it listens for Copy and Paste ActionCommands.
+ * Selections comprising non-adjacent cells result in invalid selection and
+ * then copy action cannot be performed.
+ * Paste is done by aligning the upper left corner of the selection with the
+ * 1st element in the current selection of the JTable.
+ */
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().compareTo("Copy") == 0) {
+ StringBuffer sbf = new StringBuffer();
+ // Check to ensure we have selected only a contiguous block of
+ // cells
+ int numcols = jTable1.getSelectedColumnCount();
+ int numrows = jTable1.getSelectedRowCount();
+ int[] rowsselected = jTable1.getSelectedRows();
+ int[] colsselected = jTable1.getSelectedColumns();
+ if (!((numrows - 1
+ == rowsselected[rowsselected.length - 1] - rowsselected[0]
+ && numrows == rowsselected.length)
+ && (numcols - 1
+ == colsselected[colsselected.length - 1] - colsselected[0]
+ && numcols == colsselected.length))) {
+ JOptionPane.showMessageDialog(
+ null,
+ "Invalid Copy Selection",
+ "Invalid Copy Selection",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ for (int i = 0; i < numrows; i++) {
+ for (int j = 0; j < numcols; j++) {
+ sbf.append(
+ jTable1.getValueAt(rowsselected[i], colsselected[j]));
+ if (j < numcols - 1)
+ sbf.append("\t");
+ }
+ sbf.append("\n");
+ }
+ stsel = new StringSelection(sbf.toString());
+ system = Toolkit.getDefaultToolkit().getSystemClipboard();
+ system.setContents(stsel, stsel);
+ }
+ if (e.getActionCommand().compareTo("Paste") == 0) {
+ Logger.msg(5, "Trying to Paste");
+ int startRow = (jTable1.getSelectedRows())[0];
+ int startCol = (jTable1.getSelectedColumns())[0];
+ try {
+ String trstring =
+ (String) (system.getContents(this).getTransferData(DataFlavor.stringFlavor));
+ Logger.msg(8, "String is:" + trstring);
+ StringTokenizer st1 = new StringTokenizer(trstring, "\n\r");
+ for (int i = 0; st1.hasMoreTokens(); i++) {
+ rowstring = st1.nextToken();
+ StringTokenizer st2 = new StringTokenizer(rowstring, "\t");
+ for (int j = 0; st2.hasMoreTokens(); j++) {
+ value = st2.nextToken();
+ if (startRow + i == jTable1.getRowCount())
+ parent.addRow(startRow+i);
+ if (startRow + i < jTable1.getRowCount()
+ && startCol + j < jTable1.getColumnCount())
+ jTable1.setValueAt(
+ value,
+ startRow + i,
+ startCol + j);
+ Logger.msg(5, "Putting "+value+" at row="+(startRow+i)+" column="+(startCol+j));
+ }
+ }
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+
+ }
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/OutcomeEditor.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/OutcomeEditor.java new file mode 100644 index 0000000..566d7c5 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/OutcomeEditor.java @@ -0,0 +1,218 @@ +package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+
+import com.c2kernel.persistency.outcome.OutcomeValidator;
+import com.c2kernel.persistency.outcome.Schema;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Logger;
+
+
+class OutcomeEditor extends JFrame implements ActionListener {
+
+ boolean readOnly = false;
+ File schemaFile = null;
+ File instanceFile = null;
+ JFileChooser chooser;
+ OutcomePanel outcome;
+ OutcomeValidator thisValid;
+
+ public OutcomeEditor(File schema, File instance, boolean readOnly) {
+ URL schemaURL = null;
+ URL instanceURL = null;
+ schemaFile = schema;
+ instanceFile = instance;
+ this.readOnly = readOnly;
+
+ try {
+ chooser = new JFileChooser();
+ chooser.setCurrentDirectory(new File(new File(".").getCanonicalPath()));
+ } catch (IOException e) {
+ System.out.println("Could not initialise file dialog");
+ System.exit(0);
+ }
+
+
+ this.setTitle("Outcome Editor");
+ GridBagLayout gridbag = new GridBagLayout();
+ getContentPane().setLayout(gridbag);
+
+ addWindowListener(
+ new java.awt.event.WindowAdapter() {
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent evt) {
+ System.exit(0);
+ }
+ }
+ );
+ // select files if url is empty
+
+ if (schemaFile == null) { // prompt for schema
+ schemaFile = getFile("Choose Schema File", "xsd");
+ if (schemaFile == null) {
+ System.out.println("Cannot function without a schema");
+ System.exit(1);
+ }
+ }
+
+ try {
+ schemaURL = schemaFile.toURI().toURL();
+ } catch (Exception e) {
+ System.out.println("Invalid schema URL");
+ System.exit(1);
+ }
+
+ if (instanceFile == null) { // prompt for schema
+ instanceFile = getFile("Choose Instance File", "xml");
+ }
+
+ try {
+ instanceURL = instanceFile.toURI().toURL();
+ } catch (Exception e) { }
+
+ try {
+ if (instanceFile != null && instanceFile.exists())
+ outcome = new OutcomePanel(schemaURL, instanceURL, readOnly);
+ else
+ outcome = new OutcomePanel(schemaURL, readOnly);
+
+ Schema thisSchema = new Schema();
+ thisSchema.docType = schemaURL.getFile();
+ thisSchema.docVersion = -1;
+ thisSchema.schema = FileStringUtility.url2String(schemaURL);
+ thisValid = OutcomeValidator.getValidator(thisSchema);
+
+ } catch (Exception e) { e.printStackTrace(); System.exit(0);}
+
+
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridx = 0; c.gridy = 0;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1.0; c.weighty = 1.0;
+ c.gridwidth = 2; c.ipadx = 5; c.ipady = 5;
+ gridbag.setConstraints(outcome, c);
+ this.getContentPane().add(outcome);
+
+ JButton saveButton = new JButton("Save");
+ saveButton.setActionCommand("save");
+ saveButton.addActionListener(this);
+ c.gridy++; c.weighty = 0; c.gridwidth = 1;
+ gridbag.setConstraints(saveButton, c);
+ this.getContentPane().add(saveButton);
+ if (readOnly) saveButton.setEnabled(false);
+
+ JButton saveAsButton = new JButton("Save As");
+ saveAsButton.setActionCommand("saveas");
+ saveAsButton.addActionListener(this);
+ c.gridx++; c.weighty = 0;
+ gridbag.setConstraints(saveAsButton, c);
+ this.getContentPane().add(saveAsButton);
+ if (readOnly) saveAsButton.setEnabled(false);
+ System.out.println("Building Outcome Panel. Please wait . . .");
+ outcome.run();
+ pack();
+ setVisible(true);
+ super.toFront();
+
+ }
+
+ public File getFile(String title, String fileType) {
+ File targetFile = null;
+ chooser.setFileFilter(new SimpleFilter(fileType));
+ chooser.setDialogTitle(title);
+ int returnVal = chooser.showDialog(this, "Select");
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ targetFile = chooser.getSelectedFile();
+ }
+ try {
+ System.out.println(fileType+"="+targetFile.toURL());
+ } catch (Exception ex) { }
+ return targetFile;
+ }
+
+ public static void usage() {
+ System.out.println("-schema file:///schema.xsd");
+ System.out.println("-inst file:///instance.xml");
+ System.out.println("Leave one out to get a file open box.");
+ System.exit(0);
+ }
+ public static void main( String[] argv ) {
+ Logger.addLogStream(System.out, 6);
+ File instance = null;
+ File schema = null;
+ boolean readOnly = false;
+ for (int i = 0; i < argv.length; i++) {
+ if (argv[i].equals("-schema"))
+ schema = new File(argv[++i]);
+ if (argv[i].equals("-inst"))
+ instance = new File(argv[++i]);
+ if (argv[i].equals("-readOnly"))
+ readOnly = true;
+ if (argv[i].equals("-help") || argv[i].equals("-h"))
+ usage();
+ }
+ new OutcomeEditor(schema, instance, readOnly);
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().indexOf("save") == 0) {
+ String output;
+ output = outcome.getOutcome();
+
+ String errors = thisValid.validate(output);
+ if (errors != null && errors.length() > 0) {
+ int choice = JOptionPane.showConfirmDialog(null, errors+"\n\nSave anyway?", "Errors validating document", JOptionPane.YES_NO_OPTION);
+ if (choice != JOptionPane.YES_OPTION)
+ return;
+ }
+
+ if (instanceFile == null || e.getActionCommand().equals("saveas")) {
+ instanceFile = getFile("Choose Instance File", "xml");
+ if (instanceFile == null) {
+ System.out.println(output);
+ return;
+ }
+ }
+ try {
+ FileOutputStream targetStream = new FileOutputStream(instanceFile);
+ targetStream.write(output.getBytes());
+ targetStream.close();
+ } catch (Exception ex) {ex.printStackTrace();}
+ }
+ }
+
+ private class SimpleFilter extends javax.swing.filechooser.FileFilter {
+ String extension;
+
+ public SimpleFilter(String extension) {
+ super();
+ this.extension = extension;
+ }
+
+ @Override
+ public String getDescription() {
+ return extension.toUpperCase()+" Files";
+ }
+
+ @Override
+ public boolean accept(File f) {
+ if ((f.isFile() && f.getName().endsWith(extension.toLowerCase())) || f.isDirectory()) {
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/OutcomePanel.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/OutcomePanel.java new file mode 100644 index 0000000..63c1d3d --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/OutcomePanel.java @@ -0,0 +1,370 @@ +package com.c2kernel.gui.tabs.outcome.form;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.net.URL;
+
+import javax.swing.Box;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JSplitPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTextArea;
+import javax.swing.SwingConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.xml.serialize.Method;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Schema;
+import org.exolab.castor.xml.schema.reader.SchemaReader;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.outcome.InvalidOutcomeException;
+import com.c2kernel.gui.tabs.outcome.InvalidSchemaException;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.OutcomeHandler;
+import com.c2kernel.gui.tabs.outcome.OutcomeNotInitialisedException;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Logger;
+
+// will load the outcome as instructed by other bits of the gui
+// provides the 'save' button and creates the trees of objects to feed to the outcome form
+
+public class OutcomePanel extends JPanel implements OutcomeHandler
+{
+
+ Schema schemaSOM;
+ //ASModel schemaASModel;
+ Document outcomeDOM;
+ OutcomeStructure documentRoot;
+ DocumentBuilder parser;
+ boolean readOnly;
+ boolean useForm = true;
+ boolean panelBuilt = false;
+ boolean unsaved = false;
+ JScrollPane scrollpane = new JScrollPane();
+ HelpPane help = new HelpPane();
+
+ JTextArea basicView;
+
+ public OutcomePanel()
+ {
+ GridBagLayout gridbag = new java.awt.GridBagLayout();
+ setLayout(gridbag);
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setValidating(false);
+ dbf.setNamespaceAware(false);
+ try
+ {
+ parser = dbf.newDocumentBuilder();
+ }
+ catch (ParserConfigurationException e)
+ {
+ e.printStackTrace();
+ }
+
+ // Set up panel
+
+ JComponent pane;
+ if (!MainFrame.getPref("ShowHelp", "true").equals("true"))
+ pane = scrollpane;
+ else {
+ JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, scrollpane, help);
+ splitPane.setOneTouchExpandable(true);
+ splitPane.setDividerSize(9);
+ pane = splitPane;
+ }
+
+ GridBagConstraints c = new GridBagConstraints();
+
+ c.gridx = 0;
+ c.gridy = 0;
+ c.anchor = GridBagConstraints.NORTHWEST;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = 1.0;
+ c.weighty = 1.0;
+ c.ipadx = 5;
+ c.ipady = 5;
+
+ gridbag.setConstraints(pane, c);
+ this.add(pane);
+ }
+
+ public OutcomePanel(boolean readOnly)
+ {
+ this();
+ setReadOnly(readOnly);
+ }
+
+ public OutcomePanel(String schema, boolean readOnly) throws OutcomeException
+ {
+ this(readOnly);
+ this.setDescription(schema);
+ }
+
+ public OutcomePanel(String schema, String outcome, boolean readOnly) throws OutcomeException
+ {
+ this(readOnly);
+ this.setDescription(schema);
+ this.setOutcome(outcome);
+ }
+
+ // Parse from URLS
+ public void setOutcome(URL outcomeURL) throws InvalidOutcomeException
+ {
+
+ try
+ {
+ setOutcome(new InputSource(outcomeURL.openStream()));
+ }
+ catch (IOException ex)
+ {
+ throw new InvalidOutcomeException("Error creating instance DOM tree: " + ex);
+ }
+ }
+
+ public void setDescription(URL schemaURL) throws InvalidSchemaException
+ {
+ Logger.msg(7, "OutcomePanel.setDescription() - schemaURL:" + schemaURL.toString());
+ try
+ {
+ setDescription(new InputSource(schemaURL.openStream()));
+ }
+ catch (IOException ex)
+ {
+ throw new InvalidSchemaException("Error creating exolab schema object: " + ex);
+ }
+
+ }
+
+ public OutcomePanel(URL schemaURL, boolean readOnly) throws OutcomeException
+ {
+ this(readOnly);
+ this.setDescription(schemaURL);
+ }
+
+ public OutcomePanel(URL schemaURL, URL outcomeURL, boolean readOnly) throws OutcomeException
+ {
+ this(readOnly);
+ this.setDescription(schemaURL);
+ this.setOutcome(outcomeURL);
+ }
+
+ // Parse from Strings
+ @Override
+ public void setOutcome(String outcome) throws InvalidOutcomeException
+ {
+
+ try
+ {
+ setOutcome(new InputSource(new StringReader(outcome)));
+ }
+ catch (IOException ex)
+ {
+ throw new InvalidOutcomeException("Error creating instance DOM tree: " + ex);
+ }
+ }
+
+ @Override
+ public void setDescription(String schema) throws InvalidSchemaException
+ {
+ if (schema == null)
+ throw new InvalidSchemaException("Null schema supplied");
+ try
+ {
+ setDescription(new InputSource(new StringReader(schema)));
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ }
+
+ }
+
+ @Override
+ public void setReadOnly(boolean readOnly)
+ {
+ this.readOnly = readOnly;
+ }
+
+ public void setDescription(InputSource schemaSource) throws InvalidSchemaException, IOException
+ {
+
+ SchemaReader mySchemaReader = new SchemaReader(schemaSource);
+ this.schemaSOM = mySchemaReader.read();
+ }
+
+ public void setOutcome(InputSource outcomeSource) throws InvalidOutcomeException, IOException
+ {
+ try
+ {
+ outcomeDOM = parser.parse(outcomeSource);
+ }
+ catch (SAXException ex)
+ {
+ throw new InvalidOutcomeException("Sax error parsing Outcome " + ex);
+ }
+ }
+
+ @Override
+ public void run()
+ {
+ Thread.currentThread().setName("Outcome Panel Builder");
+ try
+ {
+ makeDisplay();
+ }
+ catch (Exception oe)
+ {
+ scrollpane.setViewportView(new JLabel("Outcome View Generation Failed: " + oe.getMessage()));
+ Logger.error(oe);
+ }
+ }
+
+ public void makeDisplay()
+ {
+ try
+ {
+ initPanel();
+ }
+ catch (OutcomeException ex)
+ {
+ // something went wrong
+ useForm = false;
+ Box textPanel = Box.createVerticalBox();
+ JLabel errorMsg = new JLabel("Could not create outcome view: " + ex.getMessage());
+ errorMsg.setHorizontalAlignment(SwingConstants.LEFT);
+ textPanel.add(errorMsg);
+ textPanel.add(Box.createVerticalGlue());
+ if (outcomeDOM!=null) {
+ basicView = new JTextArea(serialize(outcomeDOM, true));
+ basicView.setEnabled(!readOnly);
+ textPanel.add(basicView);
+ }
+ scrollpane.setViewportView(textPanel);
+ }
+ }
+
+ public void initPanel() throws OutcomeException
+ {
+ Element docElement;
+ /*if (panelBuilt)
+ return;*/
+ Logger.msg(5, "Initialising Panel..");
+ scrollpane.setViewportView(new JLabel("Building outcome. Please hang on two ticks . . ."));
+ if (schemaSOM == null)
+ throw new InvalidSchemaException("A valid schema has not been supplied.");
+ // create root panel with element declaration and maybe root document element node
+
+ //find the root element declaration in the schema - may need to look for annotation??
+ ElementDecl rootElementDecl = null;
+ docElement = (outcomeDOM == null) ? null : outcomeDOM.getDocumentElement();
+
+ for (ElementDecl elementDecl: schemaSOM.getElementDecls())
+ {
+ rootElementDecl = elementDecl;
+ // REVISIT: We don't detect which is the most likely root element if there is more than one root decl
+ // xmlspy looks for an element not referenced elsewhere. simple but hard
+ // if we already have a document then use its root element to find the right decl
+ if (docElement != null && docElement.getTagName().equals(rootElementDecl.getName()))
+ break;
+ }
+
+ if (rootElementDecl == null)
+ throw new InvalidSchemaException("No root elements defined");
+ documentRoot = new DataRecord(rootElementDecl, readOnly, help, false);
+
+ Logger.msg(5, "Finished structure. Populating...");
+ if (docElement == null)
+ {
+ outcomeDOM = parser.newDocument();
+ docElement = documentRoot.initNew(outcomeDOM);
+ outcomeDOM.appendChild(docElement);
+ }
+ else
+ documentRoot.addInstance(docElement, outcomeDOM);
+
+ // got a fully rendered Outcome! put it in the scrollpane
+ // initialise container panel
+
+ JTabbedPane outcomeTab = new JTabbedPane();
+ outcomeTab.addTab(rootElementDecl.getName(), documentRoot);
+ outcomeTab.setSelectedIndex(0);
+
+ scrollpane.setViewportView(outcomeTab);
+ panelBuilt = true;
+
+ revalidate();
+ doLayout();
+ if (!readOnly)
+ documentRoot.grabFocus();
+ }
+
+ @Override
+ public JPanel getPanel() throws OutcomeNotInitialisedException
+ {
+ return this;
+ }
+
+ @Override
+ public String getOutcome()
+ {
+ if (useForm)
+ {
+ documentRoot.validateStructure();
+ return serialize(outcomeDOM, false);
+ }
+ else
+ {
+ return basicView.getText();
+ }
+ }
+
+ static public String serialize(Document doc, boolean prettyPrint)
+ {
+ String serializedDoc = null;
+ OutputFormat format = new OutputFormat(Method.XML, null, prettyPrint);
+ StringWriter stringOut = new StringWriter();
+ XMLSerializer serial = new XMLSerializer(stringOut, format);
+ try
+ {
+ serial.asDOMSerializer();
+ serial.serialize(doc);
+ }
+ catch (java.io.IOException ex)
+ {
+ Logger.error(ex.toString());
+ }
+ serializedDoc = stringOut.toString();
+ return serializedDoc;
+ }
+
+ @Override
+ public boolean isUnsaved() {
+ return unsaved;
+ }
+
+ @Override
+ public void saved() {
+ unsaved = false;
+ }
+
+ @Override
+ public void export(File targetFile) throws Exception {
+ FileStringUtility.string2File(targetFile, getOutcome());
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java new file mode 100644 index 0000000..aee09df --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java @@ -0,0 +1,283 @@ +package com.c2kernel.gui.tabs.outcome.form;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+
+import javax.swing.ImageIcon;
+import javax.swing.JPanel;
+
+import org.exolab.castor.types.AnyNode;
+import org.exolab.castor.xml.schema.Annotated;
+import org.exolab.castor.xml.schema.Annotation;
+import org.exolab.castor.xml.schema.ComplexType;
+import org.exolab.castor.xml.schema.ContentModelGroup;
+import org.exolab.castor.xml.schema.Documentation;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Group;
+import org.exolab.castor.xml.schema.ModelGroup;
+import org.exolab.castor.xml.schema.Order;
+import org.exolab.castor.xml.schema.Particle;
+import org.exolab.castor.xml.schema.SimpleType;
+import org.exolab.castor.xml.schema.SimpleTypesFactory;
+import org.exolab.castor.xml.schema.XMLType;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.utils.Language;
+import com.c2kernel.utils.Logger;
+
+// contains child outcome elements - creates new ones
+public abstract class OutcomeStructure extends JPanel {
+
+ ElementDecl model;
+ Element myElement = null;
+ boolean readOnly;
+ HashMap<String, OutcomeStructure> subStructure = new HashMap<String, OutcomeStructure>();
+ ArrayList<String> order = new ArrayList<String>();
+ String help = "<i>"+Language.translate("No help is available for this element")+"</i>";
+ HelpPane helpPane;
+ boolean deferChild = false;
+
+ public OutcomeStructure(ElementDecl model, boolean readOnly , HelpPane helpPane) {
+ this.model = model;
+ this.readOnly = readOnly;
+ this.helpPane = helpPane;
+ subStructure = new HashMap<String, OutcomeStructure>();
+ Logger.msg(8, "Creating " + model.getName() + " structure as " +
+ this.getClass().getName().substring(this.getClass().getName().lastIndexOf('.') + 1));
+
+ String doc = extractHelp(model);
+ if (doc.length() > 0) help = doc;
+ }
+
+ public boolean getReadOnly() {
+ return readOnly;
+ }
+ /** Contains the rules for deciding which OutcomeStructure will represent a chosen Element Declaration.
+ * In this order
+ * <ol>
+ * <li>if maxOccurs>1 then Dimension
+ * <li> SimpleTypes are Fields
+ * <li> No element children is a Field
+ * <li> Everything else is a DataRecord
+ * </ol>
+ */
+ public OutcomeStructure createStructure(ElementDecl model, boolean readOnly, HelpPane help) throws OutcomeException {
+ XMLType elementType = model.getType();
+ ComplexType elementComplexType;
+
+ if (model.getMaxOccurs() == 0) return null;
+
+ // if more than one can occur - dimension
+ if (model.getMaxOccurs() > 1
+ || model.getMaxOccurs() == Particle.UNBOUNDED
+ || model.getMinOccurs() == 0)
+ return new Dimension(model, readOnly, help);
+
+ // must have a type from now on
+ if (elementType == null)
+ throw new StructuralException("Element "+model.getName()+" is elementary yet has no type.");
+ // simple types will be fields
+ if (elementType instanceof SimpleType) return new Field(model, readOnly, help);
+
+ // otherwise is a complex type
+ try {
+ elementComplexType = (ComplexType)elementType;
+ }
+ catch (ClassCastException e) {
+ throw new StructuralException("Unknown XMLType for element " + model.getName());
+ }
+
+ //when no element children - field
+ if (elementComplexType.getParticleCount() == 0) return new Field(model, readOnly, help);
+
+ //everything else is a data record
+ return new DataRecord(model, readOnly, help, deferChild);
+ }
+
+ /** Extracts child Element declarations from a content group and recursively from any group
+ * (not Element) of that group. calls createStructure() to find the corresponding OutcomeStructure
+ * then adds it to this structure.
+ */
+ public void enumerateElements(ContentModelGroup group) throws OutcomeException {
+
+ // process base types first if complex type
+ //HACK: castor does not include elements from basetype, so we do it manually. if they fix it, this will duplicate child elements.
+ if (group instanceof ComplexType) {
+ XMLType base = ((ComplexType)group).getBaseType();
+ if (base instanceof ComplexType)
+ enumerateElements((ComplexType)base);
+ }
+
+ for (Enumeration<?> elements = group.enumerate(); elements.hasMoreElements(); ) {
+ Particle thisParticle = (Particle)elements.nextElement();
+ if (thisParticle instanceof Group) {
+ Group thisGroup = (Group)thisParticle;
+ if (thisGroup instanceof ModelGroup) {
+ // HACK: Castor strangeness - model groups don't seem to resolve their own references. If fixed, this will still work
+ ModelGroup thisModel = (ModelGroup)thisGroup;
+ if (thisModel.hasReference()) thisGroup = thisModel.getReference();
+ }
+ Order thisOrder = thisGroup.getOrder();
+ if (thisOrder == Order.sequence || thisOrder == Order.all) enumerateElements(thisGroup);
+ else // we only support sequences in data structures such as these
+ throw new StructuralException("The '"+thisGroup.getOrder()+"' group is not supported");
+ }
+ else if (thisParticle instanceof ElementDecl) {
+ ElementDecl thisElement = (ElementDecl)thisParticle;
+ addStructure(createStructure(thisElement, readOnly, helpPane));
+ }
+ else throw new StructuralException("Particle " + thisParticle.getClass() + " not implemented");
+ }
+ }
+
+ /** Adds a generated OutcomeStructure as a child of this one. A separate structure as is often overridden.
+ */
+ public void addStructure(OutcomeStructure newElement) throws OutcomeException {
+ if (newElement == null) return;
+ subStructure.put(newElement.getName(), newElement);
+ order.add(newElement.getName());
+ }
+
+ /** After schema processing, addInstance() propogates the XML instance document down the layout.
+ * Most OutcomeStructures will throw an exception if called more than once, except Dimension, which is the only
+ * Outcome Structure to support maxOccurs>1
+ */
+ public abstract void addInstance(Element myElement, Document parentDoc) throws OutcomeException;
+
+ public Element getElement() {
+ return myElement;
+ }
+
+ @Override
+ public String getName() {
+ if (model == null) return null;
+ return model.getName();
+ }
+
+ public ElementDecl getModel() {
+ return model;
+ }
+
+ public String getHelp() {
+ return help;
+ }
+
+ public String validateStructure() {
+ StringBuffer errors = new StringBuffer();
+ for (OutcomeStructure element : subStructure.values()) {
+ errors.append(element.validateStructure());
+ }
+ return errors.toString();
+ }
+
+ public abstract Element initNew(Document parent);
+
+ public static String extractHelp(Annotated model) {
+ Enumeration<?> e = model.getAnnotations();
+ StringBuffer doc = new StringBuffer();
+ if (e.hasMoreElements()) { // look for HTML
+ Annotation note = (Annotation)e.nextElement();
+ for (Enumeration<?> g = note.getDocumentation(); g.hasMoreElements();) {
+ Documentation thisDoc = (Documentation)g.nextElement();
+ for (Enumeration<?> h = thisDoc.getObjects(); h.hasMoreElements();) {
+ AnyNode node = (AnyNode)h.nextElement();
+ String line = node.toString();
+ if (line.length() == 0)
+ line = node.getStringValue();
+ if (line.length() > 0) {
+ doc.append(line).append("\n");
+ }
+ }
+ }
+ }
+
+ return doc.toString();
+ }
+
+ @Override
+ public abstract void grabFocus();
+
+ public static Class<?> getJavaClass(int typeCode) {
+ switch (typeCode) {
+
+ // boolean
+ case SimpleTypesFactory.BOOLEAN_TYPE:
+ return Boolean.class;
+
+ // integers
+ case SimpleTypesFactory.INTEGER_TYPE:
+ case SimpleTypesFactory.NON_POSITIVE_INTEGER_TYPE:
+ case SimpleTypesFactory.NEGATIVE_INTEGER_TYPE:
+ case SimpleTypesFactory.NON_NEGATIVE_INTEGER_TYPE:
+ case SimpleTypesFactory.POSITIVE_INTEGER_TYPE:
+ case SimpleTypesFactory.INT_TYPE:
+ case SimpleTypesFactory.UNSIGNED_INT_TYPE:
+ case SimpleTypesFactory.SHORT_TYPE:
+ case SimpleTypesFactory.UNSIGNED_SHORT_TYPE:
+ case SimpleTypesFactory.LONG_TYPE:
+ case SimpleTypesFactory.UNSIGNED_LONG_TYPE:
+ case SimpleTypesFactory.BYTE_TYPE:
+ case SimpleTypesFactory.UNSIGNED_BYTE_TYPE:
+ return BigInteger.class;
+ // floats
+ case SimpleTypesFactory.FLOAT_TYPE:
+ case SimpleTypesFactory.DOUBLE_TYPE:
+ case SimpleTypesFactory.DECIMAL_TYPE:
+ return BigDecimal.class;
+
+ // images
+ case SimpleTypesFactory.BASE64BINARY_TYPE:
+ case SimpleTypesFactory.HEXBINARY_TYPE:
+ return ImageIcon.class;
+
+ // everything else is a string for now
+ default:
+ return String.class;
+ }
+ }
+
+ public static Object getTypedValue(String value, Class<?> type) {
+ try {
+ if (type.equals(Boolean.class))
+ if (value == null || value.equals(""))
+ return Boolean.FALSE;
+ else
+ return Boolean.valueOf(value);
+ else if (type.equals(BigInteger.class))
+ if (value == null || value.equals(""))
+ return new BigInteger("0");
+ else
+ return new BigInteger(value);
+ else if (type.equals(BigDecimal.class))
+ if (value == null || value.equals(""))
+ return new BigDecimal(0);
+ else
+ return new BigDecimal(value);
+ } catch (Exception ex) {
+ Logger.error("Cannot convert value '"+value+"' to a "+type.getName());
+ }
+ return value==null?"":value;
+ }
+
+ public static boolean isEmpty(Object value) {
+ if (value == null) return true;
+
+ if (value instanceof String) {
+ if (((String)value).length() == 0) return true;
+ }
+ else if (value instanceof Boolean) {
+ if (((Boolean)value).booleanValue() == false) return true;
+ }
+ else if (value instanceof BigInteger) {
+ if (((BigInteger)value).intValue() == 0) return true;
+ }
+ else if (value instanceof BigDecimal) {
+ if (((BigDecimal)value).floatValue() == 0.0) return true;
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/StructuralException.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/StructuralException.java new file mode 100644 index 0000000..5aff436 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/StructuralException.java @@ -0,0 +1,12 @@ +package com.c2kernel.gui.tabs.outcome.form;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+
+public class StructuralException extends OutcomeException {
+
+ public StructuralException() {
+ super();
+ }
+ public StructuralException(String ex) {
+ super(ex);
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ArrayEditField.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ArrayEditField.java new file mode 100644 index 0000000..742d1b4 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ArrayEditField.java @@ -0,0 +1,173 @@ +package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.text.JTextComponent;
+
+import org.exolab.castor.xml.schema.SimpleType;
+
+import com.c2kernel.utils.Language;
+
+/**************************************************************************
+ *
+ * $Revision: 1.7 $
+ * $Date: 2006/05/24 07:51:51 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ArrayEditField extends StringEditField implements ActionListener {
+
+ Box arrayBox;
+ Box expandBox;
+ Box editBox;
+ JScrollPane arrayView;
+ JButton arrayButton;
+ JButton expandButton;
+ JButton contractButton;
+ JButton addButton;
+ JButton removeButton;
+ ArrayTableModel arrayModel;
+ JLabel arrayLabel = new JLabel("Array");
+ boolean panelShown = false;
+ boolean readOnly = false;
+
+ public ArrayEditField(SimpleType type) {
+ arrayBox = Box.createVerticalBox();
+ arrayBox.add(arrayLabel);
+ arrayButton = new JButton(Language.translate("Show"));
+ arrayButton.addActionListener(this);
+ arrayButton.setActionCommand("toggle");
+ arrayBox.add(arrayButton);
+
+ expandBox = Box.createHorizontalBox();
+ expandButton = new JButton(">>");
+ expandButton.setToolTipText("Increase the number of columns displaying this array");
+ expandButton.addActionListener(this);
+ expandButton.setActionCommand("extend");
+
+ contractButton = new JButton("<<");
+ contractButton.setToolTipText("Decrease the number of columns displaying this array");
+ contractButton.addActionListener(this);
+ contractButton.setActionCommand("contract");
+
+ expandBox.add(contractButton);
+ expandBox.add(Box.createHorizontalGlue());
+ expandBox.add(expandButton);
+
+ arrayModel = new ArrayTableModel(type);
+ if (arrayModel.getColumnCount() < 2) contractButton.setEnabled(false);
+ arrayView = new JScrollPane(new JTable(arrayModel));
+
+ editBox = Box.createHorizontalBox();
+ addButton = new JButton("+");
+ addButton.setToolTipText("Add a field to the end of this array");
+ addButton.addActionListener(this);
+ addButton.setActionCommand("add");
+ removeButton = new JButton("-");
+ removeButton.setToolTipText("Remove the last field from this array");
+ removeButton.addActionListener(this);
+ removeButton.setActionCommand("remove");
+ editBox.add(addButton);
+ editBox.add(Box.createHorizontalGlue());
+ editBox.add(removeButton);
+ }
+ /**
+ *
+ */
+ @Override
+ public String getDefaultValue() {
+ return "";
+ }
+ /**
+ *
+ */
+ @Override
+ public String getText() {
+ return arrayModel.getData();
+ }
+ /**
+ *
+ */
+ @Override
+ public void setText(String text) {
+ arrayModel.setData(text);
+ arrayLabel.setText("Array ("+arrayModel.getArrayLength()+" values)");
+ }
+ /**
+ *
+ */
+ @Override
+ public Component getControl() {
+ return arrayBox;
+ }
+ /**
+ *
+ */
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getActionCommand().equals("toggle")) {
+ arrayBox.removeAll();
+ if (panelShown) {
+ arrayBox.add(arrayLabel);
+ arrayBox.add(Box.createVerticalStrut(7));
+ arrayBox.add(arrayButton);
+ arrayButton.setText("Show");
+ }
+ else {
+ arrayBox.add(arrayLabel);
+ arrayBox.add(Box.createVerticalStrut(7));
+ arrayBox.add(arrayButton);
+ arrayBox.add(Box.createVerticalStrut(7));
+ arrayBox.add(expandBox);
+ arrayBox.add(Box.createVerticalStrut(7));
+ arrayBox.add(arrayView);
+ if (!readOnly) arrayBox.add(editBox);
+ arrayButton.setText("Hide");
+ }
+ panelShown = !panelShown;
+ arrayBox.validate();
+ }
+ else if (e.getActionCommand().equals("add")) {
+ arrayModel.addField();
+ arrayLabel.setText("Array ("+arrayModel.getArrayLength()+" values)");
+ }
+ else if (e.getActionCommand().equals("remove")) {
+ arrayModel.removeField();
+ arrayLabel.setText("Array ("+arrayModel.getArrayLength()+" values)");
+ }
+ else {
+ int currentCols = arrayModel.getColumnCount();
+ if (e.getActionCommand().equals("extend"))
+ currentCols++;
+ else if (e.getActionCommand().equals("contract"))
+ currentCols--;
+ arrayModel.setColumnCount(currentCols);
+ contractButton.setEnabled(currentCols > 1);
+ }
+
+ }
+
+ /**
+ *
+ */
+ @Override
+ public JTextComponent makeTextField() {
+ // not used by array
+ return null;
+ }
+ @Override
+ public void setEditable(boolean editable) {
+ readOnly = !editable;
+ arrayModel.setReadOnly(!readOnly);
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ArrayTableModel.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ArrayTableModel.java new file mode 100644 index 0000000..341c33a --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ArrayTableModel.java @@ -0,0 +1,113 @@ +package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.StringTokenizer;
+
+import javax.swing.table.AbstractTableModel;
+
+import org.exolab.castor.xml.schema.SimpleType;
+
+import com.c2kernel.gui.tabs.outcome.form.OutcomeStructure;
+import com.c2kernel.utils.Language;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2006/05/24 07:51:53 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ArrayTableModel extends AbstractTableModel {
+
+ ArrayList<Object> contents = new ArrayList<Object>();
+ Class<?> type;
+ int numCols = 1;
+ boolean readOnly = false;
+
+ public ArrayTableModel(SimpleType type) {
+ super();
+ this.type = OutcomeStructure.getJavaClass(type.getTypeCode());
+ }
+
+ public void setReadOnly(boolean readOnly) {
+ this.readOnly = readOnly;
+ }
+
+ public void setData(String data) {
+ contents.clear();
+ StringTokenizer tok = new StringTokenizer(data);
+ while(tok.hasMoreTokens())
+ contents.add(OutcomeStructure.getTypedValue(tok.nextToken(), type));
+ fireTableStructureChanged();
+ }
+
+ public String getData() {
+ if (contents.size() == 0) return "";
+ Iterator<Object> iter = contents.iterator();
+ StringBuffer result = new StringBuffer(iter.next().toString());
+ while (iter.hasNext())
+ result.append(" ").append(iter.next().toString());
+ return result.toString();
+ }
+
+ public void addField() {
+ contents.add(OutcomeStructure.getTypedValue("", type));
+ fireTableStructureChanged();
+ }
+
+ public void removeField() {
+ contents.remove(contents.size()-1);
+ fireTableStructureChanged();
+ }
+
+ @Override
+ public Class<?> getColumnClass(int columnIndex) {
+ return type;
+ }
+
+ @Override
+ public int getColumnCount() {
+ return numCols;
+ }
+
+ public int getArrayLength() {
+ return contents.size();
+ }
+
+ public void setColumnCount(int newCols) {
+ numCols = newCols;
+ fireTableStructureChanged();
+ }
+
+ @Override
+ public String getColumnName(int column) {
+ return Language.translate("Value");
+ }
+
+ @Override
+ public int getRowCount() {
+ return (contents.size()/numCols)+1;
+ }
+
+ @Override
+ public Object getValueAt(int arg0, int arg1) {
+ int index = arg1+(arg0 * numCols);
+ if (index >= contents.size())
+ return null;
+ return contents.get(arg1+(arg0 * numCols));
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ if (columnIndex+(rowIndex*numCols) > contents.size()-1) return false;
+ return !readOnly;
+ }
+
+ @Override
+ public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
+ contents.set(columnIndex+(rowIndex*numCols), aValue);
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/BooleanEditField.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/BooleanEditField.java new file mode 100644 index 0000000..c831eb4 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/BooleanEditField.java @@ -0,0 +1,75 @@ +package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Component;
+import java.awt.event.FocusEvent;
+
+import javax.swing.JCheckBox;
+import javax.swing.text.JTextComponent;
+
+import com.c2kernel.utils.Logger;
+
+/**************************************************************************
+ *
+ * $Revision: 1.7 $
+ * $Date: 2005/08/16 13:59:56 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class BooleanEditField extends StringEditField {
+
+ JCheckBox checkbox;
+
+ public BooleanEditField() {
+ checkbox = new JCheckBox();
+ checkbox.setSelected(false);
+ checkbox.addFocusListener(this);
+ }
+
+ @Override
+ public String getText() {
+ return String.valueOf(checkbox.isSelected());
+ }
+
+ @Override
+ public void setText(String text) {
+ boolean newState = false;
+ try {
+ newState = Boolean.valueOf(text).booleanValue();
+ } catch (Exception ex) {
+ Logger.error("Invalid value for checkbox: "+text);
+ }
+ checkbox.setSelected(newState);
+ }
+
+ @Override
+ public void setEditable(boolean editable) {
+ super.setEditable(editable);
+ checkbox.setEnabled(editable);
+ }
+
+ @Override
+ public Component getControl() {
+ return checkbox;
+ }
+
+ @Override
+ public String getDefaultValue() {
+ return "false";
+ }
+
+ /** don't reserve the item finder for a boolean */
+ @Override
+ public void focusGained(FocusEvent e) {
+ helpPane.setHelp(name, helpText);
+ }
+
+ /**
+ *
+ */
+ @Override
+ public JTextComponent makeTextField() {
+ // not used by boolean
+ return null;
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ComboField.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ComboField.java new file mode 100644 index 0000000..2c4ce05 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ComboField.java @@ -0,0 +1,144 @@ +package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Component;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+
+import javax.swing.DefaultComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.text.JTextComponent;
+
+import org.exolab.castor.types.AnyNode;
+import org.exolab.castor.xml.schema.AttributeDecl;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Facet;
+import org.exolab.castor.xml.schema.SimpleType;
+
+import com.c2kernel.gui.tabs.outcome.form.StructuralException;
+import com.c2kernel.scripting.Script;
+import com.c2kernel.utils.Logger;
+
+/*******************************************************************************
+ *
+ * $Revision: 1.4 $ $Date: 2005/08/16 13:59:56 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research All
+ * rights reserved.
+ ******************************************************************************/
+
+public class ComboField extends StringEditField {
+
+ JComboBox comboField;
+ ListOfValues vals;
+ DefaultComboBoxModel comboModel;
+ AnyNode listNode;
+
+ public ComboField(SimpleType type, AnyNode listNode) {
+ super();
+ comboField = new JComboBox();
+ content = type;
+ this.listNode = listNode;
+ createLOV();
+ }
+
+ @Override
+ public String getDefaultValue() {
+ if (vals.getDefaultKey() != null)
+ return vals.get(vals.getDefaultKey()).toString();
+ else
+ return "";
+ }
+
+ @Override
+ public String getText() {
+ return vals.get(comboModel.getSelectedItem()).toString();
+ }
+
+ @Override
+ public JTextComponent makeTextField() {
+ // not used by this control
+ return null;
+ }
+
+ @Override
+ public void setText(String text) {
+ comboModel.setSelectedItem(text);
+ }
+
+ @Override
+ public Component getControl() {
+ return comboField;
+ }
+
+ private void createLOV() {
+ vals = new ListOfValues();
+
+ if (listNode != null) { // schema instructions for list building
+ String lovType = listNode.getLocalName();
+ String param = listNode.getFirstChild().getStringValue();
+ if (lovType.equals("ScriptList"))
+ populateLOVFromScript(param);
+ if (lovType.equals("PathList"))
+ populateLOVFromLDAP(param);
+ }
+
+ // handle enumerations
+ // TODO: should be ANDed with above results
+ if (content.hasFacet(Facet.ENUMERATION)) {
+ //ListOfValues andList = new ListOfValues();
+ Enumeration<Facet> enums = content.getFacets(Facet.ENUMERATION);
+ while (enums.hasMoreElements()) {
+ Facet thisEnum = enums.nextElement();
+ vals.put(thisEnum.getValue(), thisEnum.getValue(), false);
+ }
+ }
+
+ String[] keyArray = new String[vals.keySet().size()];
+ comboModel = new DefaultComboBoxModel(vals.keySet().toArray(keyArray));
+ comboModel.setSelectedItem(vals.getDefaultKey());
+ comboField.setModel(comboModel);
+ }
+
+ /**
+ * @param param
+ */
+ private void populateLOVFromLDAP(String param) {
+ // TODO List of Values from LDAP properties, eg '/root/path;prop=val;prop=val'
+
+
+ }
+
+ private void populateLOVFromScript(String scriptName) {
+ try {
+ StringTokenizer tok = new StringTokenizer(scriptName, "_");
+ if (tok.countTokens() != 2)
+ throw new Exception("Invalid LOVScript name");
+ Script lovscript = new Script(tok.nextToken(), Integer.parseInt(tok.nextToken()));
+ lovscript.setInputParamValue("LOV", vals);
+ lovscript.execute();
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+ }
+
+ @Override
+ public void setDecl(AttributeDecl model) throws StructuralException {
+ super.setDecl(model);
+ createLOV();
+ }
+
+ @Override
+ public void setDecl(ElementDecl model) throws StructuralException {
+ super.setDecl(model);
+ createLOV();
+ }
+
+ /**
+ *
+ */
+
+ @Override
+ public void setEditable(boolean editable) {
+ comboField.setEditable(editable);
+ }
+}
\ No newline at end of file diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/DecimalEditField.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/DecimalEditField.java new file mode 100644 index 0000000..fabaed8 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/DecimalEditField.java @@ -0,0 +1,122 @@ +package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Toolkit;
+import java.math.BigDecimal;
+
+import javax.swing.JTextField;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.PlainDocument;
+
+/**************************************************************************
+ *
+ * $Revision: 1.3 $
+ * $Date: 2005/08/16 13:59:56 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class DecimalEditField extends StringEditField {
+
+ public DecimalEditField() {
+ super();
+ field.addFocusListener(this);
+ field.setToolTipText("This field must contains a decimal number e.g. 3.14159265");
+ }
+
+ @Override
+ public String getText() {
+ return field.getText();
+ }
+
+ @Override
+ public void setText(String text) {
+ field.setText(text);
+ }
+
+ @Override
+ public String getDefaultValue() {
+ return "0.0";
+ }
+
+ @Override
+ public JTextComponent makeTextField() {
+ return new DecimalTextField();
+ }
+
+ private class DecimalTextField extends JTextField {
+
+ public DecimalTextField() {
+ super();
+ setHorizontalAlignment(RIGHT);
+ }
+ @Override
+ protected Document createDefaultModel() {
+ return new Decimal();
+ }
+ }
+
+ private class Decimal extends PlainDocument {
+
+ BigDecimal currentVal = new BigDecimal(0.0);
+
+
+ @Override
+ public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
+
+ if (str == null || str.equals("")) {
+ return;
+ }
+
+ String proposedResult = null;
+
+ if (getLength() == 0) {
+ proposedResult = str;
+ } else {
+ StringBuffer currentBuffer = new StringBuffer( this.getText(0, getLength()) );
+ currentBuffer.insert(offs, str);
+ proposedResult = currentBuffer.toString();
+ }
+
+ try {
+ currentVal = parse(proposedResult);
+ super.insertString(offs, str, a);
+ } catch (Exception e) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ }
+
+ @Override
+ public void remove(int offs, int len) throws BadLocationException {
+
+ String currentText = this.getText(0, getLength());
+ String beforeOffset = currentText.substring(0, offs);
+ String afterOffset = currentText.substring(len + offs, currentText.length());
+ String proposedResult = beforeOffset + afterOffset;
+
+ if (proposedResult.length() == 0) { // empty is ok
+ super.remove(offs, len);
+ return;
+ }
+ try {
+ currentVal = parse(proposedResult);
+ super.remove(offs, len);
+ } catch (Exception e) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ }
+
+ public BigDecimal parse(String proposedResult) throws NumberFormatException {
+
+ BigDecimal value = new BigDecimal(0);
+ if ( proposedResult.length() != 0) {
+ value = new BigDecimal(proposedResult);
+ }
+ return value;
+ }
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ImageEditField.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ImageEditField.java new file mode 100644 index 0000000..716a073 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ImageEditField.java @@ -0,0 +1,112 @@ +package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Component;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.FileInputStream;
+import java.lang.reflect.Array;
+
+import javax.swing.Box;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+
+import org.apache.xerces.impl.dv.util.Base64;
+
+import com.c2kernel.utils.Logger;
+
+public class ImageEditField extends StringEditField {
+
+ JLabel imageLabel;
+
+ Box imagePanel;
+
+ JButton browseButton;
+
+ String encodedImage;
+
+ static JFileChooser chooser = new JFileChooser();
+ static {
+ chooser.addChoosableFileFilter(new javax.swing.filechooser.FileFilter() {
+ @Override
+ public String getDescription() {
+ return "Image Files";
+ }
+
+ @Override
+ public boolean accept(File f) {
+ return (f.isDirectory() || (f.isFile() && (f.getName()
+ .endsWith(".gif")
+ || f.getName().endsWith(".jpg")
+ || f.getName().endsWith(".jpeg")
+ || f.getName().endsWith(".png"))));
+ }
+ });
+ }
+
+ public ImageEditField() {
+ super();
+ imageLabel = new JLabel();
+ imagePanel = Box.createVerticalBox();
+ browseButton = new JButton("Browse");
+ browseButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ int returnVal = chooser.showOpenDialog(null);
+ if (returnVal == JFileChooser.APPROVE_OPTION) {
+ File file = chooser.getSelectedFile();
+ try {
+ FileInputStream fis = new FileInputStream(file);
+ byte[] bArray = (byte[]) Array.newInstance(byte.class,
+ (int) file.length());
+ fis.read(bArray, 0, (int) file.length());
+ fis.close();
+
+ ImageIcon newImage = new ImageIcon(Toolkit
+ .getDefaultToolkit().createImage(bArray));
+ imageLabel.setIcon(newImage);
+ encodedImage = Base64.encode(bArray);
+ } catch (Exception ex) {
+ Logger.exceptionDialog(ex);
+ }
+ }
+ }
+ });
+ imagePanel.add(imageLabel);
+ imagePanel.add(Box.createVerticalStrut(5));
+ imagePanel.add(browseButton);
+ }
+
+ @Override
+ public String getDefaultValue() {
+ return "";
+ }
+
+ @Override
+ public Component getControl() {
+ return imagePanel;
+ }
+
+ @Override
+ public String getText() {
+ return encodedImage == null ? "" : encodedImage;
+ }
+
+ @Override
+ public void setText(String text) {
+ encodedImage = text;
+ if (text != null && text.length() > 0) {
+ byte[] decodedImage = Base64.decode(encodedImage);
+ imageLabel.setIcon(new ImageIcon(Toolkit.getDefaultToolkit()
+ .createImage(decodedImage)));
+ }
+ }
+
+ @Override
+ public void setEditable(boolean editable) {
+ browseButton.setVisible(false);
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/IntegerEditField.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/IntegerEditField.java new file mode 100644 index 0000000..e2c3df4 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/IntegerEditField.java @@ -0,0 +1,120 @@ +package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Toolkit;
+import java.math.BigInteger;
+
+import javax.swing.JTextField;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.JTextComponent;
+import javax.swing.text.PlainDocument;
+
+/**************************************************************************
+ *
+ * $Revision: 1.4 $
+ * $Date: 2005/08/16 13:59:56 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class IntegerEditField extends StringEditField {
+
+ public IntegerEditField() {
+ super();
+ field.setToolTipText("This field must contains a whole number e.g. 3");
+ }
+
+ @Override
+ public String getText() {
+ return field.getText();
+ }
+
+ @Override
+ public void setText(String text) {
+ field.setText(text);
+ }
+
+ @Override
+ public String getDefaultValue() {
+ return "0";
+ }
+
+ @Override
+ public JTextComponent makeTextField() {
+ return new IntegerTextField();
+ }
+
+ private class IntegerTextField extends JTextField {
+
+ public IntegerTextField() {
+ super();
+ setHorizontalAlignment(RIGHT);
+ }
+ @Override
+ protected Document createDefaultModel() {
+ return new IntegerDocument();
+ }
+ }
+
+ private class IntegerDocument extends PlainDocument {
+
+ BigInteger currentVal = new BigInteger("0");
+
+ @Override
+ public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
+
+ if (str == null || str.equals("")) {
+ return;
+ }
+
+ String proposedResult = null;
+
+ if (getLength() == 0) {
+ proposedResult = str;
+ } else {
+ StringBuffer currentBuffer = new StringBuffer( this.getText(0, getLength()) );
+ currentBuffer.insert(offs, str);
+ proposedResult = currentBuffer.toString();
+ }
+
+ try {
+ currentVal = parse(proposedResult);
+ super.insertString(offs, str, a);
+ } catch (Exception e) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ }
+
+ @Override
+ public void remove(int offs, int len) throws BadLocationException {
+
+ String currentText = this.getText(0, getLength());
+ String beforeOffset = currentText.substring(0, offs);
+ String afterOffset = currentText.substring(len + offs, currentText.length());
+ String proposedResult = beforeOffset + afterOffset;
+ if (proposedResult.length() == 0) { // empty is ok
+ super.remove(offs, len);
+ return;
+ }
+
+ try {
+ currentVal = parse(proposedResult);
+ super.remove(offs, len);
+ } catch (Exception e) {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ }
+
+ public BigInteger parse(String proposedResult) throws NumberFormatException {
+
+ BigInteger value = new BigInteger("0");
+ if ( proposedResult.length() != 0) {
+ value = new BigInteger(proposedResult);
+ }
+ return value;
+ }
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ListOfValues.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ListOfValues.java new file mode 100644 index 0000000..f95c5c9 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/ListOfValues.java @@ -0,0 +1,31 @@ +package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.util.HashMap;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/04/26 06:48:12 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ListOfValues extends HashMap<String, Object> {
+
+ String defaultKey = null;
+
+ public ListOfValues() {
+ super();
+ }
+
+ public String put(String key, String value, boolean isDefaultKey) {
+ if (isDefaultKey) defaultKey = key;
+ return (String)super.put(key, value);
+ }
+
+ public String getDefaultKey() {
+ return defaultKey;
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/LongStringEditField.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/LongStringEditField.java new file mode 100644 index 0000000..140d7f2 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/LongStringEditField.java @@ -0,0 +1,40 @@ +package com.c2kernel.gui.tabs.outcome.form.field;
+
+import java.awt.Component;
+
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.text.JTextComponent;
+
+import com.c2kernel.utils.Language;
+
+
+/**************************************************************************
+ *
+ * $Revision$
+ * $Date$
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class LongStringEditField extends StringEditField {
+
+ JTextArea bigText;
+ JScrollPane bigScroller;
+ public LongStringEditField() {
+ super();
+ field.setToolTipText(Language.translate("This field can contain any string."));
+ }
+
+ @Override
+ public JTextComponent makeTextField() {
+ return new JTextArea();
+ }
+ @Override
+ public Component getControl() {
+ if (bigScroller == null) {
+ bigScroller = new JScrollPane(field);
+ }
+ return bigScroller;
+ }
+}
diff --git a/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/StringEditField.java b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/StringEditField.java new file mode 100644 index 0000000..0e5fee9 --- /dev/null +++ b/src/main/java/com/c2kernel/gui/tabs/outcome/form/field/StringEditField.java @@ -0,0 +1,257 @@ +package com.c2kernel.gui.tabs.outcome.form.field;
+import java.awt.Component;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+import javax.swing.ImageIcon;
+import javax.swing.JTextField;
+import javax.swing.text.JTextComponent;
+
+import org.exolab.castor.types.AnyNode;
+import org.exolab.castor.xml.schema.Annotation;
+import org.exolab.castor.xml.schema.AppInfo;
+import org.exolab.castor.xml.schema.AttributeDecl;
+import org.exolab.castor.xml.schema.ElementDecl;
+import org.exolab.castor.xml.schema.Facet;
+import org.exolab.castor.xml.schema.SimpleType;
+import org.exolab.castor.xml.schema.Structure;
+import org.exolab.castor.xml.schema.XMLType;
+import org.exolab.castor.xml.schema.simpletypes.ListType;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Node;
+import org.w3c.dom.Text;
+
+import com.c2kernel.gui.DomainKeyConsumer;
+import com.c2kernel.gui.MainFrame;
+import com.c2kernel.gui.tabs.outcome.OutcomeException;
+import com.c2kernel.gui.tabs.outcome.form.HelpPane;
+import com.c2kernel.gui.tabs.outcome.form.OutcomeStructure;
+import com.c2kernel.gui.tabs.outcome.form.StructuralException;
+import com.c2kernel.lookup.DomainPath;
+
+/** Superclass for the entry field for Field and AttributeList.
+ */
+public class StringEditField implements FocusListener, DomainKeyConsumer {
+
+ Node data;
+ Structure model;
+ protected SimpleType content;
+ HelpPane helpPane;
+ String helpText;
+ protected JTextComponent field;
+
+ boolean isValid = true;
+ boolean editable = true;
+ String name;
+
+
+ public StringEditField() {
+ field = makeTextField();
+ if (field != null)
+ field.addFocusListener(this);
+ }
+
+ private static StringEditField getFieldForType(SimpleType type) {
+ // handle lists special
+ if (type instanceof ListType)
+ return new ArrayEditField(type.getBuiltInBaseType());
+
+ // is a combobox
+ if (type.hasFacet(Facet.ENUMERATION))
+ return new ComboField(type, null);
+ //find LOVscript TODO: Implement LOV
+ Enumeration<Annotation> e = type.getAnnotations();
+ while (e.hasMoreElements()) {
+ Annotation note = e.nextElement();
+ for (Enumeration<AppInfo> f = note.getAppInfo(); f.hasMoreElements();) {
+ AppInfo thisAppInfo = f.nextElement();
+ for (Enumeration<?> g = thisAppInfo.getObjects(); g.hasMoreElements();) {
+ AnyNode appInfoNode = (AnyNode)g.nextElement();
+ if (appInfoNode.getLocalName().equals("ScriptList")
+ || appInfoNode.getLocalName().equals("LDAPList")) {
+ return new ComboField(type, appInfoNode);
+ }
+ }
+ }
+ }
+ // find info on length before we go to the base type
+ long length = -1;
+ if (type.getLength()!=null) length = type.getLength().longValue();
+ else if (type.getMaxLength()!=null) length = type.getMaxLength().longValue();
+ else if (type.getMinLength()!=null) length = type.getMinLength().longValue();
+
+ // find base type if derived
+ if (!(type.isBuiltInType()))
+ type = type.getBuiltInBaseType();
+ // else derive the class
+ Class<?> contentClass = OutcomeStructure.getJavaClass(type.getTypeCode());
+ // disable list edits for the moment
+ if (contentClass.equals(Boolean.class))
+ return new BooleanEditField();
+ else if (contentClass.equals(BigInteger.class))
+ return new IntegerEditField();
+ else if (contentClass.equals(BigDecimal.class))
+ return new DecimalEditField();
+ else if (contentClass.equals(ImageIcon.class))
+ return new ImageEditField();
+ else if (length > 60)
+ return new LongStringEditField();
+ else return new StringEditField();
+ }
+
+ public static StringEditField getEditField(AttributeDecl model) throws StructuralException {
+ if (model.isReference()) model = model.getReference();
+ StringEditField newField = getFieldForType(model.getSimpleType());
+ newField.setDecl(model);
+ return newField;
+ }
+
+ public static StringEditField getEditField(ElementDecl model) throws StructuralException {
+ try {
+ XMLType baseType = model.getType();
+ while (!(baseType instanceof SimpleType))
+ baseType = baseType.getBaseType();
+ StringEditField newField = getFieldForType((SimpleType)baseType);
+ newField.setDecl(model);
+ return newField;
+ } catch (Exception ex) {
+ throw new StructuralException("No type defined in model");
+ }
+ }
+
+ public void setDecl(AttributeDecl model) throws StructuralException {
+ this.model=model;
+ this.content=model.getSimpleType();
+ this.name = model.getName();
+ if (model.isFixed()) setEditable(false);
+ }
+
+ public void setDecl(ElementDecl model) throws StructuralException {
+ this.model=model;
+ this.name = model.getName();
+ XMLType type = model.getType();
+
+ // derive base type
+ if (type.isSimpleType())
+ this.content = (SimpleType)type;
+ else
+ this.content = (SimpleType)(type.getBaseType());
+
+ if (this.content == null) throw new StructuralException("No declared base type of element");
+
+ //
+ if (model.getFixedValue() != null) setEditable(false);
+
+ }
+
+ public void setData(Attr newData) throws StructuralException {
+ if (!(newData.getName().equals(name)))
+ throw new StructuralException("Tried to add a "+newData.getName()+" into a "+name+" attribute.");
+
+ this.data = newData;
+ setText(newData.getValue());
+ }
+
+ public void setData(Text newData) {
+ String contents = newData.getData();
+ this.data = newData;
+ setText(contents);
+ }
+
+ public void setData(String newData) throws OutcomeException {
+ if (data == null) throw new OutcomeException("No node exists");
+ setText(newData);
+ updateNode();
+
+ }
+
+ public Structure getModel() {
+ return model;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Node getData() {
+ return data;
+ }
+
+ public String getDefaultValue() {
+ return "";
+ }
+
+ public void setHelp(HelpPane helpPane, String helpText) {
+ this.helpPane = helpPane;
+ this.helpText = helpText;
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ if (MainFrame.itemFinder != null)
+ MainFrame.itemFinder.clearConsumer(this);
+ updateNode();
+ }
+
+ @Override
+ public void focusGained(FocusEvent e) {
+ helpPane.setHelp(name, helpText);
+ if (editable && MainFrame.itemFinder != null)
+ MainFrame.itemFinder.setConsumer(this, "Insert");
+ }
+
+ public void updateNode() {
+ if (data == null) return;
+ if (data instanceof Text) {
+ ((Text)data).setData(getText());
+ }
+ else { //attribute
+ ((Attr)data).setValue(getText());
+ }
+ }
+
+ /**
+ * Read domkey from barcode input
+ */
+ @Override
+ public void push(DomainPath key) {
+ setText(key.getName());
+ }
+
+ /**
+ * Read string from barcode input
+ */
+ @Override
+ public void push(String key) {
+ setText(key);
+ }
+
+ public void setEditable(boolean editable) {
+ this.editable = editable;
+ if (field != null)
+ field.setEditable(editable);
+ }
+
+ public String getText() {
+ return field.getText();
+ }
+
+ public void setText(String text) {
+ field.setText(text);
+ }
+
+ public JTextComponent makeTextField() {
+ return new JTextField();
+ }
+
+ public Component getControl() {
+ return field;
+ }
+
+ public void grabFocus() {
+ getControl().requestFocus();
+ }
+}
|
