/* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is the Kowari Metadata Store. * * The Initial Developer of the Original Code is Plugged In Software Pty * Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002 * Plugged In Software Pty Ltd. All Rights Reserved. * * Contributor(s): N/A. * * [NOTE: The text of this Exhibit A may differ slightly from the text * of the notices in the Source Code files of the Original Code. You * should use the text of this Exhibit A rather than the text found in the * Original Code Source Code for Your Modifications.] * */ package org.mulgara.store.stringpool.xa; //Java 2 standard packages import java.nio.ByteBuffer; import java.net.URI; //apache packages import org.apache.log4j.*; //mulgara packages import org.mulgara.query.rdf.XSD; import org.mulgara.store.stringpool.AbstractSPTypedLiteral; import org.mulgara.store.stringpool.SPComparator; import org.mulgara.store.stringpool.SPObject; import org.mulgara.store.stringpool.SPTypedLiteral; /** * Class that represents a XSD hexBinary primitive datatype. * * @created 2004-10-04 * @author <a href="mailto:robert.turner@tucanatech.com">Robert Turner</a> * @company <a href="http://www.tucanatech.com/">Tucana Technologies</a> * @copyright ©2001 <a href="http://www.pisoftware.com/">Plugged In Software Pty Ltd</a> * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a> */ public class SPHexBinaryImpl extends AbstractSPTypedLiteral implements SPTypedLiteral { /** Logger */ @SuppressWarnings("unused") private static final Logger logger = Logger.getLogger(SPHexBinaryImpl.class); /** Type code that identifies this type */ static final int TYPE_ID = 14; /** the xsd:hexBinary URI */ static final URI TYPE_URI = XSD.HEX_BINARY_URI; /** The hex binary data as bytes */ private final ByteBuffer data; /** * Constructor. * @param lexicalForm String must contain valid hex values [a-f][A-F][0-9] */ public SPHexBinaryImpl(String lexicalForm) { super(TYPE_ID, TYPE_URI); if (lexicalForm == null) throw new IllegalArgumentException("'lexicalForm' cannot be null."); // ignore case String lexical = lexicalForm.toLowerCase(); // ensure that lexical falls on a boundary of 2 chars if ((lexical.length() % 2) != 0) lexical = "0" + lexical; //pack two chars into each byte (hex digits are 4 bit) int capacity = lexical.length() / 2; data = ByteBuffer.allocate(capacity); byte currentByte = 0; int lowChar = 0; int hiChar = 0; int offset = 0; for (int i = lexical.length() - 1; i > 0; i -= 2) { //there will always be an even number of chars lowChar = hexValue(lexical.charAt(i)); hiChar = hexValue(lexical.charAt(i - 1)); //join the hex values currentByte = (byte) ((hiChar << 4) | lowChar); data.put(offset++, currentByte); } data.rewind(); data.limit(offset); } /** * Constructor. * @param buffer ByteBuffer */ public SPHexBinaryImpl(ByteBuffer buffer) { super(TYPE_ID, TYPE_URI); data = buffer; } /** * Converts a hex character [0-9][a-f][A-F] to an int. * @param hexChar char * @return int */ public int hexValue(char hexChar) { return Integer.parseInt("" + hexChar, 16); } /** * Converts the value into a hax character. Value must be between 0 and 15 * @param value int * @return char */ public char hexChar(int value) { return Character.forDigit(value, 16); } /** * Returns a read-only ByteBuffer containing the hexBinary data * @return ByteBuffer */ public ByteBuffer getData() { return data.asReadOnlyBuffer(); } public SPComparator getSPComparator() { return SPBinaryComparator.getInstance(); } /** * Converts the data bytes into a String. * @return String */ public String getLexicalForm() { StringBuffer lexicalForm = new StringBuffer(); byte currentByte = 0; int hiChar = 0; int lowChar = 0; //start at the beginning data.rewind(); while (data.limit() > data.position()) { currentByte = data.get(); //get hi and low 4 bits hiChar = (currentByte >> 4) & 0x0F; lowChar = currentByte & 0x0F; //append the hex characters lexicalForm.append(hexChar(lowChar)); lexicalForm.append(hexChar(hiChar)); } //remove any trailing '0' chars (buffer will be reversed) int length = lexicalForm.length(); if ((length >= 1) && (lexicalForm.charAt(length -1) == '0')) { lexicalForm.deleteCharAt(length - 1); } //return as big-endian return lexicalForm.reverse().toString(); } /** * Compare's this SPBoolean to another object. * @param obj Object * @return int */ public int compareTo(SPObject obj) { int compare = super.compareTo(obj); if (compare == 0) { //compare by lexical value compare = getLexicalForm().compareTo(((SPTypedLiteral)obj).getLexicalForm()); //compare buffers // ByteBuffer objData = ((SPTypedLiteral) obj).getData(); // ByteBuffer data = getData(); // SPComparator comparator = getSPComparator(); // // //compare prefixes first // compare = comparator.comparePrefix(data, objData, data.limit()); // if (compare == 0) { // // compare = comparator.compare(data, objData); // } } return compare; } }