/* * TeleStax, Open Source Cloud Communications * Copyright 2012, Telestax Inc and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.mobicents.protocols.ss7.isup.impl.message.parameter; import javolution.xml.XMLFormat; import javolution.xml.stream.XMLStreamException; import org.mobicents.protocols.ss7.isup.ParameterException; import org.mobicents.protocols.ss7.isup.message.parameter.GenericDigits; import org.mobicents.protocols.ss7.isup.util.BcdHelper; import javax.xml.bind.DatatypeConverter; import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; /** * Start time:12:24:47 2009-03-31<br> * Project: mobicents-isup-stack<br> * * @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a> * @author <a href="mailto:grzegorz.figiel@pro-ids.com"> Grzegorz Figiel </a> */ public class GenericDigitsImpl extends AbstractISUPParameter implements GenericDigits { private static final String ENCODING_SCHEME = "encodingScheme"; private static final String TYPE_OF_DIGITS = "typeOfDigits"; private static final String DIGITS = "digits"; private static final Charset asciiCharset = Charset.forName("ASCII"); private static final int DEFAULT_VALUE = 0; private int encodingScheme; private int typeOfDigits; private byte[] digits; public GenericDigitsImpl(byte[] b) throws ParameterException { super(); decode(b); } public GenericDigitsImpl(int encodingScheme, int typeOfDigits, byte[] digits) { super(); this.encodingScheme = encodingScheme; this.typeOfDigits = typeOfDigits; this.setEncodedDigits(digits); } public GenericDigitsImpl(int encodingScheme, int typeOfDigits, String digits) throws UnsupportedEncodingException { super(); this.typeOfDigits = typeOfDigits; setDecodedDigits(encodingScheme, digits); } public GenericDigitsImpl() { super(); } public String getDecodedDigits() throws UnsupportedEncodingException { switch (encodingScheme) { case GenericDigits._ENCODING_SCHEME_BCD_EVEN: case GenericDigits._ENCODING_SCHEME_BCD_ODD: return BcdHelper.bcdDecodeToHexString(encodingScheme, digits); case GenericDigits._ENCODING_SCHEME_IA5: return new String(digits, asciiCharset); default: //TODO: add other encoding schemas support throw new UnsupportedEncodingException("Specified GenericDigits encoding: " + encodingScheme + " is unsupported"); } } public void setDecodedDigits(int encodingScheme, String digits) throws UnsupportedEncodingException { if (digits == null || digits.length() < 1) { throw new IllegalArgumentException("Digits must not be null or zero length"); } switch (encodingScheme) { case GenericDigits._ENCODING_SCHEME_BCD_EVEN: case GenericDigits._ENCODING_SCHEME_BCD_ODD: if ((digits.length() % 2) == 0) { if (encodingScheme == GenericDigits._ENCODING_SCHEME_BCD_ODD) throw new UnsupportedEncodingException("SCHEME_BCD_ODD is possible only for odd digits count"); } else { if (encodingScheme == GenericDigits._ENCODING_SCHEME_BCD_EVEN) throw new UnsupportedEncodingException("SCHEME_BCD_EVEN is possible only for odd digits count"); } this.encodingScheme = encodingScheme; this.setEncodedDigits(BcdHelper.encodeHexStringToBCD(digits)); break; case GenericDigits._ENCODING_SCHEME_IA5: this.encodingScheme = encodingScheme; this.setEncodedDigits(digits.getBytes(asciiCharset)); break; default: //TODO: add other encoding schemas support throw new UnsupportedEncodingException("Specified GenericDigits encoding: " + encodingScheme + " is unsupported"); } } public int decode(byte[] b) throws ParameterException { if (b == null || b.length < 2) { throw new ParameterException("byte[] must not be null or has size less than 2"); } this.typeOfDigits = b[0] & 0x1F; this.encodingScheme = (b[0] >> 5) & 0x07; this.digits = new byte[b.length - 1]; for (int index = 1; index < b.length; index++) { this.digits[index - 1] = b[index]; } return 1 + this.digits.length; } public byte[] encode() throws ParameterException { byte[] b = new byte[this.digits.length + 1]; b[0] |= this.typeOfDigits & 0x1F; b[0] |= ((this.encodingScheme & 0x07) << 5); for (int index = 1; index < b.length; index++) { b[index] = (byte) this.digits[index - 1]; } return b; } public int getEncodingScheme() { return encodingScheme; } public void setEncodingScheme(int encodingScheme) { this.encodingScheme = encodingScheme; } public int getTypeOfDigits() { return typeOfDigits; } public void setTypeOfDigits(int typeOfDigits) { this.typeOfDigits = typeOfDigits; } public byte[] getEncodedDigits() { return digits; } public void setEncodedDigits(byte[] digits) { if (digits == null) throw new IllegalArgumentException("Digits must not be null"); this.digits = digits; } public int getCode() { return _PARAMETER_CODE; } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("GenericDigits [encodingScheme="); sb.append(encodingScheme); sb.append(", typeOfDigits="); sb.append(typeOfDigits); if (digits != null) { sb.append(", encodedDigits=["); sb.append(DatatypeConverter.printHexBinary(digits)); sb.append("]"); try { String s = getDecodedDigits(); sb.append(", decodedDigits=["); sb.append(s); sb.append("]"); } catch (Exception e) { } } sb.append("]"); return sb.toString(); } /** * XML Serialization/Deserialization */ protected static final XMLFormat<GenericDigitsImpl> ISUP_GENERIC_DIGITS_XML = new XMLFormat<GenericDigitsImpl>( GenericDigitsImpl.class) { @Override public void read(javolution.xml.XMLFormat.InputElement xml, GenericDigitsImpl genericDigits) throws XMLStreamException { genericDigits.encodingScheme = xml.getAttribute(ENCODING_SCHEME, DEFAULT_VALUE); genericDigits.typeOfDigits = xml.getAttribute(TYPE_OF_DIGITS, DEFAULT_VALUE); ByteArrayContainer bc = xml.get(DIGITS, ByteArrayContainer.class); if (bc != null) { genericDigits.digits = bc.getData(); } } @Override public void write(GenericDigitsImpl genericDigits, javolution.xml.XMLFormat.OutputElement xml) throws XMLStreamException { xml.setAttribute(ENCODING_SCHEME, genericDigits.encodingScheme); xml.setAttribute(TYPE_OF_DIGITS, genericDigits.typeOfDigits); if (genericDigits.digits != null) { ByteArrayContainer bac = new ByteArrayContainer(genericDigits.digits); xml.add(bac, DIGITS, ByteArrayContainer.class); } } }; }