Search

Mark Ashworth

Designing applications, writing, photography and reading

Calculating string differences

compare-differences-persons-after

The Apache Commons Text library comes with some nifty string comparison routines which is nicely demonstrated by Baeldung in his Introduction to Apache Commons Text.

Instead of only calculating the difference, I wanted to visually display those differences to the user as shown above. To accomplish this I used the CommandVisitor interface to iterate through the differences and mark them appropriately.

final String left = "Phillips";
final String right = "Phillip";

MarkupCommandVisitor visitor = new MarkupCommandVisitor();
new StringsComparator(left, right).getScript().visit(visitor);

System.out.println(visitor.getMarkup());

Here is the implementation of the MarkupCommandVisitor demonstrating how the insert and delete differences are marked up between the two strings.

static class MarkupCommandVisitor implements CommandVisitor {

    private static final String CLASS_INSERT = "diff_insert";
    private static final String CLASS_DELETE = "diff_delete";
    private static final String SPAN_PREFIX = "";
    private static final String SPAN_END = "";

    /**
     * A map containing the command and the CSS class
     */
    private Map<Command, String> markUpCommands = new HashMap<>();
    /**
     * The current command
     */
    private Command command = Command.NONE;
    /**
     * The buffer for the diff text
     */
    private StringBuffer buffer = new StringBuffer();

    public MarkupCommandVisitor() {
        this.markUpCommands.put(Command.DELETE, CLASS_DELETE);
        this.markUpCommands.put(Command.INSERT, CLASS_INSERT);
    }

    public String getMarkup() {
        if (isCurrentMarkupCommand()) {
            visit(Command.END, Optional.empty());
        }

        return this.buffer.toString();
    }

    public void visitInsertCommand(final Character character) {
        visit(Command.INSERT, Optional.of(character));
    }

    public void visitKeepCommand(final Character character) {
        visit(Command.KEEP, Optional.of(character));
    }

    public void visitDeleteCommand(final Character character) {
        visit(Command.DELETE, Optional.of(character));
    }

    private void visit(final Command nextCommand, final Optional character) {

        if (!isCurrentCommand(nextCommand)) {
            /* Close off the current marked-up command */
            if (isCurrentMarkupCommand()) {
                buffer.append(SPAN_END);
            }
            /* Open the next marked-up command */
            if (isMarkupCommand(nextCommand)) {
                buffer.append(SPAN_PREFIX);
                buffer.append(this.markUpCommands.get(nextCommand));
                buffer.append(SPAN_POSTFIX);
            }
        }
        character.ifPresent(buffer::append);
        command = nextCommand;
    }

    private boolean isMarkupCommand(final Command command) {
        return this.markUpCommands.containsKey(command);
    }

    private boolean isCurrentMarkupCommand() {
        return this.markUpCommands.containsKey(this.command);
    }

    private boolean isCurrentCommand(final Command command) {
        return this.command == command;
    }
}

Here is how the original screen used to look without the HTML markup to indicate that the two strings were different.

compare-differences-persons-before

The code is available on GitHub at https://github.com/markash/threesixty-tutorial.

Advertisements

Sending email to Gmail in Apache Camel

Setting up Gmail

All of the advise that most site provide is that you should allow less secure access to your Gmail account during the testing and then turn this setting off again afterwards.

Gmail 2-Step Verification

What I have found to work better is to enable 2-Step verification on your Gmail account and then to generate an App Password for the application instead of using the email account password.

App Password

Browse to the Sign-in and security section of the Gmail account and under the 2-Step Verification you’ll find the App Password section.

2017-05-03 Gmail Security Settings

After confirming your password, all the App Password are displayed and a link to generate a new App Password. The App Password will be used later instead of the email account password.

2017-05-03 Gmail App Password

Importing the Gmail certificate into the Java Keystore

I could only find two methods to retrieve the Google Gmail certificate, one being OpenSSL and the other being Python. Now my development machine is Windows and I did not want to go through the pain of setting up Cygwin only to execute one command so I instead opted for the Python approach. As a side note, I wanted to find a pure Java solution but to date have found none.

Python

import smtplib
import ssl

connection = smtplib.SMTP()
connection.connect('smtp.gmail.com')
connection.starttls()

f1=open('./gmail.pem', 'w+')
print >> f1, ssl.DER_cert_to_PEM_cert(connection.sock.getpeercert(binary_form=True))

The preceding code connects to smtp.gmail.com and saves the certificate in the PEM Base64 encoding.

OpenSSL

To be honest there are enough sources on the net on how to use OpenSSL to retrieve a certificate, so I will not polute the net with yet another.

Creating the certificate keystore

