A Simple Encryption app in JavaFX

OK, So Here is another toy app i wrote to understand Multi-threading in JavaFX.
The main focus of this app is to understand multi-threading in JavaFX. So, Do not use it for any real world encryption,

By the way the algorithm that i used in this app was found in a python module called "this" also known as "Zen of Python".


Here is the main logic of the app. You can find full repo on Github or Download Standalone jar

/**
imports omitted for brevity  
**/

/**
 *
 * @author Aamir khan
 */

public class FXMLDocumentController implements Initializable {

    @FXML
    private TextArea input;
    @FXML
    private TextArea output;
    @FXML
    private Label counter;
    @FXML
    private Label progress;
    @FXML
    private Label progressMsg;
    @FXML
    private Button btn;
    @FXML
    private Label stopTask;

    final ImageView DONE_ICON = new ImageView(
            new Image(getClass().getResourceAsStream("sign-check.png")));

    StringBuilder demoText;

    private Map<character character> encodingMap;

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        init();
        prepareMap(encodingMap);
        bindNodes();
    }

    @FXML
    private void encrypt(ActionEvent event) {
        startTask();
    }

    Service<void> task = new Service() {

        @Override
        protected Task createTask() {
            return new Task<void>() {

                long start = 0L;
                long stop = 0L;

                @Override
                protected Void call() throws Exception {
                    String inputText = input.getText();
                    final float INPUT_LEN = inputText.length();
                    StringBuilder result = new StringBuilder((int)INPUT_LEN);

                    start = System.nanoTime();

                    for (char c : inputText.toCharArray()) {
                        Character ch = encodingMap.getOrDefault(c, c);
                        result.append(ch);

                        String percent = String.format("%.2f", (result.length() / INPUT_LEN) * 100);
                        updateMessage("Processing... " + percent + "%");

                        if (isCancelled()) {
                            updateMessage("Task Was Cancelled " + percent + "% was done");
                            break;
                        }

                    }
                    stop = System.nanoTime();

                    Platform.runLater(() -&gt; {
                        output.setText(result.toString());
                    });

                    return null;
                }

                @Override
                protected void succeeded() {
                    progressMsg.setText("Done. in " + (stop - start) / 1000000000.0 + " sec");
                    progressMsg.setGraphic(DONE_ICON);
                    updateMessage("");
                }

            };
        }

    };

    boolean wasStartedBefore = false;

    /**
     * start or restart the task
     */
    private void startTask() {

        if (wasStartedBefore) {
            task.restart();
        } else {
            task.start();
            wasStartedBefore = true;
        }

    }

    @FXML
    private void cancleTask() {
        progress.setTextFill(Color.RED);
        task.cancel();
    }

    /**
     * fills the @link{Map} with chars according to the algo <strong> ((i + 13) % 26 +c)</strong>
     * 
where i represents [a-z]
     * 
where c represents the range of [a-z] and [A-Z]
     * 
* <b>Note:the algorithm was copied form the python Module called "this"</b>
     *
     * @param map
     */
    private void prepareMap(Map map) {

        System.out.println("preparing map");
        for (int c : new int[]{65, 97}) {

            for (int i = 0; i &lt; 26; i++) {

                Character key = (char) (i + c);
                Character value = (char) ((i + 13) % 26 + c);

                map.put(key, value);
            }
        }

    }//prepareMap ENDS

    //avoid re generating the text
    boolean wasTextNotGeneratedBefore = true;

    /**
     * Fill input field with some demo text
     */
    @FXML
    private void fillWithDemoText() {
        //if Text was not generated before genetate it
        if (wasTextNotGeneratedBefore) {
            generateDemoTextAndFill();
            wasTextNotGeneratedBefore = false;
        } //if text was generated before fill the input with some random text &gt; 200000 characteres
        else {
            //just fill with some random data
            input.setText(demoText.substring(0, (int) (200000 + Math.random() * 500)));
        }

    }//fillWithDemoText ends

    /**
     * * Bind the properties to keep track the state of app  
     * - keep track of input field changes and update the counter 
     * - keep track of input field if its empty disable the encrypt/decrypt
     * button 
     * - keep track of task property if a task is running disable the
     * encrypt/decrypt button till task is running
     * - keep update the progress Msg while task is running
     * - show the stop task label as the user start the task - Mor to come
     * 
     */
    private void bindNodes() {

        //keep track of input field changes and update the counter
        counter.textProperty().bind(input.textProperty().length().asString());

        //keep track of input field if its empty disable the encrypt/decrypt button
        btn.disableProperty().bind(input.textProperty().isEmpty()
                .or(task.stateProperty().isEqualTo(RUNNING))
        );
        //keep update the progress Msg while task is running
        progress.textProperty().bind(task.messageProperty());
        //show the stop task label as the user start the task
        stopTask.visibleProperty().bind(task.stateProperty().isEqualTo(RUNNING));

    }

    /**
     * initialize things
     */
    private void init() {
        encodingMap = new HashMap&lt;&gt;(52);
        stopTask.setTooltip(new Tooltip("Cancle Task"));
        //Some House keeping 
        task.setOnReady(e -&gt; {
            progressMsg.setText("");
            progressMsg.setGraphic(null);
            progress.setTextFill(Color.web("#078ffa"));
            output.clear();
        });
    }

    /**
     * Generate some Demo Text and fill the input filed with the Text
     */
    private void generateDemoTextAndFill() {

        new Thread() {//in future i am gonna use Executors

            String data = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod\n"
                    + "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,\n"
                    + "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo\n"
                    + "consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse\n"
                    + "cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non\n"
                    + "proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\n\n";

            @Override
            public void run() {
                final int BUILDER_SIZE = (data.length() * data.length());
                demoText = new StringBuilder(BUILDER_SIZE);

                for (int i = 0; i &lt; data.length(); i++) {
                    demoText.append(data);
                }

                Platform.runLater(() -&gt; {
                    input.setText(demoText.toString());
                });

            }

        }.start();
    }

}



No comments :

Post a Comment