Package center.system.msg

Source Code of center.system.msg.ISO8583Field

package center.system.msg;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map;
import java.util.TreeMap;

import javax.xml.crypto.Data;

import ru.vassaev.core.exception.SysException;
import ru.vassaev.core.io.CloseableOutputStream;
import ru.vassaev.core.util.Strings;

/**
* Формат поля ISO8583
*
* @author Vassaev A.V.
* @version 1.0 21/08/2012
*/
public class ISO8583Field extends CloseableOutputStream {
  private static final String charset = "ibm866";
  // Буфер для поля
  private byte[] dta = null;
  private boolean left = false;
  // Длина буфера для длины поля в байтах
  private final int vl;
  // Максимальная длина поля в байтах
  private final int maxl;
  // Длина длины подполя в байтах или в полубайтах
  private final int fl;
  // Длина кода подполя в байтах или в полубайтах
  private final int fc;
  // Длина в 16-ричной кодировке
  public final boolean isHexH;
  // Тело поля в 16-ричной кодировке
  public final boolean isHexB;
  // Наименование поля
  public final String name;
  public final boolean bytes;

  /**
   * Конструктор
   *
   * @param name
   *            - наименование поля
   * @param frmt
   *            - формат, заданный строкой 12 - поле 12 байт 12H - поле 12
   *            байт содержит 24 знака из множества цифр 10-ричной системы
   *            счислени LL12 - поле максимальной длины 12 байтов, поле длины
   *            - 2 байта в буквенной-цифровом формате LL12H - поле
   *            максимальной длины 12 знака из множества цифр 10-рично системы
   *            счисления (6 байтов), поле длины - 2 байта в
   *            буквенной-цифровом формате HH11H - поле максимальной длины 6
   *            (=11/2) байт содержит 11 знаков из множества цифр 10-рично
   *            системы счисления. поле длины - 2 знака и 1 байт HHH11 - поле
   *            длины - 3 знака и 2 байта, максимальная длина - 11 знаков
   *
   *            HH99[LLCC] LLL120[LLCC]H
   *
   */
  public ISO8583Field(String name, String frmt) {
    this.name = name;
    int l = frmt.length();
    int vl = 0;
    int i = 0;
    boolean isHexH = false;
    char ch;
    // Читаем информацию о буфере для длины
    for (; i < l; i++) {
      ch = frmt.charAt(i);
      if (ch == 'L')
        vl++;
      else if (ch == 'H') {
        vl++;
        isHexH = true;
      } else
        break;
    }
    this.isHexH = isHexH;
    this.vl = vl;
    ch = frmt.charAt(l - 1);
    this.isHexB = (l > 1 && (ch == 'H' || ch == 'h' || ch == 'B'));
    if (ch == 'h')
      left = true;
    bytes = (ch == 'B');
    i = frmt.indexOf('[', i);
    if (i > vl) {
      this.maxl = Integer.parseInt(frmt.substring(vl, i));
      i++;
      int fl_ = 0;
      int fc_ = 0;
      for (; i < l; i++) {
        ch = frmt.charAt(i);
        switch (ch) {
        case 'L':
          fl_++;
          break;
        case 'C':
          fc_++;
          break;
        }
        if (ch == ']')
          break;
      }
      fc = fc_;
      fl = fl_;
    } else {
      this.maxl = Integer.parseInt(frmt.substring(vl, l
          - ((isHexB) ? 1 : 0)));
      fc = 0;
      fl = 0;
    }
    int fl = ((isHexH) ? vl / 2 + vl % 2 : vl)
        + ((isHexB && !bytes) ? maxl / 2 + maxl % 2 : maxl);
    this.dta = new byte[fl];
    reset();
  }

