Wednesday, June 15, 2011

Loop around an array in said direction

/*
 * Class to loop an array of elements in said direction.
 */

package logic;

/**
 *
 * @author Nageswara Rao. V
 */
public class LoopArray {

    int dir = 1; // direction +1 -> forward, -1 -> reverse
    int startPos = 0; // init at zero position
    int[] source = new int[0]; // source array
    int curPos = 0; // current position in iterator
    boolean hasNext = false; // next available?

    /**
     * setter for loop direction
     *
     * @param inDir - direction of loop
     */
    public void setDirection(int inDir) {
        if(inDir > 0) {
            dir = 1;
        } else if (inDir < 0) {
            dir = -1;
        }
    }

    /**
     * setter for source array
     *
     * @param src - source array
     */
    public boolean setSource(int[] src) {
        if(src.length > 0) {
            source = src;
            hasNext = true;
            return true;
        }
        return false;
    }

    /**
     * setter for position to start looping
     *
     * @param src - source array
     */
    public boolean setStartPos(int pos) {
        if(pos > 0 && pos < source.length) {
            startPos = pos;
            curPos = pos;
            return true;
        }
        return false;
    }

    /**
     * acessor of next status
     *
     */
    public boolean hasNext() {
        return hasNext;
    }

    /**
     * calculates next position
     *
     * @param src - source array
     */
    private int getNextPos() {
        int lcurrent = (curPos+dir+source.length) % source.length;;
        return lcurrent;
    }

    /**
     * returns next value and resets current pointer
     *
     * @param src - source array
     */
    public int next() {
        int value = source[curPos];
        int nxtPos = getNextPos();
        if((hasNext = (startPos != nxtPos))) {
            curPos = nxtPos;
        }
        return value;
    }

    /**
     * reset current position and hasNext status
     *
     * @param src - source array
     */
    public void reset() {
        curPos = startPos;
        hasNext = true;
    }

    public static void main(String args[]) {
        int[] src = {90, 80, 70, 60, 50, 40, 30, 20, 10, 00};
        LoopArray bdt = new LoopArray();
        bdt.setSource(src);
        bdt.setDirection(-1);
        bdt.setStartPos(src.length-1);
        while(bdt.hasNext()) {
            System.out.println(bdt.next());
        }
    }
}

Wednesday, June 8, 2011

A simple configuration utility using StAX Parser

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package xml.parse;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.net.URLDecoder;
import java.util.Enumeration;
import javax.xml.stream.events.Attribute;
import java.util.Properties;
import javax.xml.namespace.QName;
import javax.xml.stream.EventFilter;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

/**
 * Class to parse configuration properties and serve values in required format
 *
 * @author Nageswara Rao. V
 */
public class ConfigUtil implements IConfig {

    String filePath; // Path of configuration file
    String[] types; // list of types to parse, will be left null to skip type filter
    String[] tags; //list of tags to parse, will be left null to handle all tags
    Properties props = new Properties();

    /**
     * Constructor to initialize configuration utility
     *
     * @param filePath - Path to configuration file
     * @param types - array of types to filter
     */
    public ConfigUtil(String filePath, String[] propTags, String[] types) {
        this.filePath = filePath;
        this.types = types;
        this.tags = propTags;
        loadConfig();
    }

    /**
     * Overloaded Constructor to skip type filter
     *
     * @param filePath - Path to configuration file
     * @param propTags - array of tags to handle
     */
    public ConfigUtil(String filePath, String[] propTags) {
        this(filePath, propTags, null);
    }

    /**
     * Overloaded Constructor to skip type filter handle all tags declared
     *
     * @param filePath - Path to configuration file
     * @param propTags - array of tags to handle
     */
    public ConfigUtil(String filePath) {
        this(filePath, null, null);
    }

    /**
     * Method to load and parse properties and populates props object
     */
    private void loadConfig() {
        try {
            XMLConfigParser parser = new XMLConfigParser(filePath);
            parser.setTagFilter(tags);
            parser.setTypeFilter(types);
            props = parser.parseProps();
        } catch (ConfigException cExp) {
            System.out.println("Failed to parse config file. Return values will be default values");
        }
    }

    /**
     *
     * @return - Current configuration
     */
    public Properties getConfig() {
        return props;
    }

    /**
     * To returns integer value
     *
     * @param key - property key
     * @param def - default integer value
     * @return - integer value
     */
    public int getIntegerValue(String key, int def) {
        String value = props.getProperty(key);
        try {
            return Integer.parseInt(value);
        } catch (Exception numfExp) {
            System.out.println("Invalid integer "+value);
        }
        return def;
    }

    /**
     * To return String value
     *
     * @param key - Property key
     * @param def - default string value
     * @return - string value
     */
    public String getValue(String key, String def) {
        String value = props.getProperty(key);
        if (value == null) {
            return def;
        }
        return value;
    }

    /**
     * To return double value
     *
     * @param key - Property key
     * @param def - default double value
     * @return - double value
     */
    public double getDoubleValue(String key, double def) {
        String value = props.getProperty(key);
        try {
            return Double.parseDouble(value);
        } catch (Exception numfExp) {
            System.out.println("Invalid double "+value);
        }
        return def;
    }

