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