edu.kit.iks.Cryptographics.Caesar.Demonstration.CryptoDemonstrationController.java Source code

Java tutorial

Introduction

Here is the source code for edu.kit.iks.Cryptographics.Caesar.Demonstration.CryptoDemonstrationController.java

Source

/**
 * Copyright (c) 2014 Matthias Jaenicke <matthias.jaenicke@student.kit.edu>,
 * Matthias Plappert <undkc@student.kit.edu>,
 * Julien Duman <uncyc@student.kit.edu>, 
 * Christian Dreher <uaeef@student.kit.edu>,
 * Wasilij Beskorovajnov <uajkm@student.kit.edu> and 
 * Aydin Tekin <aydin.tekin@student.kit.edu>
 * 
 * Released under the MIT license (refer to LICENSE.md)
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package edu.kit.iks.Cryptographics.Caesar.Demonstration;

import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.io.InputStream;

import javax.swing.BorderFactory;
import javax.swing.JTextField;

import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.xnap.commons.i18n.I18n;

import edu.kit.iks.Cryptographics.VisualizationContainerController;
import edu.kit.iks.Cryptographics.Caesar.Experiment.CryptoModel;
import edu.kit.iks.CryptographicsLib.AbstractVisualizationController;
import edu.kit.iks.CryptographicsLib.AbstractVisualizationInfo;
import edu.kit.iks.CryptographicsLib.AlphabetStripView;
import edu.kit.iks.CryptographicsLib.Configuration;
import edu.kit.iks.CryptographicsLib.ImageView;
import edu.kit.iks.CryptographicsLib.KeyboardView;
import edu.kit.iks.CryptographicsLib.Logger;
import edu.kit.iks.CryptographicsLib.MouseClickListener;

/**
 * Controller for the last step of demonstration phase. Controls the needed elements from
 * {@link CryptoDemonstrationView}
 * 
 * @author Wasilij Beskorovajnov.
 * 
 */
public class CryptoDemonstrationController extends AbstractVisualizationController {

    /**
     * localization.
     */
    private static I18n i18n = Configuration.getInstance().getI18n(CryptoDemonstrationController.class);

    /**
     * Identicates the step of the demonstration.
     */
    private int demonstrationStep;

    /**
     * Indicates how much fields left to edit.
     */
    private int editableFields;

    /**
     * The model of this controller.
     */
    private CryptoModel model;

    private Element cryptoResources;

    /**
     * Constructor.
     * 
     * @param visualizationInfo
     */
    public CryptoDemonstrationController(AbstractVisualizationInfo visualizationInfo) {
        super(visualizationInfo);

        SAXBuilder saxBuilder = new SAXBuilder();

        // obtain file object
        InputStream is = this.getClass().getResourceAsStream("/caesar/CaesarResources.xml");

        try {
            // converted file to document object
            Document document = saxBuilder.build(is);

            // get root node from xml
            this.cryptoResources = document.getRootElement();
        } catch (JDOMException | IOException e) {
            Logger.error(e);
        }
    }

    @Override
    public void loadView() {
        this.view = new CryptoDemonstrationView();
        this.model = CryptoModel.getInstance();

        // set the initial first step.
        this.demonstrationStep = 1;

        // generate ActionListener for the navigationButtons.
        this.generateNavigationListener();

        // generate ActionListener for the forwarding button proceed.
        this.generateProceedListener();

        for (int i = 1; i < this.getView().getUserOutput().length; i++) {
            // Needed for delegating to the inner type ActionListener, when the actionEvent from the
            // Button "ENTER" on the Keyboard is fired.
            final JTextField userOutput = this.getView().getUserOutput()[i];

            // FocusListener for the textfields.
            this.generateUserOutputFocusListener(i, userOutput);
            // actionListener for the textfields.
            this.generateUserOutputActionListener(i, userOutput);
        }

        this.getView().validate();
    }

    /**
     * Gets the view
     * 
     * @return The view of this controller
     */
    @Override
    public CryptoDemonstrationView getView() {
        return (CryptoDemonstrationView) this.view;
    }

    // ---------------------------------------------------------//
    // -----------------private methods-------------------------//

