Implied Entity Attributes

There may be occassions where an entity attribute is implied or inferred by the location of a MAPPER report. This is more likely when the data set for a single entity is spread among several MAPPER reports. For example, in an inventory system, storage might be arranged so all items in reports 20 to 30 of drawer B are back ordered. Reports may also exist where the data lines represent the same domain entity but are differentiated by line type; in such cases, the line type could imply a "discriminator" entity attribute.

MJ treats implied attributes as enumerations, which are stored as variable-length character strings. It is up to the migration analyst or developer to name the attribute and identify the valid, enumerated values for the attribute. Using this information, MJ generates a database column, an associated property in the Hibernate entity and a corresponding Java enum.

By default, MJ supports inferring an entity attribute from a report number, range of report numbers or line type.

ReportNumberEnumMapping Bean

The bean class ReportNumberEnumMapping maps report numbers to enumeration constants and their corresponding representation as strings. Important bean properties are:

enumClassName Full name of enumeration class, including package. For example, com.acme.myapp.entity.OrderStatusEnum.
enumsFromProperties Defines enumerated constants and associated keys from a properties object.
defineEnum Define an enumerated constant and specify it's associated key.

An implied entity attribute is most easily defined as properties via the enumsFromProperties method and the extended name/value syntax supported by this method:

    key=symbol->value

For ReportNumberEnumMapping, key is a report number, symbol is an enumerated constant name and value is the enumerated constant value. Here is an example:

    22=ACCEPTED -> ACC

The key, symbol and value are:

key
22
The MAPPER report number.
symbol
ACCEPTED
The name of the enumerated constant (this is different from the name of the class derived from java.lang.enum, which is specified by enumClassName).
value
ACC
The value of the enumerated constant; this string is stored in the database column created for the implied entity attribute.

To flesh out this example, assume the value of an implied "orderStatus" entity attribute is either ACCEPTED, in FULFILLMENT, SHIPPED or RETURNed and is determined by report number. The ReportNumberEnumMapping bean for "orderStatus" is configured with Spring XML as follows:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/util
                           http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<!-- ===== setup report number enumeration mapping ===== -->
<bean id="enumStatusFromRptNum"
      class="com.arsi.mj.maprpt.enums.ReportNumberEnumMapping"
      p:enumClassName="com.acme.myapp.entity.OrderStatusEnum">

  <property name="enumsFromProperties">
    <value>
    22=ACCEPTED -> ACC
    44=FULFILLMENT -> FFL
    66=SHIPPED -> SHP
    88=RETURN -> RMA
    </value>
  </property>
</bean>

</beans>

The implied "orderStatus" entity attribute is defined with ColumnDef, specifying the database column ORD_STAT stores the attribute. The ColumnDef bean is used instead of AnnotatedColumnDef since the source of the data entity attribute isn't a MAPPER data field defined in the report's header line:

<bean id="orderEntityHandler.coldefStatusFromRptNum"
      class="com.arsi.mj.config.atoms.ColumnDef">
  <!-- entity attrname, column name, length, NULLABLE, data type -->
  <constructor-arg index="0" value="orderStatus"/>
  <constructor-arg index="1" value="ORD_STAT"/>
  <constructor-arg index="2" value="3"/>
  <constructor-arg index="3" value="false"/>
  <constructor-arg index="4">
    <util:constant static-field="org.hibernate.type.StandardBasicTypes.STRING"/>
  </constructor-arg>
</bean>

The ReportNumberEnumMapping and ColumnDef collaborating beans are referenced by DataEntityHandler bean:

<bean id="orderEntityHandler"
      class="com.arsi.mj.maprpt.entity.handler.DataEntityHandler"
      . . .
      p:column1-ref="orderEntityHandler.coldefStatusFromRptNum"
      p:enumForColumn1-ref="enumStatusFromRptNum"
      . . .
</bean>

MJ generates the OrderStatusEnum enumeration:

package com.acme.myapp.entity;

/** Enumeration of <code>OrderStatus</code>. */
public enum OrderStatusEnum {
  ACCEPTED("ACC"),
  FULFILLMENT("FFL"),
  SHIPPED("SHP"),
  RETURN("RMA");

  /** String value associated with each enumeration constant. */
  private String value;

  /** Restricted ctor for creating an instance of this class. */
  private OrderStatusEnum(String aValue) {
    this.value = aValue;
  }

  /**
   * Get canonical name of the enumeration constant, which is the associated string value.
   *
   * @return
   *  canonical name, i.e., associated string value (e.g., if Java enum constant is
   *  <code>AVERAGE</code>, canonical name might be "AVG").
   */
  public String asName() { return this.value; }

