All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.verapdf.gui.PolicyPanel Maven / Gradle / Ivy

There is a newer version: 1.6.4-PDFBOX
Show newest version
package org.verapdf.gui;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.SwingUtilities;
import javax.xml.stream.XMLStreamException;

import org.verapdf.core.utils.FileUtils;
import org.verapdf.features.FeatureObjectType;
import org.verapdf.features.objects.Feature;
import org.verapdf.features.objects.FeaturesStructureContainer;
import org.verapdf.gui.tools.GUIConstants;
import org.verapdf.policy.PolicyChecker;
import org.verapdf.policy.SchematronGenerator;
import org.verapdf.policy.SchematronOperation;

/**
 * @author Sergey Shemyakov
 */
@SuppressWarnings("synthetic-access")
public class PolicyPanel extends JPanel {
	private static final long serialVersionUID = 4654611715077095480L;

	private static final String ERROR_IDS = "Error IDs"; //$NON-NLS-1$

	private File policyFile;

	private JButton okButton;
	private JDialog dialog;
	private boolean ok;
	private JPanel mainPanel;
	private JPanel assertionsPanel;
	private LayoutManager mainPanelLayout;
	private JScrollPane scrollPane;

	private List> featureTypes;
	private List arguments;
	private List> features;
	private List> operations;
	private List removeLineButtons;
	private List layoutPanels;

	private JPanel buttonPanel;
	private JButton addLineButton;