keytool -keystore cacerts.jks -importcert -alias gmail -file gmail.pem
keytool -list -keystore cacerts.jks

I guess the commands are pretty self explanatory, since the first performs the actual creation of the cacerts.jks file with the certificate gmail.pem being aliased by the name gmail. The second command lists the certificates within the cacerts.jks file.

Providing the SSL Context Parameters

Configuration

In the application.properties define the properties for the location and the password for the keystore. A neat feature of Spring Boot is that the password can be overwritten by providing a environment variable THREESIXTY_KEYSTORE_PASSWORD which will keep the actual password away from prying eyes or opt for HashCorp Vault to keep this.

# Keystore
threesixty.keystore.location=C:\\tmp\\cacerts.jks
threesixty.keystore.password=password

Bean

Next provide the creation of the SSLContextParameters object from the keystore location and password for Apache Camel.

@Bean
   public SSLContextParameters sslContextParameters(
          @Value("threesixty.keystore.location") final String location,
      @Value("threesixty.keystore.password") final String password) {

       KeyStoreParameters store = new KeyStoreParameters();
       store.setResource(location);
       store.setPassword(password);

       TrustManagersParameters trust = new TrustManagersParameters();
       trust.setKeyStore(store);

    SSLContextParameters parameters = new SSLContextParameters();
    parameters.setTrustManagers(trust);

    return parameters;
   }

Configuring a route to deliver a file to email

The route polls the directory for files and then enriches the exchange with a header field that will contain the attachment (i.e. the file itself) and then routes the file to the email smtps endpoint which will use the file as the body and as an attachment.

from("file:C://tmp/camel")
                 .routeId("DELIVER001")
                 .routeDescription("Deliver file to Gmail")
                 .bean(new AttachmentProcessor())
                 .to("smtps:smtp.gmail.com:465?username=<Gmail Email Address>&password=<App Password>&to=somebody@gmail.com&subject=Test&debugMode=true&mail.smtp.auth=true&mail.smtp.starttls.enable=true");

 

public class AttachmentProcessor implements Processor {
    @Handler
    public void process(Exchange exchange) {

        try {
            byte[] file = exchange.getIn().getBody(byte[].class);
            String fileName = exchange.getIn().getHeader("CamelFileName", String.class);
            String path = exchange.getIn().getHeader("CamelFileAbsolutePath", String.class);
            String mimeType = Files.probeContentType(Paths.get(path));

            exchange.getIn().setHeader("mimeType", mimeType);
            exchange.getIn().addAttachment(fileName, new DataHandler(new ByteArrayDataSource(file, mimeType)));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

A review of JavaScript drawing libraries for flowcharts, Gantt charts and timelines

Dr James Bayley

Overview

I manage my projects using my own ElephantPM project management methodology. This is a similar in many ways to PRINCE2 but is greatly simplified so that it is suitable for use by smaller organisations.

My needs

ElephantPM divides the Start-up stage into an analysis step and a planning step. During the analysis step it is necessary to create several diagrams,

  • A mind map showing the output of the Discovery Workshop
  • An “org chart” showing the breakdown of the project into Business Deliverables
  • A flow chart showing the order in which Business Deliverables should be made
  • A diagram showing the relationship between stages and the production of Business Deliverables

During the planning step it is necessary to produce

  • Gantt Charts showing the Project Schedule and Stage Schedules

Current solution

Over the years I have used various tools to produce these charts but I have now settled on Freemind and Microsoft Project 2010.

View original post 1,313 more words

Compute the RANK() for a group of records

Say for example that you have a table with transactions and you would like to index the records from 1…n on each supplier id and potentially at the same time do this in transaction date sequence.

Continue reading “Compute the RANK() for a group of records”

Three Sixty Material Design

Using the Material Design Bootstrap for the new version of ThreeSixty to conceptualize the design possible to make the user of the application easier for users. Have a look at https://threesixy-pathfinder.herokuapp.com/ and if you have any ideas those would be welcomed 🙂

threesixty-pathfinder

To generate a logo of a Font Awesome Icon is real simple using the Logo Generator at MDB.

Below is the Three Sixty logo on the new proof on concept implementation based upon Google’s Material Design with the help of mdbootstrap.com.
2016-03-02 Pathfinder example logo

The first version released of the ThreeSixty web application to streamline the 360 review process for managers and employees.

Demo available at yellowfire-threesixty.herokuapp.com

Code available on GitHub https://github.com/markash/threesixty

Stanley Plane for Christmas ;-)

Courage

Courage is not simply one of the virtues, but the form of every virtue at the testing point. C. S. Lewis

Blog at WordPress.com.

Up ↑