/**
   * See Interface for functional description.
   *
   * @param xmlData aggregationDefinition as xml in aggregationDefinition schema.
   * @return Returns the XML representation of the resource.
   * @throws MissingMethodParameterException ex
   * @throws ScopeNotFoundException ex
   * @throws SystemException ex
   * @see de.escidoc.core.sm.business.interfaces
   *     .AggregationDefinitionHandlerInterface#create(java.lang.String)
   */
  @Override
  @Transactional(rollbackFor = {SystemException.class, RuntimeException.class})
  public String create(final String xmlData)
      throws MissingMethodParameterException, ScopeNotFoundException, SystemException {
    if (xmlData == null || xmlData.length() == 0) {
      throw new MissingMethodParameterException("xml may not be null");
    }

    // parse
    final StaxParser sp = new StaxParser();
    final AggregationDefinitionStaxHandler handler = new AggregationDefinitionStaxHandler(sp);
    sp.addHandler(handler);
    try {
      sp.parse(xmlData);
    } catch (final Exception e) {
      throw new SystemException(e);
    }

    final String scopeId = handler.getAggregationDefinition().getScope().getId();
    final Scope scope = scopesDao.retrieve(scopeId);

    // get AggregationDefinitionObject to insert aggregation-definition
    // into database
    final AggregationDefinition aggregationDefinition = handler.getAggregationDefinition();
    aggregationDefinition.setCreatorId(utility.getCurrentUserId());
    aggregationDefinition.setCreationDate(new Timestamp(System.currentTimeMillis()));
    aggregationDefinition.setScope(scope);

    dao.save(aggregationDefinition);
    handler.setAggregationDefinition(aggregationDefinition);

    // AggregationStatisticDataSelectors
    for (final AggregationStatisticDataSelector selector :
        handler.getAggregationStatisticDataSelectors()) {
      dao.save(selector);
    }
    aggregationDefinition.setAggregationStatisticDataSelectors(
        handler.getAggregationStatisticDataSelectors());

    // AggregationTables
    for (final AggregationTable aggregationTable : handler.getAggregationTables()) {
      dao.save(aggregationTable);
    }
    aggregationDefinition.setAggregationTables(handler.getAggregationTables());

    // Get databaseTableVos for all Aggregation-Tables
    // defined in Aggregation Definition
    final Collection<DatabaseTableVo> databaseTableVos =
        generateAggregationDatabaseTableVos(aggregationDefinition);
    if (databaseTableVos != null) {
      for (final DatabaseTableVo databaseTableVo : databaseTableVos) {
        // create aggregation table in Database
        dbAccessor.createTable(databaseTableVo);
      }
    }

    return renderer.render(aggregationDefinition);
  }
  /**
   * Generates DatabaseTableVos for DirectDatabaseAccessor to create Aggregation-Tables as defined
   * in aggregation-definition.
   *
   * @param aggregationDefinition aggregationDefinition binding object.
   * @return Collection Returns Collection with DatabaseTableVo.
   * @throws SqlDatabaseSystemException e
   */
  private Collection<DatabaseTableVo> generateAggregationDatabaseTableVos(
      final AggregationDefinition aggregationDefinition) throws SqlDatabaseSystemException {
    final Collection<DatabaseTableVo> databaseTableVos = new ArrayList<DatabaseTableVo>();
    for (final AggregationTable aggregationTable : aggregationDefinition.getAggregationTables()) {
      final DatabaseTableVo databaseTableVo = new DatabaseTableVo();
      databaseTableVo.setTableName(aggregationTable.getName().toLowerCase(Locale.ENGLISH));

      // Generate Fields
      final Collection<DatabaseTableFieldVo> databaseFieldVos =
          new ArrayList<DatabaseTableFieldVo>();
      // sort AggregationTableFields
      final Collection<AggregationTableField> sortedAggregationTableFields =
          new TreeSet<AggregationTableField>(new AggregationTableFieldComparator());
      sortedAggregationTableFields.addAll(aggregationTable.getAggregationTableFields());

      for (final AggregationTableField field : sortedAggregationTableFields) {
        final DatabaseTableFieldVo databaseTableFieldVo = new DatabaseTableFieldVo();
        if (field.getFieldTypeId() == Constants.COUNT_CUMULATION_FIELD_ID
            || field.getFieldTypeId() == Constants.DIFFERENCE_CUMULATION_FIELD_ID
            || field.getFieldTypeId() == Constants.TIME_REDUCTION_FIELD_ID) {
          dbAccessor.checkReservedExpressions(field.getName());
          databaseTableFieldVo.setFieldName(field.getName().toLowerCase(Locale.ENGLISH));
          databaseTableFieldVo.setFieldType(Constants.DATABASE_FIELD_TYPE_NUMERIC);
        } else if (field.getFieldTypeId() == Constants.INFO_FIELD_ID) {
          dbAccessor.checkReservedExpressions(field.getName());
          databaseTableFieldVo.setFieldName(field.getName().toLowerCase(Locale.ENGLISH));
          databaseTableFieldVo.setFieldType(field.getDataType());
        } else {
          throw new SqlDatabaseSystemException(
              "Table-Fields may not be empty in aggregation definition");
        }
        databaseFieldVos.add(databaseTableFieldVo);
      }
      databaseTableVo.setDatabaseFieldVos(databaseFieldVos);

      // Generate Indexes
      if (aggregationTable.getAggregationTableIndexes() != null
          && !aggregationTable.getAggregationTableIndexes().isEmpty()) {
        final Collection<DatabaseIndexVo> databaseIndexVos = new ArrayList<DatabaseIndexVo>();
        for (final AggregationTableIndexe index : aggregationTable.getAggregationTableIndexes()) {
          final DatabaseIndexVo databaseIndexVo = new DatabaseIndexVo();
          databaseIndexVo.setIndexName(index.getName().toLowerCase(Locale.ENGLISH));
          final Collection<String> indexFields = new ArrayList<String>();
          if (index.getAggregationTableIndexFields() != null) {
            // sort AggregationTableIndexFields
            final Collection<AggregationTableIndexField> sortedAggregationTableIndexFields =
                new TreeSet<AggregationTableIndexField>(new AggregationTableIndexFieldComparator());
            sortedAggregationTableIndexFields.addAll(index.getAggregationTableIndexFields());
            for (final AggregationTableIndexField indexField : sortedAggregationTableIndexFields) {
              indexFields.add(indexField.getField());
            }
          }
          databaseIndexVo.setFields(indexFields);
          databaseIndexVos.add(databaseIndexVo);
        }
        databaseTableVo.setDatabaseIndexVos(databaseIndexVos);
      }
      databaseTableVos.add(databaseTableVo);
    }
    return databaseTableVos;
  }