Kris Jurka napsal(a):
>> I recently implemented hstore class for project I work on and I
>> decided to share it with list.
>
> I did the same thing myself pretty recently, but haven't finished
> cleaning it up. A quick look at the differences between our versions
> are that your getValue call doesn't handle nulls or strings with
> backslashes or quotes correctly. The parsing is a little to tricky to
> read through quickly, but I based mine on a pretty literal conversion
> of the backend C code.
Oh right it didn't this version does ;)
Parser should work fine. I am not big fan of literal conversions from
one language to another.
> Also at the moment the driver is still retaining JDK1.4 compatibility
> so generics can't be used.
Oh didn't know that (like I said I am new to Java), removed those.
--
Regards
Petr Jelinek (PJMODOS)
package org.postgresql.util;
import java.io.Serializable;
import java.util.Collection;
import java.util.Set;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
/**
* Class that handles hstore contrib datatype.
*/
public class PGhstore extends PGobject
implements Serializable, Cloneable, Map {
private final static long serialVersionUID = 1;
private Map hashList;
public PGhstore()
{
setType("hstore");
}
public PGhstore(String value) throws java.sql.SQLException
{
this();
setValue(value);
}
public PGhstore(Map value)
{
this();
hashList = new LinkedHashMap(value);
}
@Override
public void setValue(String s) throws java.sql.SQLException
{
hashList = new LinkedHashMap();
if (s != null)
{
char[] chars = s.toCharArray();
String key = null;
StringBuffer buffer = new StringBuffer();
boolean insideKey = true;
boolean insideVal = false;
boolean insideString = false;
for (int i = 0; i < chars.length; i++)
{
// escape character that we need to skip
if (chars[i] == '\\')
{
i++;
}
// white space
else if (!insideString && Character.isWhitespace(chars[i]))
{
continue;
}
// the => between key and value
else if (!insideString && chars[i] == '=')
{
i++;
if (i == chars.length)
throw new PSQLException("Unexpected end of string", PSQLState.DATA_ERROR);
if (!insideKey || chars[i] != '>')
throw new PSQLException("Syntax error at position "+i, PSQLState.DATA_ERROR);
insideKey = false;
insideVal = true;
key = buffer.toString();
buffer.setLength(0);
continue;
}
// quote, item separator or end of string
else if (chars[i] == '"' || (!insideString && chars[i] == ',') || i == chars.length - 1)
{
if (chars[i] == '"')
{
insideString = !insideString;
if (i != chars.length - 1)
continue;
}
else if (chars[i] != ',' && buffer != null)
{
buffer.append(chars[i]);
}
String b = (buffer == null) ? null : buffer.toString();
// end of element, add it to list
if (b != null && (b.length() > 0 || insideVal))
{
hashList.put(key, b.equalsIgnoreCase("NULL") ? null : b);
}
insideKey = true;
insideVal = false;
buffer = new StringBuffer();
continue;
}
if (buffer != null)
buffer.append(chars[i]);
}
}
}
@Override
public String getValue()
{
if (hashList == null)
return null;
Iterator iter = hashList.entrySet().iterator();
if (!iter.hasNext())
return null;
Entry e = (Entry)iter.next();
StringBuffer buffer = new StringBuffer();
appendEntry(buffer, e);
while (iter.hasNext())
{
e = (Entry)iter.next();
buffer.append(',');
appendEntry(buffer, e);
}
return buffer.toString();
}
private void appendEntry(StringBuffer buf, Entry e)
{
appendValue(buf, e.getKey(), true);
buf.append("=>");
appendValue(buf, e.getValue(), false);
}
private void appendValue(StringBuffer buf, Object v, boolean isKey)
{
if (v == null)
{
if (isKey)
buf.append("\"NULL\"");
else
buf.append("NULL");
return;
}
String s = v.toString();
buf.append('"');
for (int i=0; i<s.length(); i++)
{
char c = s.charAt(i);
if (c == '"' || c == '\\')
buf.append('\\');
buf.append(c);
}
buf.append('"');
}
public Collection values() {
return hashList.values();
}
public int size() {
return hashList.size();
}
public Object remove(Object key) {
return hashList.remove(key);
}
public void putAll(Map m) {
hashList.putAll(m);
}
public Object put(Object key, Object value) {
return hashList.put(key, value);
}
public Set keySet() {
return hashList.keySet();
}
public boolean isEmpty() {
return hashList.isEmpty();
}
public Set entrySet() {
return hashList.entrySet();
}
public boolean containsKey(Object key) {
return hashList.containsKey(key);
}
public Object get(Object key) {
return hashList.get(key);
}
public boolean containsValue(Object value) {
return hashList.containsValue(value);
}
public void clear() {
hashList.clear();
}
}