/* * This file is part of the HyperGraphDB source distribution. This is copyrighted * software. For permitted uses, licensing options and redistribution, please see * the LicensingInformation file at the root level of the distribution. * * Copyright (c) 2005-2010 Kobrix Software, Inc. All rights reserved. */ package org.hypergraphdb.type.javaprimitive; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.Comparator; import org.hypergraphdb.HGException; /** * <p> * The implementation of the primitive <code>String</code> type. * </p> * * <p> * This implementation should be used only for relatively small strings, things like * names or titles, since they are indexed and reference counted for lookup. * If you want to store larger text data, including big documents, use the * <code>TextType</code> instead. * </p> * * <p> * A <code>java.lang.String</code> object is translated to a byte [] as * follows: * * <ul> * <li>The first 4 bytes consitute an unsigned integer - the reference count * for the string. The reference count is managed by the superclass</li> * <li>The fifth byte is a descriptor tag that indicates whether the string is * <code>null</code>, empty or it has actual content: 0 means null, 1 means empty * and 2 means we have something. In the future this might be extended to support * various encodings.</li> * <li>The rest of the bytes constitute the actual string with the default 8-bit * Java encoding.</li> * </ul> * * </p> * * @author Borislav Iordanov */ public class StringType extends PrimitiveTypeBase<String> { public static final String INDEX_NAME = "hg_string_value_index"; private Comparator<byte[]> comp = new StringComparator(); public static class CaseInsensitiveStringComparator implements Comparator<byte[]>, java.io.Serializable { private static final long serialVersionUID = 1L; public int compare(byte [] left, byte [] right) { if (left[dataOffset] < 2) if (right[dataOffset] < 2) { // null is considered < "" for the purpose of ordering if (left[dataOffset] < right[dataOffset]) return -1; else if (left[dataOffset] == right[dataOffset]) return 0; else return 1; } else return -1; else if (right[dataOffset] < 2) return 1; else { int i = dataOffset + 1; String lefts = new String(left, i, left.length - i); String rights = new String(right, i, right.length - i); //System.out.println(lefts + " -- " + rights); return lefts.compareToIgnoreCase(rights); /* InputStreamReader leftReader = new InputStreamReader( new ByteArrayInputStream(left, i, left.length - i)); InputStreamReader rightReader = new InputStreamReader( new ByteArrayInputStream(right, i, right.length - i)); try { while (true) { int cl = leftReader.read(); int cr = rightReader.read(); if (cl == -1) return (cr == -1) ? 0 : -1; else if (cr == -1) return 1; int c = Character.toUpperCase(cl) - Character.toUpperCase(cr); if (c != 0) return c; } } catch (IOException ex) { throw new HGException(ex); } */ } } } public static class StringComparator implements Comparator<byte[]>, java.io.Serializable { private static final long serialVersionUID = 1L; public int compare(byte [] left, byte [] right) { if (left[dataOffset] < 2) if (right[dataOffset] < 2) { // null is considered < "" for the purpose of ordering if (left[dataOffset] < right[dataOffset]) return -1; else if (left[dataOffset] == right[dataOffset]) return 0; else return 1; } else return -1; else if (right[dataOffset] < 2) return 1; else { int i = dataOffset + 1; for (; i < left.length && i < right.length; i++) if (left[i] < right[i]) return -1; else if (left[i] > right[i]) return 1; if (i == left.length) if (i == right.length) return 0; else return -1; else return 1; } } } public Comparator<byte[]> getComparator() { return comp; } protected String getIndexName() { return INDEX_NAME; } private byte [] stringToBytes(String s) { byte [] data; if (s == null) { data = new byte[1]; data[0] = 0; } else if (s.length() == 0) { data = new byte[1]; data[0] = 1; } else { byte [] asBytes = s.getBytes(); data = new byte[1 + asBytes.length]; data[0] = 2; System.arraycopy(asBytes, 0, data, 1, asBytes.length); } return data; } protected byte [] writeBytes(String value) { return stringToBytes(value); } protected String readBytes(byte [] data, int offset) { switch (data[offset]) { case 0: return null; case 1: return ""; default: return new String(data, offset + 1, data.length - offset - 1); } } public boolean isCaseSensitive() { return comp instanceof StringComparator; } public void setCaseSensitive(boolean caseSensitive) { if (caseSensitive) comp = new StringComparator(); else comp = new CaseInsensitiveStringComparator(); } }