	public PolicyPanel() {
		setPreferredSize(
				new Dimension(GUIConstants.PREFERRED_POLICY_SIZE_WIDTH, GUIConstants.PREFERRED_POLICY_SIZE_HEIGHT));

		this.featureTypes = new LinkedList<>();
		this.arguments = new LinkedList<>();
		this.features = new LinkedList<>();
		this.operations = new LinkedList<>();
		this.removeLineButtons = new LinkedList<>();
		this.layoutPanels = new LinkedList<>();

		this.okButton = new JButton(GUIConstants.OK);
		this.okButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				if (PolicyPanel.this.okButton.hasFocus()) {
					JTextField emptyArguments = PolicyPanel.this.findEmptyNumberArguments();
					if (emptyArguments == null) {
						if (PolicyPanel.this.layoutPanels.size() > 0) {
							org.verapdf.gui.PolicyPanel.this.ok = true;
						}
						org.verapdf.gui.PolicyPanel.this.dialog.setVisible(false);
					} else {
						emptyArguments.requestFocus();
						PolicyPanel.this.showErrorMessage(GUIConstants.ARG_REQUIRED);
					}
				}
			}
		});

		final JButton cancelButton = new JButton(GUIConstants.CANCEL);
		cancelButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				if (cancelButton.hasFocus()) {
					org.verapdf.gui.PolicyPanel.this.dialog.setVisible(false);
				}
			}
		});

		setLayout(new BorderLayout());

		JPanel okButtonPanel = new JPanel();
		okButtonPanel.add(this.okButton);
		okButtonPanel.add(cancelButton);
		add(okButtonPanel, BorderLayout.SOUTH);

		this.addLineButton = new JButton(GUIConstants.PLUS);
		this.addLineButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				org.verapdf.gui.PolicyPanel.this.addLineToMainPanel();
			}
		});
		this.addLineButton.setPreferredSize(new Dimension(GUIConstants.PREFERRED_POLICY_SIZE_WIDTH / 20,
				GUIConstants.PREFERRED_POLICY_WINDOW_ELEMENT_HEIGHT));

		this.buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
		this.buttonPanel.add(this.addLineButton);

		this.assertionsPanel = new JPanel();
		this.mainPanelLayout = new BoxLayout(this.assertionsPanel, BoxLayout.Y_AXIS);
		this.assertionsPanel.setLayout(this.mainPanelLayout);
		this.mainPanel = new JPanel(new BorderLayout());
		this.mainPanel.add(this.buttonPanel, BorderLayout.SOUTH);
		this.mainPanel.add(this.assertionsPanel, BorderLayout.NORTH);
		this.scrollPane = new JScrollPane(this.mainPanel);
		this.add(this.scrollPane, BorderLayout.CENTER);
	}

	public boolean showDialog(Component parent) {
		Frame owner = parent instanceof Frame ? (Frame) parent
				: (Frame) SwingUtilities.getAncestorOfClass(Frame.class, parent);

		this.ok = false;
		if (this.dialog == null || this.dialog.getOwner() != owner) {
			this.dialog = new JDialog(owner, true);
			this.dialog.setResizable(false);
			this.dialog.add(this);
			this.dialog.getRootPane().setDefaultButton(this.okButton);
			this.dialog.pack();
			this.dialog.setTitle(GUIConstants.POLICY_TITLE);
		}

		this.dialog.setLocation(GUIConstants.POLICY_DIALOG_COORD_X, GUIConstants.POLICY_DIALOG_COORD_Y);
		this.dialog.setVisible(true);
		this.dialog.repaint();
		return this.ok;
	}

	public File getPolicyFile() {
		return this.policyFile;
	}

	public void writeSchematronFile() throws IOException, XMLStreamException {
		try (FileOutputStream outputStream = new FileOutputStream(this.policyFile)) {
			SchematronGenerator.writeSchematron(getAssertions(), outputStream);
		}
	}

	public void setPolicyFile(final File candidate) {
		this.policyFile = (FileUtils.hasExtNoCase(candidate.getName(), PolicyChecker.SCHEMA_EXT)) ? candidate
				: new File(candidate.getParentFile(), FileUtils.addExt(candidate.getName(), PolicyChecker.SCHEMA_EXT));
	}

	public List getAssertions() {
		List res = new ArrayList<>(this.featureTypes.size());
		for (int i = 0; i < this.featureTypes.size(); ++i) {
			FeatureObjectType assertionType = (FeatureObjectType) this.featureTypes.get(i).getSelectedItem();
			Feature assertionFeature = (Feature) this.features.get(i).getSelectedItem();
			SchematronOperation assertionOperation = (SchematronOperation) this.operations.get(i).getSelectedItem();
			JTextField argumentTextField = this.arguments.get(i);
			String assertionArgument = argumentTextField.isEditable() ? argumentTextField.getText() : "";
			res.add(new SchematronGenerator.Assertion(assertionType, assertionFeature, assertionOperation,
					assertionArgument));
		}
		return res;
	}

	private void addLineToMainPanel() {
		JPanel linePanel = new JPanel();
		GridBagLayout linePanelLayout = new GridBagLayout();
		linePanel.setLayout(linePanelLayout);

		JTextField argumentsTextField = new JTextField(10);
		this.arguments.add(argumentsTextField);
		argumentsTextField.addFocusListener(new FocusAdapter() {
			@Override
			public void focusLost(FocusEvent e) {
				JTextField textField = (JTextField) e.getSource();
				int index = PolicyPanel.this.arguments.indexOf(textField);
				Feature feature = (Feature) PolicyPanel.this.features.get(index).getSelectedItem();
				validateArgumentTextBox(textField, feature.getFeatureType());
			}
		});

		JComboBox featuresTypeComboBox = getFeatureTypeComboBox();
		this.featureTypes.add(featuresTypeComboBox);
		linePanelLayout.setConstraints(featuresTypeComboBox, getFeatureObjectTypeConstraints());
		linePanel.add(featuresTypeComboBox);

		JComboBox featuresComboBox = getFeatureComboBox(featuresTypeComboBox);
		this.features.add(featuresComboBox);
		linePanelLayout.setConstraints(featuresComboBox, getFeatureConstraints());
		linePanel.add(featuresComboBox);

		JComboBox operationsComboBox = getOperationsComboBox(featuresComboBox);
		this.operations.add(operationsComboBox);
		linePanelLayout.setConstraints(operationsComboBox, getOperationConstraints());
		linePanel.add(operationsComboBox);

		setAvailabilityForArgumentTextBox(argumentsTextField,
				(SchematronOperation) operationsComboBox.getSelectedItem());
		linePanelLayout.setConstraints(argumentsTextField, getArgumentConstraints());
		linePanel.add(argumentsTextField);

		JButton removeButton = new JButton(GUIConstants.CROSS);
		removeButton.setPreferredSize(new Dimension(GUIConstants.PREFERRED_POLICY_SIZE_WIDTH / 20,
				GUIConstants.PREFERRED_POLICY_WINDOW_ELEMENT_HEIGHT));
		removeButton.addActionListener(new RemoveLineButtonListener());
		this.removeLineButtons.add(removeButton);
		linePanelLayout.setConstraints(removeButton, getButtonConstraints());
		linePanel.add(removeButton);

		this.layoutPanels.add(linePanel);
		this.assertionsPanel.add(linePanel);

		this.dialog.revalidate();
		this.dialog.repaint();
		JScrollBar vertical = this.scrollPane.getVerticalScrollBar();
		vertical.setValue(vertical.getMaximum());
	}

	private void removeLineFromMainPanel(int index) {
		if (index >= 0 && index < this.layoutPanels.size()) {
			this.assertionsPanel.remove(index);

			this.featureTypes.remove(index);
			this.features.remove(index);
			this.operations.remove(index);
			this.arguments.remove(index);
			this.removeLineButtons.remove(index);
			this.layoutPanels.remove(index);

			this.dialog.revalidate();
			this.dialog.repaint();
		}
	}

	private JComboBox getFeatureTypeComboBox() {
		JComboBox featuresTypeComboBox = new JComboBox<>(getFeatureObjectTypes());
		featuresTypeComboBox.setRenderer(new FeatureObjectTypeRenderer());
		featuresTypeComboBox.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				if (e.getItemSelectable() instanceof JComboBox) {
					int index = PolicyPanel.this.featureTypes.indexOf(e.getItemSelectable());
					PolicyPanel.setFeaturesComboBoxForFeature(PolicyPanel.this.features.get(index),
							(FeatureObjectType) e.getItem());
				}
			}
		});
		setOptimalSizeForComboBox(featuresTypeComboBox);
		return featuresTypeComboBox;
	}

	private JComboBox getFeatureComboBox(JComboBox featuresTypeComboBox) {
		JComboBox featuresComboBox = new JComboBox<>();
		setFeaturesComboBoxForFeature(featuresComboBox, (FeatureObjectType) featuresTypeComboBox.getSelectedItem());
		featuresComboBox.setRenderer(new FeatureRenderer());
		featuresComboBox.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				if (e.getItemSelectable() instanceof JComboBox) {
					int index = PolicyPanel.this.features.indexOf(e.getItemSelectable());
					PolicyPanel.setOperationsComboBoxForFeatureType(PolicyPanel.this.operations.get(index),
							(Feature) e.getItem());
				}
			}
		});
		setOptimalSizeForComboBox(featuresComboBox);
		return featuresComboBox;
	}

	private JComboBox getOperationsComboBox(JComboBox featuresComboBox) {
		final JComboBox operationsComboBox = new JComboBox<>();
		operationsComboBox.setRenderer(new OperationsRenderer());
		setOperationsComboBoxForFeatureType(operationsComboBox, (Feature) featuresComboBox.getSelectedItem());
		operationsComboBox.addItemListener(new ItemListener() {
			@Override
			public void itemStateChanged(ItemEvent e) {
				if (e.getItemSelectable() instanceof JComboBox) {
					JComboBox comboBox = (JComboBox) e.getItemSelectable();
					int index = PolicyPanel.this.operations.indexOf(comboBox);
					SchematronOperation operation = (SchematronOperation) comboBox.getSelectedItem();
					setAvailabilityForArgumentTextBox(PolicyPanel.this.arguments.get(index), operation);
				}
			}
		});
		setOptimalSizeForComboBox(operationsComboBox);
		return operationsComboBox;
	}

	private static void setFeaturesComboBoxForFeature(JComboBox comboBox, FeatureObjectType type) {
		List features = FeaturesStructureContainer.getFeaturesListForType(type);
		comboBox.removeAllItems();
		for (Feature feature : features) {
			if (!feature.getFeatureName().equals(ERROR_IDS)) {
				comboBox.addItem(feature);
			}
		}
	}

	private static void setOperationsComboBoxForFeatureType(JComboBox comboBox, Feature type) {
		Set operations = type.getFeatureType().getLegalOperations();
		comboBox.removeAllItems();
		for (SchematronOperation operation : operations) {
			comboBox.addItem(operation);
		}
	}

	private static void setAvailabilityForArgumentTextBox(JTextField argument, SchematronOperation operation) {
		if (operation != null) {
			argument.setEditable(operation.hasArguments());
			argument.setEnabled(operation.hasArguments());
		}
	}

	private boolean validateArgumentTextBox(JTextField argument, Feature.FeatureType type) {
		if (type == Feature.FeatureType.NUMBER) {
			String argumentValue = argument.getText();
			try {
				if (argumentValue.length() > 0) {
					Double.valueOf(argumentValue);
				}
			} catch (NumberFormatException e) {
				this.showErrorMessage(GUIConstants.NUM_VALIDATION_ERROR);
				argument.requestFocus();
				return false;
			}
		}
		return true;
	}

	private JTextField findEmptyNumberArguments() {
		for (JTextField textField : this.arguments) {
			int index = this.arguments.indexOf(textField);
			Feature.FeatureType argType = ((Feature) this.features.get(index).getSelectedItem()).getFeatureType();
			if (textField.isEnabled() && textField.getText().isEmpty() && argType != Feature.FeatureType.STRING) {
				return textField;
			}
		}
		return null;
	}

	private void showErrorMessage(String message) {
		JOptionPane.showMessageDialog(this, message, GUIConstants.ERROR, JOptionPane.ERROR_MESSAGE);
	}

	private static Vector getFeatureObjectTypes() {
		Vector res = new Vector<>();
		for (FeatureObjectType type : FeatureObjectType.values()) {
			List features = FeaturesStructureContainer.getFeaturesListForType(type);
			if (!(features.size() == 1 && features.get(0).getFeatureName().equals(ERROR_IDS)) && features.size() != 0) {
				res.add(type);
			}
		}
		return res;
	}

	private static GridBagConstraints getFeatureObjectTypeConstraints() {
		GridBagConstraints res = new GridBagConstraints();
		res.gridheight = 1;
		res.gridwidth = 1;
		res.gridx = 0;
		res.gridy = 0;
		res.weighty = 0;
		res.weightx = 2;
		res.fill = GridBagConstraints.NONE;
		res.insets = getDefaultInsets();
		return res;
	}

	private static GridBagConstraints getFeatureConstraints() {
		GridBagConstraints res = new GridBagConstraints();
		res.gridheight = 1;
		res.gridwidth = 1;
		res.gridx = 1;
		res.gridy = 0;
		res.weighty = 0;
		res.weightx = 2;
		res.fill = GridBagConstraints.NONE;
		res.insets = getDefaultInsets();
		return res;
	}

	private static GridBagConstraints getOperationConstraints() {
		GridBagConstraints res = new GridBagConstraints();
		res.gridheight = 1;
		res.gridwidth = 1;
		res.gridx = 2;
		res.gridy = 0;
		res.weighty = 0;
		res.weightx = 2;
		res.fill = GridBagConstraints.NONE;
		res.insets = getDefaultInsets();
		return res;
	}

	private static GridBagConstraints getArgumentConstraints() {
		GridBagConstraints res = new GridBagConstraints();
		res.gridheight = 1;
		res.gridwidth = 1;
		res.gridx = 3;
		res.gridy = 0;
		res.weighty = 0;
		res.weightx = 6;
		res.fill = GridBagConstraints.HORIZONTAL;
		res.insets = getDefaultInsets();
		return res;
	}

	private static GridBagConstraints getButtonConstraints() {
		GridBagConstraints res = new GridBagConstraints();
		res.gridheight = 1;
		res.gridwidth = 1;
		res.gridx = 4;
		res.gridy = 0;
		res.weighty = 0;
		res.weightx = 1;
		res.fill = GridBagConstraints.HORIZONTAL;
		res.insets = getDefaultInsets();
		return res;
	}

	private static Insets getDefaultInsets() {
		return new Insets(2, 2, 2, 2);
	}

	private class FeatureObjectTypeRenderer extends JLabel implements ListCellRenderer {
		private static final long serialVersionUID = -8167306132255766422L;

		@Override
		public Component getListCellRendererComponent(JList list, FeatureObjectType value,
				int index, boolean isSelected, boolean cellHasFocus) {
			if (value != null) {
				this.setText(value.getFullName());
				this.setHorizontalAlignment(CENTER);
				this.setVerticalAlignment(CENTER);
			}
			return this;
		}
	}

	private static void setOptimalSizeForComboBox(Component component) {
		component.setMinimumSize(new Dimension(GUIConstants.POLICY_PANEL_PREFERRED_COMBO_BOX_WIDTH,
				GUIConstants.PREFERRED_POLICY_WINDOW_ELEMENT_HEIGHT));
		component.setPreferredSize(new Dimension(GUIConstants.POLICY_PANEL_PREFERRED_COMBO_BOX_WIDTH,
				GUIConstants.PREFERRED_POLICY_WINDOW_ELEMENT_HEIGHT));
		component.setMaximumSize(new Dimension(GUIConstants.POLICY_PANEL_PREFERRED_COMBO_BOX_WIDTH,
				GUIConstants.PREFERRED_POLICY_WINDOW_ELEMENT_HEIGHT));
	}

	private class FeatureRenderer extends JLabel implements ListCellRenderer {
		private static final long serialVersionUID = 1669321048267902682L;

		@Override
		public Component getListCellRendererComponent(JList list, Feature value, int index,
				boolean isSelected, boolean cellHasFocus) {
			if (value != null) {
				this.setText(value.getFeatureName());
				this.setHorizontalAlignment(CENTER);
				this.setVerticalAlignment(CENTER);
			}
			return this;
		}
	}

	private class OperationsRenderer extends JLabel implements ListCellRenderer {
		private static final long serialVersionUID = 8259625674253427340L;

		@Override
		public Component getListCellRendererComponent(JList list,
				SchematronOperation value, int index, boolean isSelected, boolean cellHasFocus) {
			if (value != null) {
				this.setText(value.getDescription());
				this.setHorizontalAlignment(CENTER);
				this.setVerticalAlignment(CENTER);
			}
			return this;
		}
	}

	private class RemoveLineButtonListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			int index = PolicyPanel.this.removeLineButtons.indexOf(e.getSource());
			PolicyPanel.this.removeLineFromMainPanel(index);
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy