Package de.foconis.lsext

Source Code of de.foconis.lsext.LSExt2Java

package de.foconis.lsext;

/*----------------------------------------------------------------------------*/
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.openntf.formula.DateTime;
import org.openntf.formula.Formatter;
import org.openntf.formula.impl.FormatterImpl;

/*----------------------------------------------------------------------------*/
public class LSExt2Java {
  private String iLSExtStr;
  private int iLSExtStrLh;

  /*----------------------------------------------------------------------------*/
  public LSExt2Java(final String lsExtStr) {
    iLSExtStr = lsExtStr;
    iLSExtStrLh = lsExtStr.length();
  }

  /*----------------------------------------------------------------------------*/
  private ArrayList<String> iStringList;
  private ArrayList<Object> iObjectList;
  private int iActPos = 0;
  private Formatter iFormatter = null;

  /*----------------------------------------------------------------------------*/
  public Object toJavaObj() {
    String start = LSExt2JavaConsts.HEADER;
    if (!iLSExtStr.startsWith(start))
      throwExc("LS stream doesn't start with " + start);
    iActPos = start.length();
    assureAvailable(8);
    String hexVersion = iLSExtStr.substring(iActPos, iActPos + 8);
    long version = parseHexStr(hexVersion);
    if (version != LSExt2JavaConsts.VERSION)
      throwExc("Can't convert old LS ext stream version " + version);
    iActPos += 8;
    assureAvailable(1);
    if (iLSExtStr.charAt(iActPos++) != '$')
      throwExc("'$' expected after hex version");
    iStringList = new ArrayList<String>(256);
    iObjectList = new ArrayList<Object>(256);
    Object ret = toJavaObjRec();
    iStringList = null;
    iObjectList = null;
    if (iActPos != iLSExtStrLh)
      throwExc("End of stream expected");
    return ret;
  }

  /*----------------------------------------------------------------------------*/
  private Object toJavaObjRec() {
    String start = readString();
    if (start.isEmpty()) // STRING
      return toCache(readString());
    if (start.equals("N"))
      return null;
    String focIF = null;
    if (start.charAt(0) == ':') {
      focIF = start.substring(1);
      start = readString();
    }
    if (start.equals("@")) {
      int vInd = readInteger();
      if (vInd >= iObjectList.size())
        throwExc("Reference to Object " + vInd + " can't be satisfied");
      return iObjectList.get(vInd);
    }
    if (start.startsWith(LSExt2JavaConsts.BOX_PREFIX)) // Some Box
      return toCache(fromBox(start));
    if (start.equals(LSExt2JavaConsts.ARRAYLIST))
      return fromArrayList(focIF); // Cache before cache List elements!
    int strMapCase = -1;
    if (start.equals(LSExt2JavaConsts.STRINGMAP))
      strMapCase = 0;
    else if (start.equals(LSExt2JavaConsts.STRINGMAP_IC))
      strMapCase = 1;
    if (strMapCase >= 0)
      return fromStringMap(strMapCase == 1, focIF); // Cache before cache
    // Map elements!
    throwExc("Foc-Class " + start + " not yet supported");
    return null;
  }

  /*----------------------------------------------------------------------------*/
  private Object fromBox(final String focClass) {
    int boxType = readInteger();
    if (boxType == LSExt2JavaConsts.INTEGER || boxType == LSExt2JavaConsts.LONG)
      return fromBoxLong();
    if (boxType == LSExt2JavaConsts.DOUBLE || boxType == LSExt2JavaConsts.SINGLE)
      return fromBoxDouble();
    if (boxType == LSExt2JavaConsts.DATE)
      return fromBoxDate();
    throwExc("FocBox-Class " + focClass + " (type=" + boxType + ") not yet supported");
    return null;
  }

  /*----------------------------------------------------------------------------*/
  private Long fromBoxLong() {
    return new Long(readLong());
  }

  /*----------------------------------------------------------------------------*/
  private Double fromBoxDouble() {
    String dStr = readString();
    try {
      return Double.valueOf(dStr);
    } catch (NumberFormatException ne) {
      throwExc("Error converting " + dStr + " to Double: " + ne.getMessage());
    }
    return null;
  }