    /**
     * Function for performing the needed demonstration. After each step the demonstration stops and
     * continues when user wishes.
     * 
     * @param step
     *            {@link demonstrationStep}
     */
    private void demonstrate(int step) {
        switch (step) {
        case 1:
            this.step1();
            break;
        case 2:
            this.step2();
            break;
        case 3:
            this.step3();
            break;
        default:

        }

    }

    private void generateUserOutputActionListener(int i, final JTextField userOutput) {
        this.getView().getUserOutput()[i].addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (userOutput.isEditable()) {
                    if (CryptoDemonstrationController.this.getModel().enc(3, userOutput.getName())
                            .equals(userOutput.getText())) {

                        // user encrypted the given char successful.
                        CryptoDemonstrationController.this.presentSuccessfullCharEncrypt(userOutput);

                        if (CryptoDemonstrationController.this.getEditableFields() == 0
                                && CryptoDemonstrationController.this.getAnimationStep() == 4) {

                            // User encrypted all characters valid.
                            CryptoDemonstrationController.this.getView().getExplanations().setText(
                                    CryptoDemonstrationController.this.wrapHtml(CryptoDemonstrationController.i18n
                                            .tr("Great work oh mighty Caesar. May your enemies shutter over your intelligence."
                                                    + " Now we can move on to the real experiment and test your skills.")));

                            // remove all unnecessary elements.
                            CryptoDemonstrationController.this.presentFinish();
                            CryptoDemonstrationController.this.getView().removeKeyboard();

                        } else if (CryptoDemonstrationController.this.getEditableFields() == 0
                                && CryptoDemonstrationController.this.getAnimationStep() == 3) {

                            // User has to encrypt the last 3 fields.
                            CryptoDemonstrationController.this.prepareNextToLastStep(userOutput);
                            CryptoDemonstrationController.this.getView().getExplanations().setText(
                                    CryptoDemonstrationController.this.wrapHtml(CryptoDemonstrationController.i18n
                                            .tr("Very nice! Let's encrypt the rest of your name. Touch proceed.")));
                            CryptoDemonstrationController.this.setFeedbackImage("CaesarPositive");
                        } else {
                            // User encrypted correctly the given char.
                            CryptoDemonstrationController.this.getView().getExplanations()
                                    .setText(CryptoDemonstrationController.this.getModel().genRandomGrats() + " "
                                            + CryptoDemonstrationController.i18n.trn("Only {0} left.",
                                                    "Only {0} left.",
                                                    CryptoDemonstrationController.this.getEditableFields(),
                                                    CryptoDemonstrationController.this.getEditableFields()));
                            CryptoDemonstrationController.this.setFeedbackImage("CaesarPositive");

                            // The next textfield to the right requests now the focus.
                            CryptoDemonstrationController.this.getView()
                                    .getUserOutput()[CryptoDemonstrationController.this.getView()
                                            .getUserOutput().length
                                            - CryptoDemonstrationController.this.getEditableFields()]
                                                    .requestFocus();
                        }
                    } else {
                        // User didn't encrypt correctly.
                        CryptoDemonstrationController.this.getView().getExplanations()
                                .setText(CryptoDemonstrationController.this.getModel().genRandomBlamings());
                        userOutput.setText("");
                        CryptoDemonstrationController.this.setFeedbackImage("CaesarNegative");

                        userOutput.requestFocus();
                    }
                }
            }
        });
    }

    private void setFeedbackImage(String resourceID) {
        this.getView().getFeedback().removeAll();
        String path = "";
        try {
            path = CryptoDemonstrationController.this.getCryptoResource().getChild("CryptoResources")
                    .getChild(resourceID).getAttributeValue("path");
        } catch (NullPointerException nullException) {
            //Element not found.
            System.out.println("[NullPointerException] Ressource not found.");
            nullException.printStackTrace();
        }

        GridBagConstraints imgConstraint = new GridBagConstraints();
        imgConstraint.gridx = this.getView().getUserInput().length + 1;
        imgConstraint.gridy = 0;
        ImageView imageToSet = new ImageView(path);
        this.getView().getFeedback().add(imageToSet, imgConstraint);

        this.getView().validate();
        this.getView().repaint();
    }

    private void generateUserOutputFocusListener(int i, final JTextField userOutput) {
        this.getView().getUserOutput()[i].addFocusListener(new FocusListener() {
            @Override
            public void focusGained(FocusEvent e) {

                JTextField output = (JTextField) e.getSource();
                // resets the highlighting.
                CryptoDemonstrationController.this.resetStateOfIOFields();

                if (CryptoDemonstrationController.this.getView().getKeyboard() != null) {
                    // remove the keyboard.
                    CryptoDemonstrationController.this.getView().removeKeyboard();
                }
                if (output.isEditable()) {
                    // highlights the character in the alphabet.
                    CryptoDemonstrationController.this.highlightInputField(userOutput);
                }
            }

            @Override
            public void focusLost(FocusEvent e) {
                // Nothing to do here.
            }
        });
    }

    private void generateProceedListener() {
        this.getView().getProceed().addMouseListener(new MouseClickListener() {
            @Override
            public void clicked(MouseEvent e) {
                CryptoDemonstrationController.this
                        .demonstrate(CryptoDemonstrationController.this.getAnimationStep());
            }
        });

    }

    private void generateNavigationListener() {
        this.getView().getBackButton().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                VisualizationContainerController containerController = (VisualizationContainerController) CryptoDemonstrationController.this
                        .getParentController();
                containerController.presentPreviousVisualizationController();
            }
        });
        this.getView().getNextButton().addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent event) {
                VisualizationContainerController containerController = (VisualizationContainerController) CryptoDemonstrationController.this
                        .getParentController();
                containerController.presentNextVisualizationController();
            }
        });
    }

    private void prepareNextToLastStep(JTextField userOutput) {
        this.getView().requestFocus();
        this.getView().removeKeyboard();
        this.getView().getProceed().setVisible(true);
        this.getView().getAlphabet().unHighlight(userOutput.getName().charAt(0) - this.getModel().ASCII_UC_A);
    }

    private void presentSuccessfullCharEncrypt(JTextField userOutput) {
        userOutput.setBorder(BorderFactory.createLineBorder(Color.green));
        this.setEditableFields(this.getEditableFields() - 1);
        userOutput.setEditable(false);
    }

    private void presentFinish() {
        this.getView().removeAlphabet();

        this.getView().getNavigationPanel().remove(this.getView().getNextButton());
        GridBagConstraints nextConst = new GridBagConstraints();
        nextConst.anchor = GridBagConstraints.CENTER;
        nextConst.weightx = 1.0;
        nextConst.weighty = 0.1;
        nextConst.gridx = 1;
        nextConst.gridy = 1;
        nextConst.gridwidth = 26;
        nextConst.gridheight = 2;
        this.getView().add(this.getView().getNextButton(), nextConst);

        this.getView().requestFocus();
    }

    private void highlightInputField(JTextField output) {
        int charToEncryptAscii = output.getName().charAt(0);
        AlphabetStripView viewAlphabet = this.getView().getAlphabet();
        viewAlphabet.highlight(charToEncryptAscii - this.getModel().ASCII_UC_A);

        output.setBorder(BorderFactory.createLineBorder(Color.blue, 5));
        this.getView().createKeyboard(output, KeyboardView.CHAR_MODE);
    }

    private void resetStateOfIOFields() {
        for (JTextField outputIterator : this.getView().getUserOutput()) {

            if (outputIterator.getText() != null
                    && CryptoDemonstrationController.this.getView().getAlphabet() != null) {
                int charToEncryptAscii = outputIterator.getName().charAt(0);
                AlphabetStripView viewAlphabet = CryptoDemonstrationController.this.getView().getAlphabet();
                viewAlphabet
                        .unHighlight(charToEncryptAscii - CryptoDemonstrationController.this.getModel().ASCII_UC_A);
                if (outputIterator.isEditable()) {
                    outputIterator.setBorder(BorderFactory.createLineBorder(Color.darkGray));
                }
            }
        }
    }

    /**
     * Explain the elements on the screen. Only explanations are shown.
     */
    private void step1() {
        this.demonstrationStep++;
        this.getView().getExplanations().setText(this.wrapHtml(CryptoDemonstrationController.i18n
                .tr("Because of your inferior intelligence you look at the first letter of your name: C."
                        + " Then you look at the 3rd letter after C and take F. Great! Now you encrypted the"
                        + " first letter of your name. Touch proceed.")));
        //       setup the alphabet.
        this.getView().setupAlphabet();
        this.getView().getUserInput()[0].setBorder(BorderFactory.createLineBorder(Color.green));
        this.getView().getUserOutput()[0].setBorder(BorderFactory.createLineBorder(Color.green));
        this.getView().getUserOutput()[0].setText("F");
        this.getView().validate();
    }

    /**
     * Describe how each character is encrypted.
     */
    private void step2() {
        this.demonstrationStep++;
        this.editableFields = 1;
        this.getView().getProceed().setVisible(false);
        this.getView().getUserInput()[0].setBorder(null);
        this.getView().getUserOutput()[0].setBorder(null);
        this.getView().getExplanations().setText(
                this.wrapHtml(CryptoDemonstrationController.i18n.tr("Now try to encrypt the next letter yourself."
                        + " If you need help, you can always use the help button.")));

        this.getView().getUserInput()[1].setBorder(BorderFactory.createLineBorder(Color.green));
        this.getView().getUserOutput()[1].setEditable(true);
        this.getView().getUserOutput()[1].requestFocus();
        this.getView().validate();
    }

    /**
     * Describe the general Caesar cipher. (The key can vary from 1-26.)
     */
    private void step3() {
        this.demonstrationStep++;
        this.editableFields = (this.getView().getUserInput().length - 2);
        this.getView().getForwardingViewContainer().remove(this.getView().getProceed());
        this.getView().setProceed(null);
        this.getView().getUserInput()[1].setBorder(null);
        this.getView().getUserOutput()[1].setBorder(null);
        for (int i = 2; i < this.getView().getUserInput().length; i++) {
            this.getView().getUserOutput()[i].setEditable(true);
        }
        this.getView().getExplanations().setText(this.wrapHtml(CryptoDemonstrationController.i18n
                .tr("Oh mighty Caesar. No one will ever be able to destroy you! Because of that fact lets end"
                        + " this childish games and finish the rest of the fields fast. Then we can send the courier again"
                        + " but this time your enemies will have no idea who wrote it and you will conquer the world.")));
        this.getView().getUserOutput()[2].requestFocus();
        this.getView().validate();

    }

    // -------------------------------------------------------//
    // -------------------Getter/Setter-----------------------//

    /**
     * @return the animationStep
     */
    public int getAnimationStep() {
        return this.demonstrationStep;
    }

    /**
     * @return the editableFields
     */
    public int getEditableFields() {
        return this.editableFields;
    }

    @Override
    public String getHelp() {
        String help = CryptoDemonstrationController.i18n.tr(
                "Remember: Position of C in the alphabet is 3 and the key is also 3. C + key = C + 3 = 3 + 3 = 6."
                        + " And 6 is the position of letter F in the alphabet. Et voila you encrypted C with the key of 3.");

        return help;
    }

    /**
     * @return the model
     */
    public CryptoModel getModel() {
        return this.model;
    }

    /**
     * @param animationStep
     *            the animationStep to set
     */
    public void setAnimationStep(int animationStep) {
        this.demonstrationStep = animationStep;
    }

    /**
     * @param editableFields
     *            the editableFields to set
     */
    public void setEditableFields(int editableFields) {
        this.editableFields = editableFields;
    }

    /**
     * @param model
     *            the model to set
     */
    public void setModel(CryptoModel model) {
        this.model = model;
    }

    @Override
    public void unloadView() {
        this.view = null;
    }

    private String wrapHtml(String text) {
        return "<html><body><div width=700px>" + text + "</div></body></html>";
    }

    /**
     * @return the cryptoResource
     */
    public Element getCryptoResource() {
        return cryptoResources;
    }

    /**
     * @param cryptoResource the cryptoResource to set
     */
    public void setCryptoResource(Element cryptoResource) {
        this.cryptoResources = cryptoResource;
    }
}