/* * 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 base64Binary primitive datatype. * * @created 2004-10-04 * @author <a href="mailto:robert.turner@tucanatech.com">Robert Turner</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 SPBase64BinaryImpl extends AbstractSPTypedLiteral implements SPTypedLiteral { /** Logger */ @SuppressWarnings("unused") private static final Logger logger = Logger.getLogger(SPBase64BinaryImpl.class); /** Type code that identifies this type */ static final int TYPE_ID = 13; /** the xsd:base64Binary URI */ static final URI TYPE_URI = XSD.BASE64_BINARY_URI; /** The base64 binary data as bytes */ private ByteBuffer data = null; /** * Constructor. * * @param lexicalForm String must contain values [0-9a-zA-Z+/=] */ public SPBase64BinaryImpl(String lexicalForm) { super(TYPE_ID, TYPE_URI); //validate if (lexicalForm == null) { throw new IllegalArgumentException("'lexicalForm' cannot be null."); } //create a buffer and copy contents of the lexical string data = ByteBuffer.allocate(lexicalForm.length()); char current = 0; byte value = 0; //convert each character to a base64 byte value //2 bits are wasted for each byte, but it is faster without the compression for (int i = 0; i < lexicalForm.length(); i++) { current = lexicalForm.charAt(i); //ignore whitespace characters if (!Character.isWhitespace(current)) { value = (byte) (base64Value(current) & 0xFF); data.put(value); } } data.flip(); } /** * Constructor. * * @param buffer ByteBuffer */ public SPBase64BinaryImpl(ByteBuffer buffer) { super(TYPE_ID, TYPE_URI); data = buffer; } /** * Converts a base64 character [0-9a-zA-Z+/=] to an int. * * @param base64Char char * @return int */ public int base64Value(char base64Char) { //invalid default value int value = -1; if (Character.isDigit(base64Char)) { //[0-9] (0 == 52, 9 == 61) value = base64Char - '0' + 52; } else if ( (base64Char >= 'A') && (base64Char <= 'Z')) { //[A-Z] (A == 0, Z == 25) value = base64Char - 'A'; } else if ( (base64Char >= 'a') && (base64Char <= 'z')) { //[a-z] (a == 26, z == 51) value = base64Char - 'a' + 26; } else if (base64Char == '+') { //(+ == 62) value = 62; } else if (base64Char == '/') { //(/ == 63) value = 63; } else if (base64Char == '=') { //(= == 64) value = 64; } //validate if ( (value < 0) || (value > 64)) { throw new IllegalArgumentException("'base64Char' (" + base64Char + ") is not a valid base 64 character " + "([0-9a-zA-Z+/=])."); } return value; } /** * Converts the value into a base64 character. Value must be between 0 and 64 * * @param value int * @return char */ public char base64Char(int value) { char base64Char = '0'; //validate if ( (value < 0) || (value > 64)) { throw new IllegalArgumentException("'value' (" + value + ") must be " + "between 0 and 64."); } if (value <= 25) { //[0-25] (A == 0, Z == 25) base64Char = (char) ('A' + value); } else if (value <= 51) { //[26-51] (a == 26, z == 51) base64Char = (char) ('a' + (value - 26)); } else if (value <= 61) { //[52-61] (0 == 52, 9 == 61) base64Char = (char) ('0' + (value - 52)); } else if (value == 62) { //(+ == 62) base64Char = '+'; } else if (value == 63) { //(/ == 63) base64Char = '/'; } else if (value == 64) { //(= == 64) base64Char = '='; } return base64Char; } /** * Returns a read-only ByteBuffer containing the base64Binary data * * @return ByteBuffer */ public ByteBuffer getData() { return data.asReadOnlyBuffer(); } /** * Converts the data bytes into a String. * * @return String */ public String getLexicalForm() { StringBuffer lexical = new StringBuffer(); ByteBuffer buffer = getData(); buffer.position(0); //convert each byte value to it's base64 character and add byte current = 0; char character = 0; int charCount = 0; while (buffer.hasRemaining()) { current = buffer.get(); character = base64Char( (current & 0xFF)); charCount++; //lines cannot be longer than 76 characters if ((charCount % 76) == 0) { charCount = 0; lexical.append(System.getProperty("line.separator")); } lexical.append(character); } return lexical.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(); //reset buffers data.position(0); objData.position(0); //compare prefixes first compare = comparator.comparePrefix(data, objData, data.limit()); if (compare == 0) { compare = comparator.compare(data, 0, objData, 0); } } return compare; } /** * Returns the SPBinaryComparator * * @return SPComparator */ public SPComparator getSPComparator() { return SPBinaryComparator.getInstance(); } public boolean equals(Object o) { if (!(o instanceof SPBase64BinaryImpl)) return false; SPBase64BinaryImpl b = (SPBase64BinaryImpl)o; return data.equals(b.data); } public int hashCode() { return data.hashCode(); } }