ReferenceNumberGeneratorBuilder.java

  1. package fr.sii.ogham.sms.builder.cloudhopper;

  2. import java.util.Random;

  3. import fr.sii.ogham.core.builder.Builder;
  4. import fr.sii.ogham.core.builder.context.BuildContext;
  5. import fr.sii.ogham.core.fluent.AbstractParent;
  6. import fr.sii.ogham.sms.splitter.RandomReferenceNumberGenerator;
  7. import fr.sii.ogham.sms.splitter.ReferenceNumberGenerator;

  8. /**
  9.  * In the cellular phone industry, mobile phones and their networks sometimes
  10.  * support concatenated short message service (or concatenated SMS) to overcome
  11.  * the limitation on the number of characters that can be sent in a single SMS
  12.  * text message transmission (which is usually 160). Using this method, long
  13.  * messages are split into smaller messages by the sending device and recombined
  14.  * at the receiving end. Each message is then billed separately. When the
  15.  * feature works properly, it is nearly transparent to the user, appearing as a
  16.  * single long text message.
  17.  *
  18.  * <p>
  19.  * One way of sending concatenated SMS (CSMS) is to split the message into 153
  20.  * 7-bit character parts (134 octets), and sending each part with a User Data
  21.  * Header (UDH) tacked onto the beginning. A UDH can be used for various
  22.  * purposes and its contents and size varies accordingly, but a UDH for
  23.  * concatenating SMSes look like this:
  24.  *
  25.  * <ul>
  26.  * <li>Field 1 (1 octet): Length of User Data Header, in this case 05.</li>
  27.  * <li>Field 2 (1 octet): Information Element Identifier, equal to 00
  28.  * (Concatenated short messages, 8-bit reference number)</li>
  29.  * <li>Field 3 (1 octet): Length of the header, excluding the first two fields;
  30.  * equal to 03</li>
  31.  * <li>Field 4 (1 octet): 00-FF, CSMS reference number, must be same for all the
  32.  * SMS parts in the CSMS</li>
  33.  * <li>Field 5 (1 octet): 00-FF, total number of parts. The value shall remain
  34.  * constant for every short message which makes up the concatenated short
  35.  * message. If the value is zero then the receiving entity shall ignore the
  36.  * whole information element</li>
  37.  * <li>Field 6 (1 octet): 00-FF, this part's number in the sequence. The value
  38.  * shall start at 1 and increment for every short message which makes up the
  39.  * concatenated short message. If the value is zero or greater than the value in
  40.  * Field 5 then the receiving entity shall ignore the whole information element.
  41.  * [ETSI Specification: GSM 03.40 Version 5.3.0: July 1996]</li>
  42.  * </ul>
  43.  *
  44.  * <p>
  45.  * It is possible to use a 16 bit CSMS reference number in order to reduce the
  46.  * probability that two different concatenated messages are sent with identical
  47.  * reference numbers to a receiver. In this case, the User Data Header shall be:
  48.  *
  49.  * <ul>
  50.  * <li>Field 1 (1 octet): Length of User Data Header (UDL), in this case
  51.  * 06.</li>
  52.  * <li>Field 2 (1 octet): Information Element Identifier, equal to 08
  53.  * (Concatenated short messages, 16-bit reference number)</li>
  54.  * <li>Field 3 (1 octet): Length of the header, excluding the first two fields;
  55.  * equal to 04</li>
  56.  * <li>Field 4 (2 octets): 0000-FFFF, CSMS reference number, must be same for
  57.  * all the SMS parts in the CSMS</li>
  58.  * <li>Field 5 (1 octet): 00-FF, total number of parts. The value shall remain
  59.  * constant for every short message which makes up the concatenated short
  60.  * message. If the value is zero then the receiving entity shall ignore the
  61.  * whole information element</li>
  62.  * <li>Field 6 (1 octet): 00-FF, this part's number in the sequence. The value
  63.  * shall start at 1 and increment for every short message which makes up the
  64.  * concatenated short message. If the value is zero or greater than the value in
  65.  * Field 5 then the receiving entity shall ignore the whole information element.
  66.  * [ETSI Specification: GSM 03.40 Version 5.3.0: July 1996]</li>
  67.  * </ul>
  68.  *
  69.  *
  70.  * Configures reference number generation strategy.
  71.  *
  72.  *
  73.  * @author AurĂ©lien Baudet
  74.  *
  75.  */
  76. public class ReferenceNumberGeneratorBuilder extends AbstractParent<MessageSplitterBuilder> implements Builder<ReferenceNumberGenerator> {
  77.     private final BuildContext buildContext;
  78.     private Random random;
  79.     private ReferenceNumberGenerator custom;

  80.     /**
  81.      * Initializes the builder with a parent builder. The parent builder is used
  82.      * when calling {@link #and()} method.
  83.      *
  84.      * @param parent
  85.      *            the parent builder
  86.      * @param buildContext
  87.      *            for registering instances and property evaluation
  88.      */
  89.     public ReferenceNumberGeneratorBuilder(MessageSplitterBuilder parent, BuildContext buildContext) {
  90.         super(parent);
  91.         this.buildContext = buildContext;
  92.     }

  93.     /**
  94.      * Uses a random number for reference number.
  95.      *
  96.      * It uses an instance of {@link Random} to generate random numbers.
  97.      *
  98.      * @return this instance for fluent chaining
  99.      */
  100.     @SuppressWarnings("squid:S2245")
  101.     public ReferenceNumberGeneratorBuilder random() {
  102.         return random(new Random());
  103.     }

  104.     /**
  105.      * Uses a random number for reference number. The provided {@link Random}
  106.      * instance is used to generate random numbers.
  107.      *
  108.      * <p>
  109.      * If this method is called several times, only the last {@link Random}
  110.      * instance is used.
  111.      *
  112.      * <p>
  113.      * If random parameter is {@code null} then any previously registered
  114.      * {@link Random} instance won't be used.
  115.      *
  116.      * @param random
  117.      *            the {@link Random} instance used to generate random numbers
  118.      * @return this instance for fluent chaining
  119.      */
  120.     public ReferenceNumberGeneratorBuilder random(Random random) {
  121.         this.random = random;
  122.         return this;
  123.     }

  124.     /**
  125.      * Uses a custom reference number generation strategy. This strategy takes
  126.      * precedence over any other generation strategy.
  127.      *
  128.      * <p>
  129.      * If this method is called several times, only the last registered
  130.      * generator is used.
  131.      *
  132.      * <p>
  133.      * If custom parameter is {@code null}, the custom strategy is disabled.
  134.      * Other previously configured strategies (like {@link #random()}) will be
  135.      * used instead.
  136.      *
  137.      * @param custom
  138.      *            custom reference number generation strategy
  139.      * @return this instance for fluent chaining
  140.      */
  141.     public ReferenceNumberGeneratorBuilder generator(ReferenceNumberGenerator custom) {
  142.         this.custom = custom;
  143.         return this;
  144.     }

  145.     @Override
  146.     public ReferenceNumberGenerator build() {
  147.         if (custom != null) {
  148.             return custom;
  149.         }
  150.         if (random != null) {
  151.             return buildContext.register(new RandomReferenceNumberGenerator(random));
  152.         }
  153.         return buildContext.register(new RandomReferenceNumberGenerator());
  154.     }
  155. }