package org.postgresql.util; 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 Map { private LinkedHashMap 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 last quote else if (chars[i] == '"' || (!insideString && chars[i] == ',')) { 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, !insideVal && 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 = iter.next(); StringBuffer buffer = new StringBuffer("\""+e.getKey()+"\"=>\""+(e.getValue() == null ? "NULL" : e.getValue())+"\""); while (iter.hasNext()) { e = iter.next(); buffer.append(",\""+e.getKey()+"\"=>\""+(e.getValue() == null ? "NULL" : e.getValue())+"\""); } return buffer.toString(); } public Collection values() { return hashList.values(); } public int size() { return hashList.size(); } public String remove(Object key) { return hashList.remove(key); } public void putAll(Map m) { hashList.putAll(m); } public String put(String key, String 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 String get(Object key) { return hashList.get(key); } public boolean containsValue(Object value) { return hashList.containsValue(value); } public void clear() { hashList.clear(); } }