All Downloads are FREE. Search and download functionalities are using the official Maven repository.

es.rickyepoderi.wbxml.document.opaque.SiDateTimeOpaque Maven / Gradle / Ivy

/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *    
 * Linking this library statically or dynamically with other modules 
 * is making a combined work based on this library. Thus, the terms and
 * conditions of the GNU General Public License cover the whole
 * combination.
 *    
 * As a special exception, the copyright holders of this library give 
 * you permission to link this library with independent modules to 
 * produce an executable, regardless of the license terms of these 
 * independent modules, and to copy and distribute the resulting 
 * executable under terms of your choice, provided that you also meet, 
 * for each linked independent module, the terms and conditions of the 
 * license of that module.  An independent module is a module which 
 * is not derived from or based on this library.  If you modify this 
 * library, you may extend this exception to your version of the 
 * library, but you are not obligated to do so.  If you do not wish 
 * to do so, delete this exception statement from your version.
 *
 * Project: github.com/rickyepoderi/wbxml-stream
 * 
 */
package es.rickyepoderi.wbxml.document.opaque;

import es.rickyepoderi.wbxml.document.OpaqueAttributePlugin;
import es.rickyepoderi.wbxml.document.WbXmlAttribute;
import es.rickyepoderi.wbxml.document.WbXmlElement;
import es.rickyepoderi.wbxml.document.WbXmlEncoder;
import es.rickyepoderi.wbxml.document.WbXmlParser;
import java.io.IOException;
import java.util.Arrays;

/**
 *
 * 

The WAP Service Indication (SI) Specification describes that the * %Datetime; entity should be encoded as an opaque attribute. This value * is originally an ISO8601 date time string value. The specification * in the chapter 8.2.2. Encoding of %Datetime; says the following:

* *

%Datetime; data MUST be encoded as OPAQUE data with each number in the * string represented by its 4-bit binary value. Any non-numerical characters * ("T", "Z", "-", and ":") are discarded. Trailing zeros (from right to left) * MUST be pair-wise omitted.

* *

For example, "1999-04-30T06:40:00Z" is encoded into six octets as follows:
* Number "1" "9" "9" "9" "0" "4" "3" "0" "0" "6" "4" "0" "0" "0"
* Binary value 0001 1001 1001 1001 0000 0100 0011 0000 0000 0110 0100 0000 0000 0000
* Octet (hex) 00011001 (19) 10011001 (99) 00000100 (04) 00110000 (30) 00000110 (06) 01000000 (40) omitted *

* * @author ricky */ public class SiDateTimeOpaque implements OpaqueAttributePlugin { /** * Utility method that transforms a an ascii array representing hexa * data in a real hexa array. The resulting array is half the size of * the one passed as parameter. * @param array The array representing an hexa array but using ascii * @return The real hexa array (half sized) */ static public byte[] charArrayToHexArray(char[] array) { // convert ascii into numeric values byte[] ascii = new byte[(array.length % 2 == 0)? array.length : array.length + 1]; for (int i = 0; i < ascii.length; i++) { if (i < ascii.length) { if ('A' <= array[i] && array[i] <= 'F') { ascii[i] = (byte) (array[i] - 'A'); } else if ('a' <= array[i] && array[i] <= 'f') { ascii[i] = (byte) (array[i] - 'a'); } else if ('0' <= array[i] && array[i] <= '9') { ascii[i] = (byte) (array[i] - '0'); } else { // bad hexa data ascii[i] = 0x0; } } else { ascii[i] = 0x0; } } // convert numeric to hexa byte[] result = new byte[array.length / 2]; for (int i = 0; i < result.length; i++) { result[i] = (byte) ((ascii[i * 2] * 16) | ascii[i * 2 + 1]); } // delete trailing zeros int i; for (i = result.length - 1; i >= 0 && result[i] == 0; i--); if (i < result.length - 1) { result = Arrays.copyOf(result, i+1); } return result; } /** * Utility method that transforms a hexa byte array into an ascii array. * Obviously the resulting array is twice the length of the input * array (a byte in hexa is represented by two digits "0-9A-F" in the * ascii resulting array). * @param array The hexa (normal) byte array to convert in ascii * @return The ascii array with the hexa values in characters */ static public char[] hexArrayToCharArray(byte[] array) { // duplicate the byte array char[] buffer = new char[array.length * 2]; for (int i = array.length - 1; i >= 0; i--) { byte b = (byte) ((array[i] & 0x0F) % 16); char c = (b < 10)? (char) ((byte) ('0' + b)) : (char) ((byte) ('A' + b - 10)); buffer[i * 2 + 1] = c; b = (byte) (((array[i] & 0xF0) >> 4) % 16); c = (b < 10)? (char) ((byte) ('0' + b)) : (char) ((byte) ('A' + b - 10)); buffer[i * 2] = c; } return buffer; } /** * Method to encode the date time as specified in the SI specification. The * string is cleaned from non digit values and then passed to hex ascii * values. * @param encoder The encoder which is performing the encoding process * @param element The element which attribute is being encoded * @param attr The attribute which value is being encoded * @param value The value (it should be a string content) * @throws IOException Some error writing to the stream */ @Override public void encode(WbXmlEncoder encoder, WbXmlElement element, WbXmlAttribute attr, String value) throws IOException { if (value == null || value.isEmpty()) { return; } // iterate over the value and remove the string // Format: YYYY-MM-DDTHH:mm:ssZ StringBuilder sb = new StringBuilder(); for (int i = 0; i < value.length(); i++) { char ch = value.charAt(i); if (!Character.isDigit(ch)) { if (ch != 'T' && ch != 'Z' && ch != '-' && ch != ':') { throw new IOException(String.format("Invalid date format '%s'!", value)); } } else { sb.append(ch); } } // write the data in ASCII charset (only 0-9 data) byte[] bytes = charArrayToHexArray(sb.toString().toCharArray()); encoder.writeOpaque(bytes); } /** * Method that parses the binary data to reconstruct the ISO8601 date time * string. The method just gets the bunch of bytes and reconstryct the * string. * @param parser The parser which is performing the decoding/parsing process * @param data The data read from the opaque value * @return The string content representing the date time * @throws IOException */ @Override public String parse(WbXmlParser parser, byte[] data) throws IOException { if (data == null) { return null; } String value = new String(hexArrayToCharArray(data)); // The value can be YYYYMMDD, YYYYMMDDHH, YYYYMMDDHHmm or YYYYMMDDHHmmss String year = "0000"; if (value.length() >= 4) { year = value.substring(0, 4); } String month = "00"; if (value.length() >= 6) { month = value.substring(4, 6); } String day = "00"; if (value.length() >= 8) { day = value.substring(6, 8); } String hour = "00"; if (value.length() >= 10) { hour = value.substring(8, 10); } String minute = "00"; if (value.length() >= 12) { minute = value.substring(10, 12); } String second = "00"; if (value.length() >= 14) { second = value.substring(12, 14); } return new StringBuilder(year) .append("-") .append(month) .append("-") .append(day) .append("T") .append(hour) .append(":") .append(minute) .append(":") .append(second) .append("Z") .toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy