/**
   * Reads line by line and creates new entities
   *
   * @throws IOException
   * @throws IfcNotFoundException
   * @throws IfcParserException
   */
  public List<IfcEntity> parseEntities(
      IfcLineReader reader, IfcSchema schema, boolean isHeaderSection, boolean ignoreUnknownTypes)
      throws IOException, IfcNotFoundException, IfcParserException {

    this.schema = schema;
    this.reader = reader;

    List<IfcEntity> entities = new ArrayList<>();

    String statement;
    String[] tokens;
    //
    // getting entity headers
    //
    while ((statement = reader.getNextStatement()) != null) {

      IfcEntity entity;
      String entityAttributesString;

      if (!isHeaderSection) {
        tokens = RegexUtils.split2(statement, IfcVocabulary.StepFormat.LINE_NUMBER);
        if (tokens.length != 2) {
          continue;
        }

        tokens = RegexUtils.split2(tokens[1], IfcVocabulary.StepFormat.EQUAL);

        //
        // create entity
        //
        long lineNumber = Long.parseLong(tokens[0].trim());
        entity = getEntity(lineNumber);
        entityAttributesString = tokens[1].trim();

      } else {
        entity = new IfcEntity(0);
        entityAttributesString = statement;
      }

      //
      // set entity type
      //
      int indexOfOpeningBracket = entityAttributesString.indexOf(StringUtils.OPENING_ROUND_BRACKET);
      String entityTypeInfoName = entityAttributesString.substring(0, indexOfOpeningBracket).trim();

      IfcEntityTypeInfo entityTypeInfo;

      try {
        entityTypeInfo = schema.getEntityTypeInfo(entityTypeInfoName);
      } catch (IfcNotFoundException e) {
        if (ignoreUnknownTypes) {
          continue;
        } else {
          throw e;
        }
      }
      entity.setTypeInfo(entityTypeInfo);

      entityAttributesString =
          entityAttributesString.substring(
              indexOfOpeningBracket + 1, entityAttributesString.length() - 1);

      List<IfcAttributeInfo> attributeInfos = entityTypeInfo.getInheritedAttributeInfos();

      //
      // parse attribute string to get attribute values
      //
      List<IfcValue> attributeValues =
          parseAttributeValues(
              new StrBuilderWrapper(entityAttributesString), entity, attributeInfos, null, null);

      setEntityAttributeValues(entity, attributeInfos, attributeValues);

      //
      // add entity to the model
      //
      entities.add(entity);
    }

    if (!isHeaderSection) {
      for (IfcEntity entity : entities) {
        entity.bindInverseLinks();
      }
    }

    return entities;
  }