Liang’s hyphenation algorithm implementation in node.js

Currently I am involved in a project that requires some string hyphenation. Initially I took a shot by using Liang’s hyphenation algorithm (taken from here liang hyphenation in python).
However it could not match my needs therefore I had to switch to the one open-office uses.

Anyway here it is the javascript implementation as a node.js module.


function LiangHyphenator(patterns) {

    this.tree = {}
    this.patterns = patterns

    for(var i= 0;i<patterns.length;i++) {
        var pattern = patterns[i]

        this.__insertPattern(pattern)
    }

}

LiangHyphenator.prototype.__insertPattern = function(pattern) {

    var chars = this.__clearPattern(pattern)
    var points = this.__createPoints(pattern)

    this.__addPatternToTree(points,chars)
}

LiangHyphenator.prototype.__clearPattern = function(pattern) {
    var numericsExpression = new RegExp('[0-9]','g')
    return pattern.replace(numericsExpression,'')
}

LiangHyphenator.prototype.__createPoints = function(pattern) {

    var charExpression = new RegExp('[.a-z]','g')
    var splitted = pattern.split(charExpression)

    for(var i= 0;i<splitted.length;i++) {
        if(splitted[i]==='') {
            splitted[i]=0
        } else {
            splitted[i] = parseInt(splitted[i])
        }
    }

    return splitted
}

LiangHyphenator.prototype.__addPatternToTree = function(points,chars) {
    var tree = this.tree
    for(var i=0;i<chars.length;i++) {

        var c = chars[i]
        if(!tree[c]) {
            tree[c] = {}
        }
        tree = tree[c]

    }


    tree['None'] = points
}

LiangHyphenator.prototype.hyphenateWord = function(word) {
    if(word.length<=4) {
        return [word]
    }

    var work = '.'+word.toLowerCase()+'.'

    var points = this.__createZeroArray(work.length+1)

    var tree = {}

    for(var j=0;j<work.length;j++) {

        var restWord = work.slice(j)
        tree = this.tree

        for(var i=0;i<restWord.length;i++) {
            var char = restWord[i]
            if(tree[char]) {
                tree = tree[char]
                if(tree['None']) {
                    var p = tree['None']
                    for(var pi=0;pi< p.length;pi++) {
                        points[pi+j] = Math.max(points[pi+j],p[pi])
                    }
                }
            } else {
                break
            }
        }
    }

    points[1] = 0
    points[2] = 0
    points[points.length-2] = 0
    points[points.length-3] = 0

    var pieces = ['']
    var zipped = this.__zip([word.split(''),points.slice(2)])

    for(var i=0;i<zipped.length;i++) {
        var c = zipped[i][0]
        var p = zipped[i][1]

        pieces[pieces.length-1] += c

        if(p%2!=0) {
            pieces.push('')
        }
    }

    return pieces

}

LiangHyphenator.prototype.__createZeroArray = function(size) {

    zeroArray = []

    for(var i=0;i<size;i++) {
        zeroArray.push(0)
    }

    return zeroArray
}

LiangHyphenator.prototype.__zip = function (arrays) {
    var serial = Array.apply(null,Array(arrays[0].length)).map(function(_,i){
        return arrays.map(function(array){return array[i]})
    });

    return serial
}


module.exports = LiangHyphenator

Aspect Oriented Programming: Java EE

CDI is a part of the Java EE farmework which provides us with AOP.

This example is the same one with the spirng aop example post. I will display the behaviour of two beans with the same definition but each one has a different aspect, more specific they will use a different interceptor.

The Entered annotation would be our interceptor binding

package com.gkatzioura;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.interceptor.InterceptorBinding;

@Inherited
@InterceptorBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface Entered {
    
}

The employee interface will be used to create the beans for this project.

package com.gkatzioura;

import javax.ejb.Local;
import javax.ejb.Singleton;

@Local
public interface Employee {
    
    @Entered
    public void enterWorkArea();
    
}

We will have two different kind of advices.
The SupervisorBeforeAdvice

package com.gkatzioura;

import java.io.Serializable;
import java.util.logging.Logger;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

@Entered
@Interceptor
public class SupervisorBeforeAdvice implements Serializable{
    
    private static final Logger LOGGER = Logger.getLogger(SupervisorBeforeAdvice.class.toString());
    
    @AroundInvoke
    protected Object protocolInvocation(final InvocationContext invocationContext) throws Exception {

        if(invocationContext.getMethod().getName().equals("enterWorkArea")) {
            LOGGER.info("Check if everything is ok");
        }
        
        return invocationContext.proceed();
    }
    
}

And the WorkerBeforeAdvice

package com.gkatzioura;

import java.io.Serializable;
import java.util.logging.Logger;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;

@Entered
@Interceptor
public class WorkerBeforeAdvice implements Serializable {
    
    private static final Logger LOGGER = Logger.getLogger(WorkerBeforeAdvice.class.toString());
    
    @AroundInvoke
    protected Object protocolInvocation(final InvocationContext invocationContext) throws Exception {
        
        if(invocationContext.getMethod().getName().equals("enterWorkArea")) {
            LOGGER.info("Informing the supervisor that I have arrived");
        }
        
        return invocationContext.proceed();
    }
    
}

Two different beans will implement our employee interface.

Supervisor

package com.gkatzioura;

import javax.ejb.Stateless;
import javax.interceptor.Interceptors;

@Stateless
public class SupervisorEmployee implements Employee{

    @Override
    @Interceptors(SupervisorBeforeAdvice.class)
    public void enterWorkArea() {
    
    }
    
}

And worker

package com.gkatzioura;

import javax.ejb.Stateless;
import javax.interceptor.Interceptors;

@Stateless
public class WorkerEmployee implements Employee{

    @Override
    @Interceptors(WorkerBeforeAdvice.class)
    public void enterWorkArea() {
    }
    
}

I will use JAX-RS to cal those beans

Application configuration

package com.gkatzioura.jersey;

import javax.ws.rs.core.Application;

@javax.ws.rs.ApplicationPath("rest")
public class ApplicationConfig extends Application {

}

And calling the two beans from different endpoints

package com.gkatzioura.jersey;


import com.gkatzioura.Employee;
import com.gkatzioura.SupervisorBeforeAdvice;
import com.gkatzioura.WorkerBeforeAdvice;
import javax.ejb.EJB;
import javax.interceptor.Interceptors;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("/")
public class AspectEndpoint {
    
    @EJB(beanName = "WorkerEmployee")
    Employee worker;
    
    @EJB(beanName = "SupervisorEmployee")
    Employee supervisor;
    
    @GET
    @Path("/worker/enter")
    public String workerEnter() {
        worker.enterWorkArea();
        return "worker entered";
    }
    
    @GET
    @Path("/supervisor/enter")
    public String supervisorEnter() {
        supervisor.enterWorkArea();
        return "supervisor entered";
    }
    
}