    /**
     * To return long value
     *
     * @param key - property key
     * @param def - default long value
     * @return - long value
     */
    public long getLongValue(String key, long def) {
        String value = props.getProperty(key);
        try {
            return Long.parseLong(value);
        } catch (Exception numfExp) {
            System.out.println("Invalid long "+value);
        }
        return def;
    }

    /**
     * To return double value
     *
     * @param key - Property key
     * @param def - default double value
     * @return - double value
     */
    public float getFloatValue(String key, float def) {
        String value = props.getProperty(key);
        try {
            return Float.parseFloat(value);
        } catch (Exception numfExp) {
            System.out.println("Invalid float "+value);
        }
        return def;
    }

    /**
     * Class to parse and extract configurations from xml file
     */
    class XMLConfigParser {

        private final String ATTR_TYPE = "TYPE"; // Identifier of TYPE attribute
        private final String ATTR_KEY = "KEY"; // Identifier of KEY attribute
        private final String ATTR_VALUE = "VALUE"; // Identifier of VALUE attribute
        String[] typeFilters = new String[0];
        String[] tagFilters = new String[0];

        File configFile; // configuration file object

        Properties configProps = new Properties();

        /**
         * Constructor to initialize XML StAX Parser with the given configuration
         * file written in well formed xml format
         *
         * @param filePath - path to configuration xml
         * @throws ConfigException
         */
        public XMLConfigParser(String filePath) throws ConfigException {
            this.configFile = loadFile(filePath);
        }

        /**
         * Method to validate and load configuration file
         *
         * @param filePath - file path
         * @return - File object if the path locates valid configuration xml
         * @throws ConfigException
         */
        private File loadFile(String filePath) throws ConfigException {
            File configFile = null;
            filePath = URLDecoder.decode(filePath);
            if ((filePath != null) && (configFile = new File(filePath)).exists() && configFile.isFile()) {
                    return configFile;
            } else {
                throw new ConfigException("Invalid config file : "+filePath, null);
            }
        }

        /**
         * Method to set tags that needs to pay attention
         *
         * @param tags - array of tags
         */
        public void setTagFilter(String[] tags) {
            if(tags != null) {
                this.tagFilters = tags;
            }
        }

        /**
         * Method to set attributes that needs to pay attention
         *
         * @param tags - array of attributes
         */
        public void setTypeFilter(String[] attrs) {
            if(attrs != null) {
                this.typeFilters = attrs;
            }
        }

        /**
         * Parse and extract attributes in <PROP> tag, enforce if filter is defined
         *
         * @throws ConfigException
         */
        public Properties parseProps() throws ConfigException {
            XMLEventReader reader = getReader();
            if(typeFilters == null || typeFilters.length == 0) {
                parseAttributes(reader);
            } else {
                parseFilteredAttributes(reader);
            }
            return configProps;
        }

        /**
         * Method to key/value from filtered types
         *
         * @param reader - StAX reader to run through the document
         * @throws ConfigException
         */
        private void parseFilteredAttributes(XMLEventReader reader) throws ConfigException {
            while(reader.hasNext()) {
                StartElement startElement = null;
                if((startElement = getStartElement(reader)) != null) {
                    Attribute attr = startElement.getAttributeByName(new QName(ATTR_TYPE));
                    if(attr != null && acceptAttribute(attr)) {
                        extractProperty(startElement);
                    }
                }
            }
        }

        private boolean acceptAttribute(Attribute attr) {
            String value = attr.getValue();
            for(int indx = 0; indx < typeFilters.length; indx++) {
                if(typeFilters[indx].equalsIgnoreCase(value)) {
                    return true;
                }
            }
            return false;
        }

        /**
         * Method to parse key/value from all <PROP> tags
         *
         * @param reader - StAX reader to run through the document
         * @param TAG_NAME - Tag name to handle
         * @throws ConfigException
         */
        private void parseAttributes(XMLEventReader reader) throws ConfigException {
            while(reader.hasNext()) {
                StartElement startElement = null;
                if((startElement = getStartElement(reader)) != null) {
                    extractProperty(startElement);
                }
            }
        }

        private StartElement getStartElement(XMLEventReader reader) throws ConfigException {
            StartElement startElement = null;
            try {
                XMLEvent event = reader.nextEvent();
                if(event.isStartElement()) {
                    startElement = event.asStartElement();
                }
            } catch (XMLStreamException xmlStrmExp) {
                throw new ConfigException("Exception while reading next event", xmlStrmExp);
            }
            return startElement;
        }

        /**
         * Method to extract key/value from tag
         *
         * @param startElement - Element to parse
         */
        private void extractProperty(StartElement startElement) {
            Attribute keyAttr = startElement.getAttributeByName(new QName(ATTR_KEY));
            if(keyAttr == null) {
                return;
            }
            String key = keyAttr.getValue();
            String value = startElement.getAttributeByName(new QName(ATTR_VALUE)).getValue();
            if(key != null) {
                configProps.put(key, value);
            }
        }