  /**
   * Получить значение поля
   *
   * @return Значение в виде строки
   */
  public String getValue() throws SysException {
    int hl = (isHexH) ? vl / 2 + vl % 2 : vl;
    int bl = getFullLengthByte();
    if (bl == 0)
      return null;
    if (isHexB) {
      StringBuffer sb = new StringBuffer();
      for (int i = hl; i < bl; i++) {
        String v = Integer.toHexString(dta[i] & 0xff).toUpperCase();
        if (v.length() == 1)
          sb.append('0');
        sb.append(v);
      }
      if (getLengthValue() % 2 == 0)
        return sb.toString();
      if (left)
        return sb.substring(0, sb.length() - 1);
      return sb.substring(1);
    } else
      try {
        return new String(dta, hl, bl - hl, charset);
      } catch (UnsupportedEncodingException e) {
        throw new SysException(e);
      }
  }

  /**
   * Установить значение поля
   *
   * @param value
   *            - устанавливаемое значение
   * @throws SysException
   */
  public void setValue(String value) throws SysException {
    int l = value.length();
    if (l / (bytes ? 2 : 1) > maxl)
      throw new SysException("Inequality data and format for field \""
          + name + "\"");
    if ((vl == 0 && l / (bytes ? 2 : 1) < maxl) || (vl > 0 & l / (bytes ? 2 : 1) >= Math.pow(10, vl)))
      throw new SysException("Inequality data and format for field \""
          + name + "\"");
    // Записать тело
    if (isHexB) { // TODO
      int i = isHexH ? vl / 2 + vl % 2 : vl;
      int j = 0;
      int k = 0;
      if (l % 2 != 0 && !left) {
        dta[i] = (byte) (Byte.parseByte(value.substring(j, j + 1), 16) & 0xff);
        k = 1;
      }
      for (; j + k < l; j++) {
        int b = Byte.parseByte(value.substring(j + k, j + k + 1), 16) << 4;
        j++;
        if (j + k < l)
          b = b
              | Byte.parseByte(value.substring(j + k, j + k + 1),
                  16);
        dta[i + k + (j >> 1)] = (byte) (0xff & b);
      }
    } else {
      int i = isHexH ? vl / 2 + vl % 2 : vl;
      byte[] buf;
      try {
        buf = value.getBytes(charset);
      } catch (UnsupportedEncodingException e) {
        throw new SysException(e);
      }
      System.arraycopy(buf, 0, dta, i, buf.length);
    }
    // Установка длины
    if (vl > 0) {
      String ls = Strings.lpad(String.valueOf(l / (bytes ? 2 : 1)), vl, '0');
      if (isHexH) {
        int j = 0;
        int k = 0;
        if (vl % 2 != 0) {
          dta[0] = (byte) (Byte.parseByte(ls.substring(j, j + 1), 16) & 0xff);
          k = 1;
        }
        for (; j + k < vl; j++) {
          int b = Byte.parseByte(ls.substring(j + k, j + k + 1), 16) << 4;
          j++;
          b = b | Byte.parseByte(ls.substring(j + k, j + k + 1), 16);
          dta[k + j >> 1] = (byte) (0xff & b);
        }
      } else {
        int j = 0;
        for (; j < vl; j++)
          dta[j] = (byte) (0xff & ls.charAt(j));
      }
    }
  }

  /**
   * Возвращает количество знаков в значении поля
   *
   * @return Количество знаков
   */
  public int getLengthValue() {
    if (vl > 0) {
      if (isHexH) {
        StringBuffer sb = new StringBuffer();
        for (int k = 0; k < vl / 2 + vl % 2; k++) {
          String v = Integer.toHexString(dta[k] & 0xff);
          if (v.length() == 1)
            sb.append('0');
          sb.append(v);
        }
        return (Integer.parseInt(sb.toString()) * (bytes ? 2 : 1));
      }
      String ls = new String(dta, 0, vl);
      return Integer.parseInt(ls) * (bytes ? 2 : 1);
    }
    return maxl;
  }