  /**
   * Given canonical name (associated string value) of an enumeration constant,
   * return the Java enumeration constant.
   *
   * @param aValue
   *   associated string value (canonical name, e.g., "AVG").
   * @return
   *   enumeration constant associated with string value (e.g., <code>AVERAGE</code>).
   * @throws IllegalArgumentException
   *   if <code>aValue</code> is not associated with any enumeration constant.
   */
  public static OrderStatusEnum asValueOf(String aValue) {
    if (ACCEPTED.asName().equals(aValue))
      return ACCEPTED;
    else if (FULFILLMENT.asName().equals(aValue))
      return FULFILLMENT;
    else if (SHIPPED.asName().equals(aValue))
      return SHIPPED;
    else if (RETURN.asName().equals(aValue))
      return RETURN;
    else
      throw new IllegalArgumentException("invalid enumeration value: " + aValue);
  }
}

ReportRangeEnumMapping Bean

The bean class ReportRangeEnumMapping maps ranges of report numbers to enumeration constants and their corresponding representation as character strings. Important bean properties are:

enumClassName Full name of enumeration class, including package. For example, com.acme.myapp.entity.OrderStatusEnum.
enumsFromProperties Defines enumerated constants and associated keys from a properties object.
defineEnum Define an enumerated constant and specify it's associated key.

The enumsFromProperties method supports an extended name/value syntax which allows an implied entity attribute to be defined as properties:

    key=symbol->value

In the case of ReportRangeEnumMapping, key is a range of report numbers, symbol is an enumerated constant name and value is the enumerated constant value. For example:

    22-23=ACCEPTED -> ACC

The key, symbol and value are:

key
22-23
Range of MAPPER report numbers.
symbol
ACCEPTED
The name of the enumerated constant.
value
ACC
The value of the enumerated constant (stored in the database).

Altering the implied "orderStatus" entity attribute example above, assume the value (ACCEPTED, in FULFILLMENT, SHIPPED or RETURNed) of "orderStatus" is determined by report number. The ReportRangeEnumMapping for this implied attribute is configured with Spring XML as follows:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/util
                           http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<!-- ===== setup report range enumeration mapping ===== -->
<bean id="enumMapper"
      class="com.arsi.mj.maprpt.enums.ReportRangeEnumMapping"
      p:enumClassName="com.acme.myapp.entity.OrderStatusEnum">

  <property name="enumsFromProperties">
    <value>
    22-23=ACCEPTED -> ACC
    44-45=FULFILLMENT -> FFL
    66-67=SHIPPED -> SHP
    88-89=RETURN -> RMA
    </value>
  </property>
</bean>

</beans>

In addition, the implied "orderStatus" entity attribute must be defined as a ColumnDef bean, and the ReportRangeEnumMapping and ColumnDef referenced by the DataEntityHandler bean. See ReportNumberEnumMapping for examples of these.

LineTypeEnumMapping Bean

Bean class LineTypeEnumMapping maps line types to enumeration constants and their corresponding representation as character strings. Important bean properties are similar to the those of the enumeration mapping beans described above:

enumClassName Full name of enumeration class, including package. For example, com.acme.myapp.entity.OrderStatusEnum.
enumsFromProperties Defines enumerated constants and associated keys from a properties object.
defineEnum Define an enumerated constant and specify it's associated key.

The enumsFromProperties method and the extended name/value syntax supported by this method allow an implied entity attribute to be defined as properties:

    key=symbol->value

For LineTypeEnumMapping, key is a literal line type character, symbol is an enumerated constant name and value is the enumerated constant value. Here is an example:

    \\t=ACCEPTED -> ACC

The key, symbol and value are:

key
\\t
Tab line type character using Java literal notation (\t). Note the backslash is doubled as the standard escape for properties.
symbol
ACCEPTED
The name of the enumerated constant.
value
ACC
The value of the enumerated constant (stored in the database).

Using the implied "orderStatus" entity attribute example again, assume the order status (ACCEPTED, in FULFILLMENT, SHIPPED or RETURNed) is represented by the line type character of each data line. Via Spring XML, the LineTypeEnumMapping bean is configured as follows:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                           http://www.springframework.org/schema/util
                           http://www.springframework.org/schema/util/spring-util-3.0.xsd">
<!-- ===== setup line type enumeration mapping ===== -->
<bean id="enumMapper"
      class="com.arsi.mj.maprpt.enums.LineTypeEnumMapping"
      p:enumClassName="com.acme.myapp.entity.OrderStatusEnum">

  <property name="enumsFromProperties">
    <value>
    \\t=ACCEPTED -> ACC
    +=FULFILLMENT -> FFL
    0=SHIPPED -> SHP
    9=RETURN -> RMA
    </value>
  </property>
</bean>

</beans>

As with the other enumeration mapping bean example above, the implied "orderStatus" entity attribute must defined as a ColumnDef bean, and the LineTypeEnumMapping and ColumnDef referenced by the DataEntityHandler bean. See ReportNumberEnumMapping for examples of these.