        /**
         * Method to construct StAX reader to parse the xml
         *
         * @return - Handle to reader
         * @throws ConfigException
         */
        private XMLEventReader getReader() throws ConfigException {
            XMLEventReader parser = null;
            try {
                FileInputStream inStream = new FileInputStream(configFile);
                XMLInputFactory factory = XMLInputFactory.newInstance();
                parser = factory.createXMLEventReader(inStream);
                parser = factory.createFilteredReader(parser, new PropEventFilter(tagFilters));
            } catch (FileNotFoundException fnfExp) {
                throw new ConfigException("Invalid Config file", fnfExp);
            } catch (XMLStreamException xmlSExp) {
                throw new ConfigException("Invalid config format", xmlSExp);
            }
            return parser;
        }
    }

    /**
     * Class to filter meta and only the filtered tags from xml document
     */
    class PropEventFilter implements EventFilter {

        String[] tagFilters = new String[0];

        PropEventFilter() {
        }

        PropEventFilter(String[] tagFilters) {
            this.tagFilters = tagFilters;
        }

        public boolean accept(XMLEvent event) {
            return doAccept(event);
        }

        private boolean doAccept(XMLEvent event) {
            // Exclude PIs
            if(event.isProcessingInstruction()) {
                return false;
            } else if (tagFilters.length > 0) {
                // filter tag if set
                boolean accept = false;
                StartElement startElement = null;
                if(event.isStartElement()) {
                    startElement = event.asStartElement();
                    String tag = startElement.getName().toString();
                    for(int idx = 0; idx < tagFilters.length; idx++) {
                        if(tag.equalsIgnoreCase(tagFilters[idx])) {
                            accept = true;
                            break;
                        }
                    }
                }
                return accept;
            }
            return true;
        }
    }

    /**
     *
     * Class to handle exceptions while parsing
     */
    class ConfigException extends Exception {
        String message;

        public ConfigException(String message, Throwable exp) {
            super(exp);
            this.message = message;
        }

        public String getMessage() {
            return message;
        }
    }

    public static void main(String args[]) {
        try {
            System.out.println("With types");
            String[] types = {"person", "address", "employment"};
            String[] tags = {"PROP"};
            ConfigUtil cfgUtil = new ConfigUtil("D:\\ws\\algorithms\\algorithms\\config.xml",
                    tags, types);

            System.out.println("Name : "+cfgUtil.getValue("name", "Default Value"));
            System.out.println("Sal : "+cfgUtil.getIntegerValue("age", 25));
            System.out.println("double : "+cfgUtil.getDoubleValue("salary", 25));

            System.out.println("General accessor");
            Properties props = cfgUtil.getConfig();
            Enumeration enumrt = props.keys();
            while(enumrt.hasMoreElements()) {
                String name  = (String)enumrt.nextElement();
                String value  = (String)props.getProperty(name);
                System.out.println("Name : "+name+ " Value : "+value);
            }
        } catch (Exception exp) {
            exp.printStackTrace();
            System.out.println("Exception "+exp.getMessage());
        }
    }
}

/*---- Sample configuration ---*/
<?xml version="1.0" encoding="UTF-8"?>

<!--
    Document   : config.xml
    Created on : May 23, 2011, 12:53 PM
    Author     : Nageswara Rao. V
    Description:
        Purpose of the document follows.
-->

<CONFIG>
    <PROP TYPE="person" KEY="name" VALUE="RAO"/>
    <PROP TYPE="person" KEY="age" VALUE="30"/>
    <PROP TYPE="person" KEY="height" VALUE="177"/>
    <PROP TYPE="employment" KEY="salary" VALUE="4550.00"/>
    <PROP TYPE="employment" KEY="firm" VALUE="ABC Inc."/>
    <PROP TYPE="address" KEY="dno" VALUE="170"/>
    <PROP TYPE="address" KEY="street" VALUE="AS Puram"/>
    <PROP TYPE="address" KEY="city" VALUE="Chennai"/>
</CONFIG>

Insertion sort

package algorithms.sort;

/**
 *
 * @author Nageswara Rao. V
 * @version 1.0 date : June 8, 2011
 */
public class InsertionSort {
    public static int[] insertionSort(int[] src) {
        for(int pos = 1; pos < src.length; pos++) {
            int i = pos;
            while((i>0) && (src[i] < src[i-1])) {
                swap(src, i, i-1);
                i = i-1;
            }
        }
        return src;
    }

    public static void swap(int[] src, int start, int end) {
        src[start] = src[start]+src[end];
        src[end] = src[start] - src[end];
        src[start] = src[start] - src[end];
    }

    public static void print(int[] src) {
        for(int i=0; i < src.length; i++) {
            System.out.print(src[i]+" ");
        }
    }

    public static void main(String args[]) {
        int[] src = {4, 3, 8, 2, 1, 0};
        System.out.println("\nSource");
        print(src);
        insertionSort(src);
        System.out.println("\nResult");
        print(src);
        System.out.println("\n");
    }
}