  /**
   * Возвращает полную длину поля в байтах (включая место под длину)
   *
   * @return длина в байтах
   */
  public int getFullLengthByte() {
    if (vl > 0) {
      if (isHexH) {
        StringBuffer sb = new StringBuffer();
        for (int k = 0; k < vl / 2 + vl % 2; k++) {
          String v = Integer.toHexString(dta[k] & 0xff);
          if (v.length() == 1)
            sb.append('0');
          sb.append(v);
        }
        int lb = Integer.parseInt(sb.toString()) * (bytes ? 2 : 1);
        if (isHexB)
          return lb / 2 + lb % 2 + vl / 2 + vl % 2;
        return lb + vl / 2 + vl % 2;
      }
      String ls = new String(dta, 0, vl);
      int lb = Integer.parseInt(ls);
      if (isHexB)
        return lb / 2 + lb % 2 + vl;
      return lb + vl;
    } else {
      if (isHexB)
        return maxl / 2 + maxl % 2;
      return maxl;
    }
  }

  /**
   * Получить данные для передачи по сети
   *
   * @return массив байт
   */
  public byte[] getData() {
    if (vl > 0) {
      int l = getFullLengthByte();
      byte[] res = new byte[l];
      System.arraycopy(dta, 0, res, 0, l);
      return res;
    } else
      return dta;
  }

