content: /*
   * Licensed to the Apache Software Foundation (ASF) under one or more
   * contributor license agreements.  See the NOTICE file distributed with
   * this work for additional information regarding copyright ownership.
   * The ASF licenses this file to You under the Apache License, Version 2.0
   * (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.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package org.apache.camel.component.smpp;
  
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  
  /**
   * Splitter for messages use National Language Lock Table
   * <p/>
   *
   * @see 3GPP 23.038 Reference
   */
  public class SmppNLSTSplitter extends SmppSplitter {
      /**
       * The length of the UDH for single short message in bytes. 0x25 - UDHIE_NLI_IDENTIFIER 0x01 - Length of the header
       * 0xXX - Locking shift table indicator the Language
       */
      protected static final int UDHIE_NLI_SINGLE_MSG_HEADER_LENGTH = 0x03; // header length for single message
      /**
       * The real length of the UDH for single short message
       */
      protected static final int UDHIE_NLI_SINGLE_MSG_HEADER_REAL_LENGTH = UDHIE_NLI_SINGLE_MSG_HEADER_LENGTH + 1;
  
      /**
       * The length of the UDH for splitted short messages, in bytes. 0x08 Overall header length 0x00 The value that
       * identifier length of the SAR fragment. (8bit reference number only) 0x03 The length of the SAR fragment 0xXX The
       * reference number for SAR 0xXX Total number of splitted / segmented messages 0xXX Segment number 0x25 National
       * language locking shift element identifier 0x01 Length of the header 0xXX Locking shift table indicator for the
       * Language (ie: 0x01 for Turkish)
       */
      protected static final int UDHIE_NLI_MULTI_MSG_HEADER_LENGTH = 0x08;
  
      /**
       * The real length of the UDH for segmentet short messages
       */
      protected static final int UDHIE_NLI_MULTI_MSG_HEADER_REAL_LENGTH = UDHIE_NLI_MULTI_MSG_HEADER_LENGTH + 1;
  
      /**
       * The element identifier value for the National Language Locking Table
       */
      protected static final int UDHIE_NLI_IDENTIFIER = 0x25;
      /**
       * The length of the NLI header
       */
      protected static final int UDHIE_NLI_HEADER_LENGTH = 0x01;
  
      /**
       * The maximum length in chars of the NLI messages.
       * <p/>
       * Each letter will be represented as 7 bit (like GSM8)
       */
      public static final int MAX_MSG_CHAR_SIZE = (MAX_MSG_BYTE_LENGTH * 8 / 7) - (UDHIE_NLI_SINGLE_MSG_HEADER_REAL_LENGTH + 1);
  
      public static final int MAX_SEG_BYTE_SIZE = (MAX_MSG_BYTE_LENGTH - UDHIE_NLI_MULTI_MSG_HEADER_REAL_LENGTH) * 8 / 7;
  
      /**
       * Locking shift table indicator for the Language, single byte
       */
      private byte languageIdentifier;
      private final Logger logger = LoggerFactory.getLogger(SmppNLSTSplitter.class);
  
      public SmppNLSTSplitter(int currentLength, byte languageIdentifier) {
          super(MAX_MSG_CHAR_SIZE, MAX_SEG_BYTE_SIZE, currentLength);
          this.languageIdentifier = languageIdentifier;
      }
  
      @Override
      public byte[][] split(byte[] message) {
          if (!isSplitRequired()) {
              byte[] nliMessage = new byte[UDHIE_NLI_SINGLE_MSG_HEADER_REAL_LENGTH + message.length];
              nliMessage[0] = (byte) UDHIE_NLI_SINGLE_MSG_HEADER_LENGTH;
              nliMessage[1] = (byte) UDHIE_NLI_IDENTIFIER;
              nliMessage[2] = (byte) UDHIE_NLI_HEADER_LENGTH;
              nliMessage[3] = this.languageIdentifier;
              System.arraycopy(message, 0, nliMessage, 4, message.length);
              return new byte[][] { nliMessage };
          }
  
          int segmentLength = getSegmentLength();
  
          // determine how many messages
          int segmentNum = message.length / segmentLength;
          int messageLength = message.length;
          if (segmentNum > MAX_SEG_COUNT) {
              // this is too long, can't fit, so chop
              segmentNum = MAX_SEG_COUNT;
              messageLength = segmentNum * segmentLength;
          }
          if ((messageLength % segmentLength) > 0) {
              segmentNum++;
          }
  
          byte[][] segments = new byte[segmentNum][];
  
          int lengthOfData;
          byte refNum = getReferenceNumber();
          for (int i = 0; i < segmentNum; i++) {
              logger.debug("segment number = {}", i);
              if (segmentNum - i == 1) {
                  lengthOfData = messageLength - i * segmentLength;
              } else {
                  lengthOfData = segmentLength;
              }
              logger.debug("Length of data = {}", lengthOfData);
  
              segments[i] = new byte[UDHIE_NLI_MULTI_MSG_HEADER_REAL_LENGTH + lengthOfData];
              logger.debug("segments[{}].length = {}", i, segments[i].length);
  
              segments[i][0] = UDHIE_NLI_MULTI_MSG_HEADER_LENGTH; // doesn't include itself, is header length
              // SAR identifier
              segments[i][1] = UDHIE_IDENTIFIER_SAR;
              // SAR length
              segments[i][2] = UDHIE_SAR_LENGTH;
              // DATAGRAM REFERENCE NUMBER
              segments[i][3] = refNum;
              // total number of segments
              segments[i][4] = (byte) segmentNum;
              // segment #
              segments[i][5] = (byte) (i + 1);
  
              // national language locking shift table, element identifier
              segments[i][6] = (byte) UDHIE_NLI_IDENTIFIER;
              segments[i][7] = (byte) UDHIE_NLI_HEADER_LENGTH;
              segments[i][8] = this.languageIdentifier;
  
              // now copy the data
              System.arraycopy(message, i * segmentLength, segments[i], UDHIE_NLI_MULTI_MSG_HEADER_REAL_LENGTH, lengthOfData);
          }
          return segments;
      }
  }
  