Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Thursday, October 15, 2009

How to simply write bean objects to String

This utility provide ability to write objects to string. Example says everything:
public class Person {

    private PersonName name;
    private Integer age;

    public static class PersonName {

        private String firstName;
        private String lastName;

        public PersonName(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }

        public String getFirstName() {
            return firstName;
        }

        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }

        public String getLastName() {
            return lastName;
        }

        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    }

    public Person(PersonName name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public PersonName getName() {
        return name;
    }

    public void setName(PersonName name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return StringUtils.objectToString("person", this);
    }
}


Then we call:
    public static void main(String[] args) {
        System.out.println(new Person(new PersonName("Astar", "Sheran"), 2009));
    }


and output is:
person.age = 2009
person.name = new Person$PersonName()
person.name.firstName = Astar
person.name.lastName = Sheran


Utility implementation:

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Michal Hlavac
 */
public class StringUtils {

    private static final Logger log = Logger.getLogger(StringUtils.class.getName());

    private static final void toString(String alias, Object obj, StringBuffer sb, List<Object> objects) {
        if (obj == null) {
            return;
        }
        if (objects.contains(obj)) {
            return;
        }
        objects.add(obj);
        try {
            BeanInfo info = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
            for (int i = 0; i < descriptors.length; i++) {
                PropertyDescriptor descriptor = descriptors[i];
                if (descriptor.getReadMethod().getDeclaringClass().equals(Object.class)) {
                    log.fine("property defined on Object class: skipping: " + descriptor.getName());
                    continue;
                }
                Object value = null;
                try {
                    value = descriptor.getReadMethod().invoke(obj, (Object[]) null);
                } catch (Throwable ex) {
                    log.fine("Can't read value of attribute " + obj.getClass().getName() + "." + descriptor.getName());
                }
                if (value == null) {
                    log.fine("property value is null: skipping: " + descriptor.getName());
                    continue;
                }
                Class<?> returnType = descriptor.getReadMethod().getReturnType();
                if (!returnType.isPrimitive() && !returnType.isArray() && !returnType.getName().startsWith("java.") &&
                        !returnType.isEnum()) {
                    log.fine("property is unknown type or not primitive [" + returnType.getName() + "]");
                    String simpleName = value.getClass().getName().substring(returnType.getName().lastIndexOf('.') + 1);
                    sb.append(alias).append(".").append(descriptor.getName()).append(" = new ").append(simpleName).append("()\n");
                    toString(alias + "." + descriptor.getName(), value, sb, objects);
                    continue;
                }
                if (value instanceof java.util.Collection<?>) {
                    try {
                        Iterator<?> iter = ((Collection<?>)  value).iterator();                        int num = 0;
                        while (iter.hasNext()) {
                            Object item = iter.next();
                            toString(alias + "." + descriptor.getName() + "[" + num + "]", item, sb, objects);
                            num++;
                        }
                    } catch (Throwable t) {
                        log.fine("Can't read value of attribute: " + alias + "." + descriptor.getName());
                    }
                    continue;
                } else if (value.getClass().isArray()) {
                    try {
                        Object[] valueArray = (Object[]) value;
                        for (int idx = 0; idx < valueArray.length; idx++) {
                            toString(alias + "." + descriptor.getName() + "[" + idx + "]", valueArray[idx], sb, objects);
                        }
                    } catch (Throwable t) {
                        log.fine("Can't read value of attribute: " + alias + "." + descriptor.getName());
                    }
                    continue;
                }
                sb.append(alias).append(".").append(descriptor.getName()).append(" = ").append(value.toString()).append('\n');
            }
        } catch (Exception e) {
            log.log(Level.SEVERE, "hql example criterion building error", e);
        }
    }

    public static final String objectToString(String alias, Object obj) {
        StringBuffer buff = new StringBuffer();
        toString(alias, obj, buff, new ArrayList<Object>());
        return buff.toString();
    }

    public static final String collectionToString(String alias, Collection<?> collection) {
        StringBuffer buff = new StringBuffer();
        int idx = 0;
        for (Object obj : collection) {
            toString(alias + "[" + idx++ + "]", obj, buff, new ArrayList<Object>());
        }
        return buff.toString();
    }

