/* RegisterCodecDialog.java created 2007-09-18
*
*/
package org.signalml.app.view.signal.signalml;
import static org.signalml.app.util.i18n.SvarogI18n._;
import java.awt.Window;
import java.io.File;
import java.io.IOException;
import javax.swing.JComponent;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import org.signalml.app.action.document.RegisterCodecAction;
import org.signalml.app.model.components.validation.ValidationErrors;
import org.signalml.app.model.document.RegisterCodecDescriptor;
import org.signalml.app.util.IconUtils;
import org.signalml.app.view.common.components.filechooser.EmbeddedFileChooser;
import org.signalml.app.view.common.dialogs.AbstractWizardDialog;
import org.signalml.codec.SignalMLCodec;
import org.signalml.codec.JsignalmlCodec;
import org.signalml.codec.SignalMLCodecManager;
import org.signalml.codec.XMLSignalMLCodec;
import org.signalml.codec.generator.xml.XMLCodecException;
import org.signalml.plugin.export.SignalMLException;
import org.signalml.util.Util;
import org.springframework.validation.Errors;
/**
* {@link AbstractWizardDialog Wizard dialog} to register a new
* {@link SignalMLCodec codec}.
* This dialog contains two steps:
* <ul>
* <li>{@link RegisterCodecStepOnePanel first}, in which the user selects
* the the file with the codec,</li>
* <li>{@link RegisterCodecStepTwoPanel second}, in which the user selects the
* name for the codec.</li>
*
* @author Michal Dobaczewski © 2007-2008 CC Otwarte Systemy Komputerowe Sp. z o.o.
*/
public class RegisterCodecDialog extends AbstractWizardDialog {
private static final long serialVersionUID = 1L;
/**
* the {@link SignalMLCodecManager manager} of {@link SignalMLCodec codecs}
*/
private SignalMLCodecManager codecManager;
/**
* the {@link SignalMLCodec codec} read in this dialog
*/
private jsignalml.compiler.CompiledClass<? extends jsignalml.Source> currentCodec;
/**
* the profile directory
*/
private File profileDir;
/**
* Constructor. Sets parent window and if this dialog
* blocks top-level windows.
* @param f the parent window or null if there is no parent
* @param dialog blocks top-level windows if true
*/
public RegisterCodecDialog(Window f, boolean isModal) {
super(f, isModal);
}
/**
* Initializes this dialog:
* <ul><li>sets the title and icon for this dialog,</li>
* <li>adds a listener which {@link #checkNameExists(String) checks} if
* the {@link SignalMLCodec codec} of that name exists and displays the
* warning,</li>
* <li>calls {@link AbstractWizardDialog#initializeNow() initialization}
* in parent class.</li></ul>
*/
@Override
protected void initialize() {
setTitle(_("Register a new SignalML codec"));
setIconImage(IconUtils.loadClassPathImage("org/signalml/app/icon/fileopen.png"));
super.initialize();
getStepTwoPanel().getNameField().getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
react(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
react(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
react(e);
}
private void react(DocumentEvent e) {
try {
checkNameExists(e.getDocument().getText(0, e.getDocument().getLength()));
} catch (BadLocationException ex) {
logger.error("Sanity exception", ex);
}
}
});
}
/**
* Returns the number of steps, which equals {@code two}
*/
@Override
public int getStepCount() {
return 2;
}
/**
* If it is the change from first step to second puts the
* {@link XMLSignalMLCodec#getFormatName() name} of the codec in the
* {@link RegisterCodecStepTwoPanel#getName() text field} and
* {@link #checkNameExists(String) checks} if such name already exists.
*/
@Override
protected boolean onStepChange(int toStep, int fromStep, Object model) {
if (fromStep == 0) {
String defaultFormatName = currentCodec.fullName; // XXX
getStepTwoPanel().getNameField().setText(defaultFormatName);
checkNameExists(defaultFormatName);
}
return true;
}
/**
* For step one:
* <ul><li>checks if the file is {@link EmbeddedFileChooser#validateFile(
* Errors, String, boolean, boolean, boolean, boolean, boolean) valid} and
* </li><li>creates the {@link XMLSignalMLCodec codec}</li>
* </ul>
* For step two:
* <ul><li>checks if the name of the codec is valid.</li></ul>
*/
@Override
public void validateDialogStep(int step, Object model, ValidationErrors errors) throws SignalMLException {
if (step == 0) {
EmbeddedFileChooser fileChooser = getStepOnePanel().getFileChooser();
fileChooser.validateFile(errors, "sourceFile", false, false, false, false, true);
if (!errors.hasErrors()) {
File file = fileChooser.getSelectedFile();
try {
currentCodec = RegisterCodecAction.loadFromFile("compiled2", file);
} catch (IOException ex) {
logger.debug("Failed to read codec file", ex);
errors.addError(_("Failed to read file"));
} catch (Exception ex) {
logger.debug("Failed to compile codec file", ex);
errors.addError(_("Failed to compile the codec"));
}
}
} else if (step == 1) {
String name = getStepTwoPanel().getNameField().getText();
if (name == null || name.length() == 0) {
errors.addError(_("Format name must be set"));
}
if (Util.hasSpecialChars(name)) {
errors.addError(_("Format name must not contain control characters"));
}
}
}
/**
* Checks if there {@link SignalMLCodecManager#getCodecForFormat(String)
* is} a {@link SignalMLCodec codec} of a given name.
* If there is makes the {@link RegisterCodecStepTwoPanel#getWarningLabel()
* warning label} in step two visible, otherwise makes it invisible.
* @param formatName the name of the codec
*/
private void checkNameExists(String formatName) {
if (codecManager.getCodecForFormat(formatName) != null) {
getStepTwoPanel().getWarningLabel().setVisible(true);
} else {
getStepTwoPanel().getWarningLabel().setVisible(false);
}
}
/**
* Calls the {@link AbstractWizardDialog#resetDialog() reset function} in
* parent and makes the {@link RegisterCodecStepTwoPanel#getWarningLabel()
* warning label} in step two invisible.
*/
@Override
protected void resetDialog() {
super.resetDialog();
getStepTwoPanel().getWarningLabel().setVisible(false);
}
/**
* Creates the interface for step:
* <ul><li>one - {@link RegisterCodecStepOnePanel},</li>
* <li>two - {@link RegisterCodecStepTwoPanel},</li></ul>
* @throws IndexOutOfBoundsException if the number of the step is
* different from 1 or 2
*/
@Override
public JComponent createInterfaceForStep(int step) {
switch (step) {
case 0 :
return new RegisterCodecStepOnePanel();
case 1 :
return new RegisterCodecStepTwoPanel();
default :
throw new IndexOutOfBoundsException();
}
}
/**
* Finish is allowed only for the last (second) step.
*/
@Override
public boolean isFinishAllowedOnStep(int step) {
return (step == (getStepCount() - 1));
}
/**
* Returns the {@link RegisterCodecStepOnePanel panel} for the first
* step.
* @return the panel for the first step
*/
public RegisterCodecStepOnePanel getStepOnePanel() {
return (RegisterCodecStepOnePanel) getInterfaceForStep(0);
}
/**
* Returns the {@link RegisterCodecStepTwoPanel panel} for the second
* step.
* @return the panel for the second step
*/
public RegisterCodecStepTwoPanel getStepTwoPanel() {
return (RegisterCodecStepTwoPanel) getInterfaceForStep(1);
}
/**
*
*/
@Override
public void fillDialogFromModel(Object model) throws SignalMLException {
RegisterCodecDescriptor rcd = (RegisterCodecDescriptor) model;
File f = rcd.getSourceFile();
if (f == null) {
f = new File("");
}
getStepOnePanel().getFileChooser().setSelectedFile(f);
}
@Override
public void fillModelFromDialog(Object model) throws SignalMLException {
RegisterCodecDescriptor rcd = (RegisterCodecDescriptor) model;
rcd.setSourceFile(getStepOnePanel().getFileChooser().getSelectedFile());
rcd.setCodec(new JsignalmlCodec(currentCodec));
rcd.setFormatName(getStepTwoPanel().getNameField().getText());
}
/**
* Model have to have type {@link RegisterCodecDescriptor}.
*/
@Override
public boolean supportsModelClass(Class<?> clazz) {
return RegisterCodecDescriptor.class.isAssignableFrom(clazz);
}
/**
* Returns the {@link SignalMLCodecManager manager} of
* {@link SignalMLCodec codecs}.
* @return the manager of codecs
*/
public SignalMLCodecManager getCodecManager() {
return codecManager;
}
/**
* Sets the {@link SignalMLCodecManager manager} of
* {@link SignalMLCodec codecs}.
* @param codecManager the manager of codecs
*/
public void setCodecManager(SignalMLCodecManager codecManager) {
this.codecManager = codecManager;
}
/**
* Returns the profile directory.
* @return the profile directory
*/
public File getProfileDir() {
return profileDir;
}
/**
* Sets the profile directory.
* @param profileDir the profile directory
*/
public void setProfileDir(File profileDir) {
this.profileDir = profileDir;
}
}