|
|
@@ -11,7 +11,7 @@ import {isArray} from "lodash";
|
|
|
class HydraNormalizer {
|
|
|
|
|
|
/**
|
|
|
- * Normalize the given entity into an Hydra formatted content.
|
|
|
+ * Normalize the given entity into a Hydra formatted content.
|
|
|
* @param entity
|
|
|
*/
|
|
|
public static normalizeEntity(entity: ApiResource): AnyJson {
|
|
|
@@ -49,56 +49,13 @@ class HydraNormalizer {
|
|
|
|
|
|
protected static getData(hydraData: AnyJson, model?: typeof ApiResource): AnyJson {
|
|
|
if (hydraData['@type'] === 'hydra:Collection') {
|
|
|
- let members = hydraData['hydra:member']
|
|
|
- let results = []
|
|
|
-
|
|
|
- for (let item of members) {
|
|
|
- results.push(HydraNormalizer.denormalizeItem(item, model))
|
|
|
- }
|
|
|
-
|
|
|
- return results
|
|
|
+ const members = hydraData['hydra:member']
|
|
|
+ return members.map((item: AnyJson) => HydraNormalizer.denormalizeItem(item, model))
|
|
|
} else {
|
|
|
return HydraNormalizer.denormalizeItem(hydraData, model)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Dénormalise un item d'une réponse hydra
|
|
|
- *
|
|
|
- * @param item
|
|
|
- * @param model
|
|
|
- * @protected
|
|
|
- */
|
|
|
- protected static denormalizeItem(item: AnyJson, model?: typeof ApiResource): AnyJson {
|
|
|
-
|
|
|
- if (!model) {
|
|
|
- const {entity, id} = HydraNormalizer.parseIRI(item['@id'])
|
|
|
- if (!id) {
|
|
|
- throw Error('De-normalization error : Could not determine the model of the entity')
|
|
|
- }
|
|
|
- model = models[entity]
|
|
|
- }
|
|
|
-
|
|
|
- const instance = new model(item)
|
|
|
-
|
|
|
- const iriEncodedFields = HydraNormalizer.getIriEncodedFields(instance)
|
|
|
-
|
|
|
- for (const field in iriEncodedFields) {
|
|
|
- const value = instance[field]
|
|
|
- const targetEntity = iriEncodedFields[field].entity
|
|
|
-
|
|
|
- if (isArray(value)) {
|
|
|
- instance[field] = value.map((iri: string) => {
|
|
|
- return HydraNormalizer.getIdFromIri(iri, targetEntity)
|
|
|
- })
|
|
|
- } else {
|
|
|
- instance[field] = HydraNormalizer.getIdFromIri(value, targetEntity)
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return instance
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* Génère les métadonnées d'un item ou d'une collection
|
|
|
*
|
|
|
@@ -143,16 +100,84 @@ class HydraNormalizer {
|
|
|
return metadata
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Dénormalise un item d'une réponse hydra
|
|
|
+ *
|
|
|
+ * @param item
|
|
|
+ * @param model
|
|
|
+ * @protected
|
|
|
+ */
|
|
|
+ protected static denormalizeItem(item: AnyJson, model?: typeof ApiResource): AnyJson {
|
|
|
+
|
|
|
+ if (model) {
|
|
|
+ return HydraNormalizer.denormalizeEntity(model, item)
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!item.hasOwnProperty('@id')) {
|
|
|
+ // Not hydra formatted
|
|
|
+ console.error('De-normalization error : the item is not hydra formatted', item)
|
|
|
+ return item
|
|
|
+ }
|
|
|
+
|
|
|
+ if (item['@id'].match(/\/api\/enum\/\w+/)) {
|
|
|
+ return HydraNormalizer.denormalizeEnum(item)
|
|
|
+ }
|
|
|
+
|
|
|
+ let entity = null
|
|
|
+
|
|
|
+ // On essaie de déterminer la nature de l'objet à partir de son id
|
|
|
+ try {
|
|
|
+ const iri = HydraNormalizer.parseEntityIRI(item['@id'])
|
|
|
+ entity = iri.entity
|
|
|
+ } catch (e) {
|
|
|
+ console.error('De-normalization error : could not parse the IRI', item)
|
|
|
+ return item
|
|
|
+ }
|
|
|
+
|
|
|
+ if (entity && models.hasOwnProperty(entity)) {
|
|
|
+ model = models[entity]
|
|
|
+ return HydraNormalizer.denormalizeEntity(model, item)
|
|
|
+ }
|
|
|
+
|
|
|
+ throw Error('De-normalization error : Could not determine the type of the entity '
|
|
|
+ + item['@id'] + ' (found: ' + entity + ')')
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static denormalizeEntity(model: typeof ApiResource, item: AnyJson) {
|
|
|
+ const instance = new model(item)
|
|
|
+
|
|
|
+ const iriEncodedFields = HydraNormalizer.getIriEncodedFields(instance)
|
|
|
+
|
|
|
+ for (const field in iriEncodedFields) {
|
|
|
+ const value = instance[field]
|
|
|
+ const targetEntity = iriEncodedFields[field].entity
|
|
|
+
|
|
|
+ if (isArray(value)) {
|
|
|
+ instance[field] = value.map((iri: string) => {
|
|
|
+ return HydraNormalizer.getIdFromEntityIri(iri, targetEntity)
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ instance[field] = HydraNormalizer.getIdFromEntityIri(value, targetEntity)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return instance
|
|
|
+ }
|
|
|
+
|
|
|
+ protected static denormalizeEnum(item: AnyJson): AnyJson {
|
|
|
+ return item
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Parse the given IRI
|
|
|
* @param iri
|
|
|
* @protected
|
|
|
*/
|
|
|
- protected static parseIRI(iri: string) {
|
|
|
+ protected static parseEntityIRI(iri: string) {
|
|
|
const rx = /\/api\/(\w+)\/(\d+)/
|
|
|
const match = rx.exec(iri)
|
|
|
if (!match) {
|
|
|
- throw Error('could not parse the IRI : ' + iri)
|
|
|
+ throw Error('could not parse the IRI : ' + JSON.stringify(iri))
|
|
|
}
|
|
|
|
|
|
return {
|
|
|
@@ -181,8 +206,8 @@ class HydraNormalizer {
|
|
|
* @param expectedEntity
|
|
|
* @protected
|
|
|
*/
|
|
|
- protected static getIdFromIri(iri: string, expectedEntity: string): number {
|
|
|
- const { entity, id } = HydraNormalizer.parseIRI(iri)
|
|
|
+ protected static getIdFromEntityIri(iri: string, expectedEntity: string): number | string {
|
|
|
+ const { entity, id } = HydraNormalizer.parseEntityIRI(iri)
|
|
|
if (entity !== expectedEntity) {
|
|
|
throw Error("IRI entity does not match the field's target entity (" + entity + ' != ' + expectedEntity + ")")
|
|
|
}
|