Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Thursday, July 29, 2010

JAXB2 Annotations

It is scary to find out that a dependency of your project is no longer supported and you really need a code update. That's what happened to me when I requested the source code of one dependency and I was told no one can find it.

The dependency I need to update is a JAXB client implementation to connect to liveglobalbid (lgb) - a leading developer of online auction software providing a high quality, real time simultaneous video and audio broadcast of a live auction sale. And surprisingly, I was able to get rid of the dependency along with the JAXB dependencies and use JAXB 2.0 API that comes with Java 5 and above.  Besides that, by using JAXB 2.0 Annotations, the new client implementation is simple and light.

First, a sample xml I'll get from lgb:
<?xml version="1.0" encoding="UTF-8" ?>
<caster xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.liveglobalbid.com/caster.xsd">
    <pid>25717</pid>
    <mountpoint name="blah blah">
        <source id="9">
            <type>sound</type>
            <remoteid>blah blah</remoteid>
            <average_frame_size>94</average_frame_size>
            <average_frame_rate>3.83</average_frame_rate>
        </source>
    </mountpoint>
</caster>

Basic structure here is:
  • Caster is the main object (XmlRootElement), which contains a pid and one or more mountpoint object (XmlElement).
  • A mountpoint object has one or more source object (XmlElement)
  • A source has type, remoteid, average_frame_size, and average_frame_rate (XmlElement)
  • So in total, we'll need 3 object models: Caster, MountPoint (XmlType), and Source (XmlType).
  • MountPoint has an attribute called name (XmlAttribute)
  • Source has an attribute called id (XmlAttribute)

Source.java
package com.my.company.caster.jaxb2;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 * @author k_wang
 *
 */
@XmlType
public class Source {

    @XmlAttribute
    protected int id;

    @XmlElement
    protected String type;

    @XmlElement
    protected String remoteid;

    @XmlElement
    protected int average_frame_size;

    @XmlElement
    protected double average_frame_rate;

    /**
     * default constructor
     */
    public Source() {
        super();
    }

    /**
     * full constructor
     */
    public Source(int id, String type, String remoteid,
          int average_frame_size, double average_frame_rate) {
        super();
        this.id = id;
        this.type = type;
        this.remoteid = remoteid;
        this.average_frame_size = average_frame_size;
        this.average_frame_rate = average_frame_rate;
    }

    public int getId() {
        return id;
    }

    public String getType() {
        return type;
    }

    public String getRemoteid() {
        return remoteid;
    }

    public int getAverageFrameSize() {
        return average_frame_size;
    }

    public int getAverageFrameRate() {
        return average_frame_rate;
    }
}


MountPoint.java
package com.my.company.caster.jaxb2;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 * @author k_wang
 *
 */
@XmlType(name="mountpoint")
public class MountPoint {

    @XmlAttribute
    protected String name;

    @XmlElement
    protected List<Source> source = new ArrayList<Source>();

    public MountPoint() {
        super();
    }

    /**
     * @param name
     * @param source
    */
    public MountPoint(String name, List<Source> source) {
        super();
        this.name = name;
        if(source != null)
            this.source = source;
    }

    public String getName() {
        return name;
    }

    public List<Source> getSource() {
        return source;
    }
}


Caster.java
package com.my.company.caster.jaxb2;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author k_wang
 *
 */
 @XmlRootElement(name="caster")
public class Caster {

    @XmlElement
    protected long pid;

    @XmlElement
    protected List<MountPoint> mountpoint = new ArrayList<MountPoint>();

    public Caster() {
        super();
    }

    public Caster(long pid, List<MountPoint> mountpoint) {
        super();
        this.pid = pid;
        this.mountpoint = mountpoint;
    }

    public long getPid() {
        return pid;
    }

    public List<MountPoint> getMountpoint() {
        return mountpoint;
    }
}


And to get the Caster model from a URL:
public Caster getCaster(URL url) throws JAXBException {
    Caster caster = null;
    try {
        InputStream in = url.openStream();
        Unmarshaller unmarshaller = JAXBContext.newInstance(Caster.class).createUnmarshaller();
        caster = (Caster) unmarshaller.unmarshal(new StreamSource(in));
        in.close();
    } catch (IOException e) {
        new JAXBException("Unable to parse source input stream: ", e);
    }
    return caster;
}

Wednesday, June 18, 2008

Java Unicode to Hexadecimal Character Codes Conversion

     When it comes to internationalization, resource encoding is a big challenge. Sun's JDK doesn't offer UTF-8 encoding on ResourceBundle. So one way to work around is convert all UTF-8 translations in property files to Hexadecimal Characters first. There are lots of website offering online converters to serve the purpose. But there is still quite a few steps to do.

     Recently, I started to work on a resource repository that centralize global resources within the company to reduce duplicate work. Users are suppose to be able to import and export resources in property file format. So it got me thinking, what if I offer real-time conversion of Hexadecimal Characters upon exporting resources to save the trouble.

     After explored some of the online converter sites mentioned earlier, I find that the actual conversion is fairly simple. Strangely, all these websites uses JavaScript, but no search result turns out to do it Java way.

     Anyway, here is my little Test class:


package net.katiewang.test;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * @author KWang
 *
 */
public class JavaUnicodeTest {
    
    private final static String digits = "0123456789ABCDEF"; 

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        if(args.length > 0){
            System.out.println("File path: " + args[0]);
            InputStream is = new FileInputStream(new File(args[0]));
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String line = "";
            while((line = reader.readLine()) != null){
                String newLine = "";
                for(int i = 0; i < line.length(); i++){
                    char ch = line.charAt(i);
                    newLine += unicodeToJava(ch);
                }
                System.out.println(newLine);
            }
        }else
            System.err.println("No argument specified!");
    }

    private static String unicodeToJava (char ch){
        switch (ch) {
            case 9:
                return "\\t";
            case 10:
                return "\\n";
            case 12:
                return "\\f";
            case 13:
                return "\\r";
            case 34:
                return "\\\"";
            case 92:
                return "\\\\";
            default:
                break;
        }
        if (ch < 32 || ch > 126)
            return "\\u" + getHexCode(ch);
        return String.valueOf(ch);
    }
    
    private static String getHexCode(char ch){
        return new String(new char[]{leastSignificantHexDigit(ch >>> 12), leastSignificantHexDigit(ch >>> 8), leastSignificantHexDigit(ch >>> 4), leastSignificantHexDigit(ch)});
    }
    
    private static char leastSignificantHexDigit(int ch){
        return digits.charAt(ch & 0x0f);
    }
}


     To run the test, simple execute with a file path as argument. In unicodeToJava, I choose to ignore any regular characters, which I recommend. But if you want to convert everything instead, skip all the conditions in unicodeToJava and leave only one line -- return "\\u" + getHexCode(ch); -- will do the trick.