package net.sourceforge.pain.tinylib.logic.event.guitool.event; import net.sourceforge.pain.*; import net.sourceforge.pain.db.*; import net.sourceforge.pain.tinylib.logic.event.guitool.*; import net.sourceforge.pain.util.*; import java.util.*; public class DbBrowseEvent extends GuiEventHandler { public void processEvent() { String[] data = (String[]) packet.data; String action = data[0]; if (action.equals("retrieve")) { retrieve(data); } else { send(new String[]{"Unknown action: '" + action + "'"}); } } private void retrieve(String[] data) { if (data.length != 2) { send(new String[]{"Illegal number of action params: " + data.length}); return; } String query = data[1]; String errMessage = null; try { if (query.equalsIgnoreCase("root")) { DbObject obj = Codebase.getDB().getRoot(); if (obj == null) { send(new String[]{"Database has no ROOT object"}); return; } Object oid = obj.getOid(); sendObject(oid); } else if (query.trim().matches("^\\[[\\d]+\\/[\\d]+\\]$")) { Object oid = new DbOid(query); sendObject(oid); } else { //field query int eqIndex = query.indexOf("="); if (eqIndex >= 3 && eqIndex < query.length() - 1) { int fieldSep = query.indexOf("."); if (fieldSep > 1 && fieldSep < eqIndex - 1) { String className = query.substring(0, fieldSep); String fieldName = query.substring(fieldSep + 1, eqIndex); String value = query.substring(eqIndex + 1); DbClass dbClass = null; for (Iterator it = Codebase.getDB().getDbClassesIterator(); it.hasNext();) { DbClass clz = (DbClass) it.next(); final String clzName = clz.getClassName(); if (clzName.endsWith(className)) { dbClass = clz; break; } } if (dbClass != null) { int num = -1; for (int i = 0; i < dbClass.getNumberOfFields(); i++) { String fName = dbClass.getFieldName(i); if (fName.equals(fieldName)) { num = i; break; } } if (num >= 0) { sendQueryResults(dbClass, num, value); return; } else { errMessage = "field not found:" + fieldName; } } else { errMessage = "dbclass not found:" + className; } } } if (errMessage == null) { errMessage = "Illegal query:" + query; } } } catch (Exception e) { errMessage = "Exception:" + e.getMessage(); } if (errMessage != null) { send(new String[]{"Error: '" + errMessage + "'"}); return; } } private void sendObject(Object o) { DbOid oid; DbObject obj; if (o instanceof DbOid) { oid = (DbOid) o; obj = Codebase.getDB().getObject(oid); if (obj == null) { send(new String[]{"Object not found! OID: '" + oid + "'"}); return; } } else { obj = (DbObject) o; oid = (DbOid) obj.getOid(); } try { DbClass dbclass = obj.getDbClass(); int fieldCount = dbclass.getNumberOfFields(); Object[] result = new Object[2 + 3 * fieldCount]; result[0] = oid.toString(); result[1] = dbclass.getClassName(); for (int i = 0, j = 2; i < fieldCount; i++, j += 3) { result[j] = dbclass.getFieldName(i); byte fieldType = dbclass.getFieldType(i); result[j + 1] = new Integer(fieldType); result[j + 2] = getFieldValue(obj, fieldType, i); Log.debug("field:" + dbclass.getFieldName(i)); } send(result); } catch (Exception e) { Log.error(e.getMessage(), e); send(new String[]{"Unexpected Error!: '" + e.getMessage() + "'"}); } } private Object getFieldValue(DbObject obj, int type, int i) { switch (type) { case DbType.BOOLEAN: return "" + obj.getBoolean(i); case DbType.BYTE: return "" + obj.getByte(i); case DbType.CHAR: return "" + obj.getChar(i); case DbType.DOUBLE: return "" + obj.getDouble(i); case DbType.FLOAT: return "" + obj.getFloat(i); case DbType.INT: return "" + obj.getInt(i); case DbType.LONG: return "" + obj.getLong(i); case DbType.SHORT: return "" + obj.getShort(i); case DbType.STRING: return obj.getString(i); case DbType.REFERENCE: DbObject ref = obj.getReference(i); return ref == null ? null : ref.getOid().toString(); case DbType.ARRAY_OF_BYTE: return obj.getByteArray(i); case DbType.ARRAY_OF_CHAR: return obj.getCharArray(i); case DbType.ARRAY_OF_INT: return obj.getIntArray(i); case DbType.ARRAY_OF_STRING: return obj.getStringArray(i); case DbType.LINKED_LIST: return refsToIds(obj.getList(i).toArray()); case DbType.ARRAY_LIST: return refsToIds(obj.getList(i).toArray()); case DbType.INT_KEY_MAP: return new Object[]{obj.getIntKeyMap(i).keySet().toArray(), refsToIds(obj.getIntKeyMap(i).values().toArray())}; case DbType.STRING_KEY_MAP: return new Object[]{obj.getStringKeyMap(i).keySet().toArray(), refsToIds(obj.getStringKeyMap(i).values().toArray())}; case DbType.REFERENCE_SET: return refsToIds(obj.getRefSet(i).toArray()); case DbType.STRING_SET: return obj.getStringSet(i).toArray(); case DbType.STRING_MAP: return new Object[]{obj.getStringMap(i).keySet().toArray(), obj.getStringMap(i).entrySet().toArray()}; default: return "Unknown field type!:" + type; } } private static Object[] refsToIds(Object[] objects) { if (objects == null) { return null; } Object[] result = new Object[objects.length]; for (int i = 0; i < objects.length; i++) { DbObject obj = (DbObject) objects[i]; result[i] = obj == null ? null : obj.getOid(); } return result; } private void sendQueryResults(DbClass dbClass, int num, String value) { int type = dbClass.getFieldType(num); if (type > 9) { send(new String[]{"Query not supported on type: '" + DbType.name(type) + "'"}); return; } FieldComparator fc = null; switch (type) { case DbType.BOOLEAN: fc = new BooleanFieldComparator(num, Boolean.getBoolean(value)); break; case DbType.BYTE: fc = new ByteFieldComparator(num, Byte.parseByte(value)); break; case DbType.CHAR: fc = new CharFieldComparator(num, value.charAt(0)); break; case DbType.DOUBLE: fc = new DoubleFieldComparator(num, Double.parseDouble(value)); break; case DbType.FLOAT: fc = new FloatFieldComparator(num, Float.parseFloat(value)); break; case DbType.INT: fc = new IntFieldComparator(num, Integer.parseInt(value)); break; case DbType.LONG: fc = new LongFieldComparator(num, Long.parseLong(value)); break; case DbType.SHORT: fc = new ShortFieldComparator(num, Short.parseShort(value)); break; case DbType.STRING: fc = new StringFieldComparator(num, value); break; } for (Iterator it = dbClass.extentIterator(); it.hasNext();) { DbObject o = (DbObject) it.next(); if (fc.matches(o)) { sendObject(o); return; } } send(new String[]{"No results found"}); } interface FieldComparator { boolean matches(DbObject obj); } final class BooleanFieldComparator implements FieldComparator { private int num; private boolean sample; public BooleanFieldComparator(int num, boolean sample) { this.num = num; this.sample = sample; } public boolean matches(DbObject obj) { return obj.getBoolean(num) == sample; } } final class ByteFieldComparator implements FieldComparator { private int num; private byte sample; public ByteFieldComparator(int num, byte sample) { this.num = num; this.sample = sample; } public boolean matches(DbObject obj) { return obj.getByte(num) == sample; } } final class CharFieldComparator implements FieldComparator { private int num; private char sample; public CharFieldComparator(int num, char sample) { this.num = num; this.sample = sample; } public boolean matches(DbObject obj) { return obj.getChar(num) == sample; } } final class DoubleFieldComparator implements FieldComparator { private int num; private double sample; public DoubleFieldComparator(int num, double sample) { this.num = num; this.sample = sample; } public boolean matches(DbObject obj) { return obj.getDouble(num) == sample; } } final class FloatFieldComparator implements FieldComparator { private int num; private float sample; public FloatFieldComparator(int num, float sample) { this.num = num; this.sample = sample; } public boolean matches(DbObject obj) { return obj.getFloat(num) == sample; } } final class IntFieldComparator implements FieldComparator { private int num; private int sample; public IntFieldComparator(int num, int sample) { this.num = num; this.sample = sample; } public boolean matches(DbObject obj) { return obj.getInt(num) == sample; } } final class LongFieldComparator implements FieldComparator { private int num; private long sample; public LongFieldComparator(int num, long sample) { this.num = num; this.sample = sample; } public boolean matches(DbObject obj) { return obj.getLong(num) == sample; } } final class ShortFieldComparator implements FieldComparator { private int num; private short sample; public ShortFieldComparator(int num, short sample) { this.num = num; this.sample = sample; } public boolean matches(DbObject obj) { return obj.getShort(num) == sample; } } final class StringFieldComparator implements FieldComparator { private int num; private String sample; public StringFieldComparator(int num, String sample) { this.num = num; this.sample = sample.toLowerCase(); } public boolean matches(DbObject obj) { final String val = obj.getString(num); return val!= null && val.toLowerCase().indexOf(sample) >= 0; } } }