  /**
   * Получить данные для отображения в 16-ричном формате
   *
   * @return строка данных
   */
  public String getDataStr16() {
    int l = getFullLengthByte();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < l; i++) {
      String b = Integer.toHexString(0xff & dta[i]).trim();
      if (b.length() == 1)
        sb.append('0');
      sb.append(b);
      if (i < l - 1)
        sb.append(' ');
    }
    return sb.toString();
  }

  /**
   * Получить формат
   */
  public String toString() {
    StringBuffer s = new StringBuffer();
    char ch = (isHexH) ? 'H' : 'L';
    for (int i = 0; i < vl; i++)
      s.append(ch);
    s.append(maxl);
    if (fl > 0 || fc > 0) {
      s.append('[');
      for (int i = 0; i < fl; i++)
        s.append('L');
      for (int i = 0; i < fc; i++)
        s.append('C');
      s.append(']');
    }
    if (isHexB)
      if (left)
        s.append('h');
      else if (bytes)
        s.append('B');
      else
        s.append('H');
    return s.toString();
  }

  /**
   * Получить значение тега
   *
   * @param tag
   *            - имя тега
   * @return Значение тега
   * @throws SysException
   */
  public String getTag(String tag) throws SysException {
    return getTagOfField(getValue(), tag, fl, fc);
  }

  /**
   * Установить значение тега
   *
   * @param tag
   *            - имя тега
   * @param val
   *            - значение тега
   * @throws SysException
   */
  public void setTag(String tag, String val) throws SysException {
    String value = setTagOfField(getValue(), tag, val, fl, fc);
    setValue(value);
  }

  /**
   * Получить список всех тегов и их значения
   *
   * @return множество тегов
   * @throws SysException
   */
  public Map<String, Object> getTags() throws SysException {
    return getTagsOfField(getValue(), fl, fc);
  }

  /**
   * Чтение тега из поля
   *
   * @param fld
   *            - поле
   * @param tag
   *            - имя тега
   * @param fl
   *            - длина длины поля
   * @param fc
   *            - длина кода поля
   * @return значение
   * @throws ru.vassaev.core.exception.SysException
   *             - общая ошибка
   */
  public static String getTagOfField(String fld, String tag, int fl, int fc) {
    int len = fld.length();
    try {
      String t;
      String v;
      int k = 0;
      do {
        int i = k;
        k = i + fl;
        t = fld.substring(i, k); // Длина
        i = k;
        k = i + fc;
        int l = Integer.parseInt(fld.substring(i, k));// Код
        i = k;
        k = i + l;
        v = fld.substring(i, k); // Значение
      } while ((!tag.equals(t)) && (k < len));
      if (tag.equals(t))
        return v;
      return null;
    } catch (NumberFormatException ex) {
      return null;
    } catch (ArrayIndexOutOfBoundsException ex) {
      return null;
    }
  }

  /**
   * Установить тег в поле
   *
   * @param fld
   *            - имя поля
   * @param tag
   *            - имя тега
   * @param val
   *            - значение
   * @throws SysException
   *             - общая ошибка
   */
  public static String setTagOfField(String fld, String tag, String val,
      int fl, int fc) throws SysException {
    int lv = val.length();
    try {
      // Получить длину поля
      int len = fld.length();
      StringBuffer res = new StringBuffer();
      String t = "";
      String v = "";
      String t1 = "";
      int k = 0;
      if (k < len)
        do {
          res.append(t).append(t1).append(v);
          int i = k;
          k = i + fl;
          t = fld.substring(i, k);
          i = k;
          k = i + fc;
          int l = Integer.parseInt(t);
          t1 = fld.substring(i, k);
          i = k;
          k = i + l - fc;
          v = fld.substring(i, k);
        } while ((!tag.equals(t1)) && (k < len));
      if (!tag.equals(t1))
        res.append(t).append(t1).append(v);
      if (lv > 0)
        res.append(Strings.lpad(String.valueOf(lv + fc), fl, '0'))
            .append(Strings.lpad(String.valueOf(tag), fc, '0'))
            .append(val);

      if (k < len)
        res.append(fld.substring(k));
      return res.toString();
    } catch (NumberFormatException ex) {
      throw new SysException("This field is not tag field");
    } catch (ArrayIndexOutOfBoundsException ex) {
      throw new SysException("This field is not tag field");
    }
  }

  /**
   * Получить список тегов в поле
   *
   * @param name
   *            - имя
   * @throws SysException
   *             - ошибка разбора
   * @return Таблицу тегов
   */
  public Map<String, Object> getTagsOfField(String fld, int fl, int fc)
      throws SysException {
    try {
      int len = fld.length();
      Map<String, Object> res = new TreeMap<String, Object>();
      String t;
      String v;
      int k = 0;
      do {
        int i = k;
        k = i + fl;
        t = fld.substring(i, k);// Имя тега
        i = k;
        k = i + fc;
        int l = Integer.parseInt(fld.substring(i, k));// длина тега
        i = k;
        k = i + l;
        v = fld.substring(i, k);// значение тега
        res.put(t, v);
      } while (k < len);
      return res;
    } catch (NumberFormatException ex) {
      throw new SysException("This field is not tag field");
    } catch (ArrayIndexOutOfBoundsException ex) {
      throw new SysException("This field is not tag field");
    }
  }

  // Текущая позиция для записи следующего байта из потока
  private int p = 0;

  public void add(byte val) {
    dta[p] = val;
    p++;
  }

  public void reset() {
    p = 0;
    if (isHexH)
      for (int i = 0; i < vl / 2 + vl % 2; i++)
        dta[i] = 0;
    else
      for (int i = 0; i < vl; i++)
        dta[i] = '0';
  }

  /**
   * Возвращает текущую позиция для записи следующего байта
   *
   * @return текущая позиция для записи следующего байта из потока
   */
  public int getPosition() {
    return p;
  }

  public boolean isClosed() throws IOException {
    return (p >= getFullLengthByte());
  }

  public void write(int b) throws IOException {
    add((byte) (b & 0xff));
  }

  public static void main(String[] args) throws SysException {
    ISO8583Field fld = new ISO8583Field("55", "HHH255B");
    fld.setValue("9F2608C4C63949AA4CB87A9F2701009F100706010A0321A0049F370468C6C6019F3602001F950508000810009A031309309C01009F02060000000005005F2A0206439F1A0208409F03060000000000009F3303E0F8C84F07A00000000310109F34035E03009F3501229F1E0831323334353637389F5301528407A00000000310109F0902008C9F410400000001");
    System.out.println(fld.getValue());

    byte[] d = fld.getData();
    int l = d.length;
    System.out.println("Length = " + l);
    for (int i = 0; i < l; i++)
      System.out.print(Integer.toString(d[i] & 0xff, 16) + " ");
  }
}
TOP

Related Classes of center.system.msg.ISO8583Field

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.