  /*----------------------------------------------------------------------------*/
  private DateTime fromBoxDate() {
    int year = readInteger();
    int month = readInteger();
    int day = readInteger();
    int hour = readInteger();
    int minute = readInteger();
    int second = readInteger();
    if (iFormatter == null)
      iFormatter = new FormatterImpl(Locale.getDefault());
    DateTime ret = iFormatter.getNewSDTInstance();
    ret.setLocalDate(year, month, day);
    ret.setLocalTime(hour, minute, second, 0);
    return ret;
  }

  /*----------------------------------------------------------------------------*/
  private List<Object> fromArrayList(final String focIF) {
    int listVersion = readInteger();
    if (listVersion != LSExt2JavaConsts.ARRAYLIST_VERSION)
      throwExc("FocArrayList version " + listVersion + " is not supported");
    int modCount = readInteger();
    int capacity = readInteger();
    int capacityIncrement = readInteger();
    int elementCount = readInteger();
    LSFocArrayList ret = new LSFocArrayList(elementCount, modCount, capacity, capacityIncrement, focIF);
    toCache(ret);
    for (int i = 0; i < elementCount; i++)
      ret.add(toJavaObjRec());
    return ret;
  }

  /*----------------------------------------------------------------------------*/
  private Map<String, Object> fromStringMap(final boolean caseInsensitive, final String focIF) {
    int mapVersion = readInteger();
    if (mapVersion != LSExt2JavaConsts.STRINGMAP_VERSION)
      throwExc("FocStringMap version " + mapVersion + " is not supported");
    int modCount = readInteger();
    int elementCount = readInteger();
    LSFocStringMap ret = new LSFocStringMap(caseInsensitive, modCount, focIF);
    toCache(ret);
    for (int i = 0; i < elementCount; i++) {
      String key = readString();
      ret.put(key, toJavaObjRec());
    }
    return ret;
  }

  /*----------------------------------------------------------------------------*/
  private Object toCache(final Object what) {
    iObjectList.add(what);
    return what;
  }

  /*----------------------------------------------------------------------------*/
  private String readString() {
    int sLh = readInteger();
    if (sLh == 0)
      return "";
    if (sLh < 0) {
      int vInd = (-sLh) - 1;
      if (vInd >= iStringList.size())
        throwExc("Reference to String " + sLh + " can't be satisfied");
      return iStringList.get(vInd);
    }
    assureAvailable(sLh);
    String ret = iLSExtStr.substring(iActPos, iActPos + sLh);
    iActPos += sLh;
    if (sLh >= LSExt2JavaConsts.MINCACHESTRLH && sLh <= LSExt2JavaConsts.MAXCACHESTRLH)
      iStringList.add(ret);
    return ret;
  }

  /*----------------------------------------------------------------------------*/
  private long readLong() {
    assureAvailable(1);
    char firstSign = iLSExtStr.charAt(iActPos++);
    boolean negative;
    if (firstSign == '-') {
      negative = true;
      assureAvailable(1);
      firstSign = iLSExtStr.charAt(iActPos++);
    } else
      negative = false;
    if (firstSign == '!' || firstSign == '\'' || firstSign == '&') {
      if (negative)
        throwExc("Invalid number format: " + '-' + firstSign);
      if (firstSign == '!')
        return -1;
      if (firstSign == '\'')
        return LSExt2JavaConsts.MIN_LS_INTEGER;
      return LSExt2JavaConsts.MIN_LS_LONG;
    }
    int needBytes;
    long ret;
    if (firstSign == '$')
      needBytes = 2;
    else if (firstSign == '%')
      needBytes = 4;
    else if (firstSign == '#')
      needBytes = 8;
    else
      needBytes = 0;
    if (needBytes == 0) {
      int aux = firstSign - '0';
      if (aux < 0 || aux > LSExt2JavaConsts.MAX_INT_1BYTE)
        throwExc("Invalid 1-character number: " + firstSign);
      ret = aux;
    } else {
      assureAvailable(needBytes);
      String hexStr = iLSExtStr.substring(iActPos, iActPos + needBytes);
      ret = parseHexStr(hexStr);
      iActPos += needBytes;
    }
    return negative ? -ret : ret;
  }

