Documentation for a newer release is available. View Latest

Definir las relaciones de mapeo

Esta sección cubre la forma de definir un mapeo de origen a destino. Estas se definen en archivos de configuración HOCON (.conf).

.conf vs .mconf

Estas definiciones también pueden definirse como archivos con el formato .mconf.

La estructura del archivo mconf tiene soporte de lenguaje integrado a través del IPF Idea Plugin, que proporciona restricciones específicas del dominio y características más allá del soporte ofrecido por plugins Hocon de terceros; elegimos una extensión específica para no solaparnos con el soporte existente del lenguaje HOCON.

Características incluyen:

  • Autocompletado y validación de rutas de campos

  • Validación condicional de claves

  • Comprobación de claves duplicadas

Y mucho más.

La estructura del archivo y la sintaxis son actualmente exactamente iguales entre los dos formatos salvo por un detalle.

La sintaxis de acceso a arrays en rutas de campos en hocon es de la forma a.b.0.c mientras que la sintaxis equivalente en mconf sería a.b[0].c

La herramienta de generación de código espera uno o más archivos de configuración HOCON presentes en una carpeta definida por el usuario. Aparte de la extensión .conf o .mconf, no hay requisitos sobre el nombre. Sin embargo, cada archivo configurará un mapeo o un enriquecimiento.

En segundo plano, los archivos mconf se traducen a archivos conf antes de ser procesados por la herramienta de generación de código.

Mapeo a objetos destino mutables

Las configuraciones de mapeo y enriquecimiento siguientes aplican al mapeo de objetos destino mutables

Configuración de mapeo

Cada par de clases a mapear se definirá mediante un archivo de configuración que contenga la clave mappings. El mapeo bidireccional también puede admitirse añadiendo la propiedad bidirectional-mapping: true al archivo de configuración de mapeo.

Una configuración básica de mapeo tendrá este aspecto:

AtoB-mapping.conf
source-class:      com.ipf.example.model.TestA  # class to read
destination-class: com.ipf.example.model.TestB  # class to produce
target-package:    com.ipf.example.mapping      # package to generate
target-class-name: TestAToTestBCustomiser       # name of the mapper class to generate
mappings: [
  { source: foo, destination: bar }             # just map this pair
  # { source: moreFoo, destination: moreBar }   # ...any other pairs would go here
]

A veces queremos mapear una clase a una versión más reciente de la misma, donde la gran mayoría de atributos coinciden. Quizá un array de elementos, de los cuales sólo nos interesa el primero, se ha convertido en un escalar, o viceversa. Con más frecuencia, se habrá eliminado un atributo.

En estos casos, podemos ser concisos y usar mapeos implícitos (implicit-mapping: true), y sólo especificar las excepciones, p. ej., para excluir un atributo eliminado:

CtoCv2-mapping.conf
source-class:      com.ipf.example.model.v1.TestC
destination-class: com.ipf.example.model.v2.TestCv2
target-package:    com.ipf.example.mapping
target-class-name: TestCToTestCv2Customiser
implicit-mapping:  true                               # match attributes by name
bidirectional-mapping: true
mappings: [
  { source: foo2, excluded: true }                         # exclude an attribute from mapping
  { source: apples.0, destination: apple }                 # map first apple in array of apples
  { source: bananas.0, destination: banana }               # map first banana in array of bananas
  { source: farmer, destination: farmers.0 }               # it also works the other way around
]

Como se dijo anteriormente, esta configuración generará mapeadores TestC → TestCv2 y TestCv2 → TestC porque el mapeo bidireccional está habilitado. El objeto apple en TestCv2 se mapeará a un array de un solo elemento con el objeto apple mapeado.

Configuración de enriquecimiento

A menudo, el mensaje que se enviará al sistema destino necesita ser enriquecido con valores fijos provenientes de la configuración, el reloj del sistema o simplemente valores codificados.

El framework admite esto leyendo la configuración de enriquecimiento de un archivo como el siguiente:

TestA-enrichment.conf
enrichment-target: com.ipf.example.model.TestA  # what class to enrich
target-package: com.ipf.example.mapping
enrichments: [
   {destination: version, enrichment-type: value , value: 100L}
   {destination: id, enrichment-type: randomAlphaNumeric}
   {destination: special, enrichment-type: config-value, path: "get.me"}
   {destination: date, enrichment-type: from-instant, format: "dd/MM/yyyy"}
]

El enriquecimiento se basa en un enrichment context, proporcionado por el framework, que admite cuatro tipos de orígenes de enriquecimiento:

type description example

value

valor constante, en la propiedad value

value: "some literal value"

randomAlphaNumeric

genera una cadena alfanumérica con una longitud dada

length: 10

config-value

lee del archivo de configuración de la aplicación, en la ruta indicada por path

path: "get.me"

from-instant

formatea el instante actual como cadena con el patrón dado

format: "dd/MM/yyyy"

Mapeo a objetos destino inmutables

Cuando el objeto destino es inmutable, el mapeo requiere el uso de un builder. En este caso, además de los tipos de origen y destino, hay que indicar el tipo del builder del destino.

Configuración de mapeo

La configuración es similar, pero el uso del servicio de transformación incluirá el builder del destino.

Configuración de enriquecimiento

Análoga a la anterior: cuando el destino es inmutable y se aplica enriquecimiento, también se debe proporcionar el tipo de builder.

Las secciones de ejemplo de código Java y HOCON incluidas aquí se mantienen en inglés para preservar la precisión técnica.