001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl-2.1.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * Nicolas Chapurlat <nchapurlat@nuxeo.com> 016 */ 017 018package org.nuxeo.ecm.core.io.marshallers.json.validation; 019 020import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; 021import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; 022 023import java.io.IOException; 024 025import org.codehaus.jackson.JsonGenerator; 026import org.nuxeo.ecm.core.api.validation.ConstraintViolation; 027import org.nuxeo.ecm.core.api.validation.ConstraintViolation.PathNode; 028import org.nuxeo.ecm.core.api.validation.DocumentValidationReport; 029import org.nuxeo.ecm.core.io.marshallers.json.ExtensibleEntityJsonWriter; 030import org.nuxeo.ecm.core.io.marshallers.json.enrichers.AbstractJsonEnricher; 031import org.nuxeo.ecm.core.io.registry.reflect.Setup; 032import org.nuxeo.ecm.core.schema.types.constraints.Constraint; 033 034import com.thoughtworks.xstream.io.json.JsonWriter; 035 036/** 037 * Convert {@link DocumentValidationReport} to Json. 038 * <p> 039 * This marshaller is enrichable: register class implementing {@link AbstractJsonEnricher} and managing 040 * {@link DocumentValidationReport}. 041 * </p> 042 * <p> 043 * This marshaller is also extensible: extend it and simply override 044 * {@link ExtensibleEntityJsonWriter#extend(DocumentValidationReport, JsonWriter)}. 045 * </p> 046 * <p> 047 * Format is: 048 * 049 * <pre> 050 * {@code 051 * { 052 * "entity-type":"validation_report", 053 * "has_error": true|false, 054 * "number": 123, <- number of errors present in this report 055 * "violations": [ 056 * { 057 * "message": "TheErrorMessage", 058 * "invalid_value": null|"THE_INVALID_VALUE_AS_STRING", 059 * "constraint": { 060 * see {@link ConstraintJsonWriter} format 061 * } 062 * }, 063 * ... 064 * ] 065 * <-- contextParameters if there are enrichers activated 066 * <-- additional property provided by extend() method 067 * } 068 * </pre> 069 * 070 * </p> 071 * 072 * @since 7.2 073 */ 074@Setup(mode = SINGLETON, priority = REFERENCE) 075public class DocumentValidationReportJsonWriter extends ExtensibleEntityJsonWriter<DocumentValidationReport> { 076 077 public static final String ENTITY_TYPE = "validation_report"; 078 079 public DocumentValidationReportJsonWriter() { 080 super(ENTITY_TYPE, DocumentValidationReport.class); 081 } 082 083 @Override 084 protected void writeEntityBody(DocumentValidationReport report, JsonGenerator jg) throws IOException { 085 jg.writeBooleanField("has_error", report.hasError()); 086 jg.writeNumberField("number", report.numberOfErrors()); 087 // constraint violations 088 jg.writeArrayFieldStart("violations"); 089 for (ConstraintViolation violation : report.asList()) { 090 jg.writeStartObject(); 091 // violation message 092 String message = violation.getMessage(ctx.getLocale()); 093 jg.writeStringField("message", message); 094 // invalid value 095 Object invalidValue = violation.getInvalidValue(); 096 if (invalidValue == null) { 097 jg.writeNullField("invalid_value"); 098 } else { 099 jg.writeStringField("invalid_value", invalidValue.toString()); 100 } 101 // violated constraint 102 Constraint constraint = violation.getConstraint(); 103 writeEntityField("constraint", constraint, jg); 104 // violation place 105 jg.writeArrayFieldStart("path"); 106 for (PathNode node : violation.getPath()) { 107 jg.writeStartObject(); 108 jg.writeStringField("field_name", node.getField().getName().getPrefixedName()); 109 jg.writeBooleanField("is_list_item", node.isListItem()); 110 if (node.isListItem()) { 111 jg.writeNumberField("index", node.getIndex()); 112 } 113 jg.writeEndObject(); 114 } 115 jg.writeEndArray(); 116 jg.writeEndObject(); 117 } 118 jg.writeEndArray(); 119 } 120 121}