  /*----------------------------------------------------------------------------*/
  private int readInteger() {
    return (int) readLong();
  }

  /*----------------------------------------------------------------------------*/
  private void assureAvailable(final int howMany) {
    if (iActPos + howMany > iLSExtStrLh)
      throwExc("No more " + howMany + " byte(s) available in LS stream");
  }

  /*----------------------------------------------------------------------------*/
  private int parseHexStr(final String hexStr) {
    try {
      return Integer.parseInt(hexStr, 16);
    } catch (NumberFormatException ne) {
      throwExc("Error converting hex string " + hexStr + ": " + ne.getMessage());
    }
    return -1;
  }

  /*----------------------------------------------------------------------------*/
  private void throwExc(final String cause) {
    throw new LSExtConvertException(iActPos, cause);
  }

  /*----------------------------------------------------------------------------*/
  /*
   * Testunterstuetzung: Dump des Ergebnis-Objekts
   */
  /*----------------------------------------------------------------------------*/
  private PrintStream iDumpPS = null;

  public void dumpObject(final PrintStream ps, final Object o) {
    iDumpPS = ps;
    dumpObject(o, 0);
  }

  private void dumpObject(final Object o, final int level) {
    printLevelPrefix(level);
    if (o == null) {
      iDumpPS.println("*** NULL ***");
      return;
    }
    if (o instanceof List) {
      List<?> l = (List<?>) o;
      int sz = l.size();
      int modCount = -1;
      int capacity = -1;
      int capacityIncrement = -1;
      String focIF = null;
      if (o instanceof LSFocArrayList) {
        modCount = ((LSFocArrayList) o).getModCount();
        capacity = ((LSFocArrayList) o).getCapacity();
        capacityIncrement = ((LSFocArrayList) o).getCapacityIncrement();
        focIF = ((LSFocArrayList) o).getFocIF();
      }
      iDumpPS.println("LIST, size=" + sz + " FocIF=" + focIF + ", MC=" + modCount + "/CAP=" + capacity + "/CAPI=" + capacityIncrement);
      for (int i = 0; i < sz; i++) {
        printLevelPrefix(level + 1);
        iDumpPS.println("List element " + (i + 1));
        dumpObject(l.get(i), level + 2);
      }
      return;
    }
    if (o instanceof Map) {
      Map<?, ?> m = (Map<?, ?>) o;
      int sz = m.size();
      int modCount = -1;
      boolean caseInsensitive = false;
      String focIF = null;
      if (o instanceof LSFocStringMap) {
        modCount = ((LSFocStringMap) o).getModCount();
        caseInsensitive = ((LSFocStringMap) o).isCaseInsensitive();
        focIF = ((LSFocStringMap) o).getFocIF();
      }
      iDumpPS.println("MAP, size=" + sz + ", CaseInsensitive=" + caseInsensitive + ", FocIF=" + focIF + ", MC=" + modCount);
      int i = 0;
      Set<?> s = m.entrySet();
      for (Object so : s) {
        Map.Entry<?, ?> me = (Map.Entry<?, ?>) so;
        printLevelPrefix(level + 1);
        iDumpPS.println("Map element " + (i + 1) + ", Key=" + me.getKey());
        dumpObject(me.getValue(), level + 2);
        i++;
      }
      return;
    }
    if (o instanceof String) {
      String s = (String) o;
      iDumpPS.println("(String)=" + s);
      return;
    }
    if (o instanceof Long) {
      Long l = (Long) o;
      iDumpPS.println("(Long)=" + l.toString());
      return;
    }
    if (o instanceof Double) {
      Double d = (Double) o;
      iDumpPS.println("(Double)=" + d.toString());
      return;
    }
    if (o instanceof DateTime) {
      DateTime d = (DateTime) o;
      iDumpPS.println("(DateTime)=" + d.toString());
      return;
    }
    throw new LSExtConvertException("Unsupported Java type: " + o.getClass().getName());
  }

  private void printLevelPrefix(int i) {
    while (i-- != 0)
      iDumpPS.print("  ");
  }

  /*----------------------------------------------------------------------------*/
TOP

Related Classes of de.foconis.lsext.LSExt2Java

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.