public ASNClassFactory(GramarFile fileName) {
    RawClassFactory rcf = new RawClassFactory(fileName);
    String rootNodeName = rcf.getRootClassName();

    RawClass rawclass = rcf.getRawClass(rootNodeName);
    // System.out.printf("\n Got RawClass for %s from file %s = \n %s ", rootNodeName, fileName
    // ,rawclass);

    ASNClass asnClass = toASNClass(rcf, rawclass, Field.ROOTFIELD);
    asnClass.toArray(); // We assume that the Top Level ASNClass is always an Array Type.

    Map<String, String> options = loadControlFile(fileName);
    String OPTION_BLOCKSIZE = "BLOCKSIZE";
    String OPTION_PADDINGBYTE = "PADDINGBYTE";

    if (options.containsKey(OPTION_BLOCKSIZE)) {
      asnClass.blockSize = Integer.parseInt(options.get(OPTION_BLOCKSIZE));
    }
    if (options.containsKey(OPTION_PADDINGBYTE)) {
      asnClass.paddingByte = (byte) Integer.parseInt(options.get(OPTION_PADDINGBYTE), 16);
    }

    field = new Field(Field.ROOTFIELD, Field.ROOTFIELD, AsnConst.POS_NOT_SPECIFIED, asnClass);
  }
  // Whatever ASNClass I am going to return will be inside a Field class
  // called (its container). This container Field's longname is provided as arg
  // so all children fields in this class should be prefixed with
  // containerFieldLongName + "." + "fieldName"
  private ASNClass toASNClass(RawClassFactory rcf, RawClass rd, String containerFieldLongName) {
    depth++;
    try {
      if (AsnConst.isPrimitive(rd.className)) {
        return getPrimitive(rd.className);
      }
      ArrayList<ASNClass> childTypes = new ArrayList<ASNClass>();
      ArrayInfo[] childIsArray = rd.arrInfo;

      for (int i = 0; i < rd.fields.length; i++) { // for all fields inside this class
        if (rd.type[i].equals("")) {
          throw new ASNException("There is no Type for RawCls" + rd + "field inx = " + i);
        }
        RawClass tmp = null;
        try {
          tmp = rcf.getRawClass(rd.type[i]);
        } catch (ASNException asnexp) {
          throw new ASNException(
              null, "Error in " + rd.className + ".getRawClass1(" + rd.type[i] + ")", asnexp);
        }
        String fieldLongName = containerFieldLongName + "." + rd.fields[i];

        if (tmp.singleLiner) {
          if (tmp.relation.equals("SET OF") || tmp.relation.equals("SEQUENCE OF")) {
            childIsArray[i].setArray(true);
            if (tmp.relation.equals("SEQUENCE OF")) {
              childIsArray[i].setType(ArrayInfo.SEQ);
            } else {
              childIsArray[i].unsetType(ArrayInfo.SEQ);
            }
            // childIsArray[i].set(1,ArrayInfo.TYPE3); // = true; // As of now we only support
            // single dimension arrays!
          }
          if (AsnConst.isPrimitive(tmp.synonymn)) { // PRIMITIVE
            ASNClass tmpClass = getPrimitive(tmp.synonymn);
            childTypes.add(tmpClass);
          } else { // COMPOSITE or a COMPOSITE which is actually a synonym
            boolean hitMultiLiner = false;
            boolean hitMultiLinerWithPrimitive = false;
            while (!hitMultiLiner) { // Keep searching amongst
              // synonyms till Primitive
              // is encountered.
              try {
                tmp = rcf.getRawClass(tmp.synonymn);
              } catch (ASNException asnexp) {
                throw new ASNException(
                    null,
                    "Error in "
                        + "RawASNClass("
                        + rd.className
                        + ") Field("
                        + rd.fields[i]
                        + ") Type("
                        + rd.type[i]
                        + ") Position("
                        + (i + 1)
                        + "/"
                        + rd.fields.length
                        + ") getRawClass2("
                        + tmp.synonymn
                        + ")",
                    asnexp);
              }

              hitMultiLiner = !tmp.singleLiner;
              if (!hitMultiLiner) {
                if (AsnConst.isPrimitive(tmp.synonymn)) // PRIMITIVE
                {
                  hitMultiLinerWithPrimitive = true;
                  childTypes.add(getPrimitive(tmp.synonymn));
                }
              }
            }
            if (!hitMultiLinerWithPrimitive) {
              ASNClass tmpClass = toASNClass(rcf, tmp, fieldLongName);
              childTypes.add(tmpClass);
              // If this field is an array and this field's Class is a CHOICE OF
              if (childIsArray[i].isArray()
                  && tmpClass.relation != null
                  && //
                  tmpClass.relation.equals(AsnConst.RELATION_CHOICE)) {
                childIsArray[i].setType(ArrayInfo.CHO);
              }
            }
          }
        } else { // multiliner.
          ASNClass tmpClass = toASNClass(rcf, tmp, fieldLongName);
          childTypes.add(tmpClass);
          // Can use tmpClass.isReference() instead of tmpClass.relation.equals(RELATION_CHOICE)
          // since we are
          // setting the variable internally by tmp.isReference().
          if (childIsArray[i].isArray()
              && tmpClass.relation != null
              && //
              tmpClass.relation.equals(AsnConst.RELATION_CHOICE)) {
            childIsArray[i].setType(ArrayInfo.CHO);
          }
        }
      }
      ASNClass[] childArr = new ASNClass[childTypes.size()];
      childTypes.toArray(childArr);

      for (int i = 0; i < childArr.length; i++) {
        if (childArr[i].isAssociatedWithTag()) {
          childIsArray[i].setType(ArrayInfo.TAG);
        } else {
          childIsArray[i].unsetType(ArrayInfo.TAG);
        }
        childArr[i].arrInfo = childIsArray[i];
      }
      // Create a Field out of what we have =========================
      Field[] fieldList = new Field[childArr.length];

      for (int i = 0; i < fieldList.length; i++) {
        ASNClass tmp_class = childArr[i];
        String longFieldName = containerFieldLongName + "." + rd.fields[i];
        fieldList[i] = new Field(longFieldName, rd.fields[i], rd.pos[i], tmp_class);
      }

      // ASNClass(String name_, String relation_, Field[] fields_, ArrayInfo arrInfo_,int
      // associatedTag_) {
      asnarr = new ASNClass(rd.className, rd.relation, fieldList);
      // asnarr = new ASNClass(rd.className, rd.relation, rd.pos, rd.fields, childArr );
      asnarr.associatedTag = rd.associatedTag;

    } catch (ASNException e) {
      throw new ASNException(
          "asn cls fctr",
          "Exception caught inside toASNClass(RawClass(" //
              + rd.className
              + "))",
          e);
    } finally {
      depth--;
    }
    return asnarr;
  }