    public static final String toStringLine(Object obj) {
        if (obj == null) {
            return "";
        }
        String clazz = obj.getClass().getName();
        String simpleClazz = clazz.substring(clazz.lastIndexOf('.') + 1);
        StringBuffer sb = new StringBuffer(simpleClazz).append("[");
        try {
            BeanInfo info = Introspector.getBeanInfo(obj.getClass());
            PropertyDescriptor[] descriptors = info.getPropertyDescriptors();
            for (int i = 0; i < descriptors.length; i++) {
                PropertyDescriptor descriptor = descriptors[i];
                if (descriptor.getPropertyType() == null ||
                        Collection.class.isAssignableFrom(descriptor.getPropertyType())) {
                    log.fine("collection handling not supported: skipping property: " + descriptor.getName());
                    continue;
                }
                if (descriptor.getReadMethod().getDeclaringClass().equals(Object.class)) {
                    log.fine("property defined on Object class: skipping: " + descriptor.getName());
                    continue;
                }
                Object value = descriptor.getReadMethod().invoke(obj, (Object[]) null);
                if (value == null) {
                    log.fine("property value is null: skipping: " + descriptor.getName());
                    continue;
                }
                Class<?> returnType = descriptor.getReadMethod().getReturnType();
                if (!returnType.isPrimitive() && !returnType.getName().startsWith("java.") && !returnType.isEnum()) {
                    log.fine("property is unknown type or not primitive [" + returnType.getName() + "]");
                    continue;
                }
                sb.append(descriptor.getName()).append(" = ").append(value).append(" | ");
            }
        } catch (Exception e) {
            log.log(Level.SEVERE, "hql example criterion building error", e);
            return null;
        }
        sb.append("]");
        return sb.toString();
    }
}

Saturday, August 08, 2009

XDXF Parser Library & Maven

Now you can use latest snapshot of xdxf parser library in maven projects. You need to add new repository and dependency to library.
1. Add repository
<repositories>
  <repository>
      <id>xdxf-snapshots</id>
      <name>XDXF Snapshots</name>
      <layout>default</layout>
      <url>https://mvn.datalan.sk/artifactory/libs-releases-snapshots/</url>
      <snapshots>
          <enabled>true</enabled>
      </snapshots>
  </repository>
</repositories>

2. Add dependency
<dependency>
  <groupid>eu.hlavki.xdxf</groupid>
  <artifactid>xdxf-parser</artifactid>
  <version>1.0-SNAPSHOT</version>
</dependency>

v1.9.5 serialVersionUID generator for netbeans 6.7 released

Changelog:

Download here.

Monday, June 15, 2009

XDXF Parser library

I created small library to parse dictionaries stored in XDXF format. API is event based and you can listen to events (dictionary, article) while parser is parsing.
Whole dictiary is not loaded to memory by default, so you can parse large dictionary with small memory footprint. Project is hosted on kenai.com. Binary packages will be available soon, but source code is available in kenai browser.

API usage example:

import eu.hlavki.xdxf.parser.DefaultXDXFParser;
import eu.hlavki.xdxf.parser.ParseException;
import eu.hlavki.xdxf.parser.XDXFParser;
import java.io.IOException;
import java.io.InputStream;

public class Sample {

public static void main(String[] args) {
InputStream in = null;
try {
XDXFParser parser = new DefaultXDXFParser();
DictionaryListener listener = new DictionaryListener();
parser.addXDXFEventListener(listener);
in = Sample.class.getResourceAsStream("/test-dict.xdxf");
long startTime = System.currentTimeMillis();
parser.parse(in);
long endTime = System.currentTimeMillis();
System.out.println("Dictionary: " + listener.getDictionary());
System.out.println("Word Count: " + listener.getArticleCount());
System.out.println("Parse time: " + (endTime - startTime) + " ms");
} catch (ParseException e) {
e.printStackTrace();
} finally {
try {
if (in != null) in.close();
} catch (IOException e) {
// should never happened
}
}
}
}

Listener sample code:

import eu.hlavki.xdxf.parser.event.XDXFArticleEvent;
import eu.hlavki.xdxf.parser.event.XDXFDictionaryEvent;
import eu.hlavki.xdxf.parser.event.XDXFEventListener;
import eu.hlavki.xdxf.parser.model.XDXFDictionary;

public class DictionaryListener implements XDXFEventListener {

private int articleCount = 0;
private XDXFDictionary dictionary;

public void onDictionary(XDXFDictionaryEvent evt) {
this.dictionary = evt.getSource();
}

public void onDictionaryChange(XDXFDictionaryEvent evt) {
this.dictionary = evt.getSource();
}

public void onArticle(XDXFArticleEvent evt) {
articleCount++;
}

public int getArticleCount() {
return articleCount;
}

public XDXFDictionary getDictionary() {
return dictionary;
}
}

Friday, May 15, 2009

v1.9.4 serialVersionUID generator for netbeans 6.7 released

Changelog:
  • project moved to Kenai
  • changes to work with Netbeans 6.7
  • fixes in svuid generator
  • new SuppressWarning("serial") hint
Download from plugin site.

Thursday, October 30, 2008

serialVersionUID generator for netbeans 6.5 released

Changelog:
  • API changes to work with Netbeans 6.5
  • works with JFrame and JPanel in Matisse since issue #140653 fixed
Download from plugin site.

Sunday, July 13, 2008

serialVersionUID generator for netbeans v1.5 released

Changelog:
  • hint configuration was moved to "general" group
  • refactoring in Descriptor class
  • support for SuppressWarrning("serial") annotation
  • abstract classes are excluded from generator and hint
Download from plugin site.

Wednesday, May 28, 2008

SerialVersionUID generator v1.9 for Netbeans 6.5 nightly builds

As I mentioned generator v1.3 is not compatible with api changes in 6.5 dev builds. So I created serialVersionUID generator v1.9 that supports 6.5 nightly builds... You can download nbm here.

Tuesday, May 27, 2008

SerialVersionUID generator v1.3 for Netbeans 6.1

Today I updated new version of generator for serialVersionUID field. It generates default value (1L) or generated value from source code. You can use it as java editor hint or code generator.



Iteresting is that it generates uid in correct way only for some cases. Correct way I mean sun's javac. Algorithm uses uses this directions to calculate value. Maybe there is problem with descriptors of fields, methods and constructors. I'll investigate it to create patch. But if you want to participate sources are in this mercurial repository.

Download plugin.

This version doesn't work with 6.5 nightly builds. See this post.

Sunday, April 06, 2008

I am JavaFX fan

Joshua Marinacci wrote really interesting post about speed of JavaFX. I have to try it. So I installed jdk 1.6.0_10 beta on my dual core Lenovo R60 with openSuse linux 10.3 and run bubblemark. Result shows the best fps results in first 15 seconds of run with 32 bubbles:

Java (Swing) - 71 fps
Java (Swing, optimized) - 131 fps
JavaFX (optimized version by Chris Oliver) - 27 fps
JavaFX - 6 fps !!!
Flash (Flex) - 31 fps
Flash (Flex) with cacheAsBitmap - 81 fps

Swing really rocks but javaFX doesn't. I don't know, may be it's only some linux issue but 6 fps is really slow. And I have to say, disabling comments on this post was really smart move (no offence). Articles like this can turn to flame war.

Monday, March 31, 2008

Generating of serialVersionUID in Netbeans 6.0+

Hello,

some time ago I wrote question about generator of serialVersionUID in netbeans. After that I saw issue in bugzilla describing this problem. I decided to write this plug-in because I can't see any progress on this issue. For now it generates only default serialVersionUID = 1L. I am working on hash method that generates serialVersionUID from fields and methods. You can find plug-in on netbeans plug-in site.

Thanks to geertjan's posts Fixable hint and Java Hint Generator development was really easy.

Note: Third picture shows code generator which works only in netbeans 6.1-dev. You can download plug-in for 6.1-dev from this location.

Fixable editor hint


Generated serialVersionUID


Code generator from context menu works only in netbeans 6.1-dev

Tuesday, February 19, 2008

New beta version 0.7 of gemini dictionary was released. It contains support for default language and some bug fixes. You can find sources at mercurial repository. Next version will contain tighter intergration with netbeans editor.

Friday, January 11, 2008

Few days ago I started new project at google sorce. It allows create dictionary with translations, synonyms and other word relations. Homepage of project is http://gemini-dictionary.googlecode.com. It it set of plugins (2) for netbeans RCP 6.0. If you have some suggestions or want to participate please feel free to contact me.

It is still in beta (maybe alpha :) ) quality state so be patient to first release.

Sources are available in mercurial repository http://www.hlavki.eu/hg/gemini-dictionary.

Saturday, November 10, 2007

New version 0.3 of JNetWalk game was released.

Web started application launch button