001/* 002 * (C) Copyright 2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nicolas Chapurlat <nchapurlat@nuxeo.com> 018 */ 019 020package org.nuxeo.ecm.core.io.marshallers.json.validation; 021 022import static org.nuxeo.ecm.core.io.registry.reflect.Instantiations.SINGLETON; 023import static org.nuxeo.ecm.core.io.registry.reflect.Priorities.REFERENCE; 024 025import java.io.IOException; 026 027import org.codehaus.jackson.JsonGenerator; 028import org.nuxeo.ecm.core.api.validation.ConstraintViolation; 029import org.nuxeo.ecm.core.api.validation.ConstraintViolation.PathNode; 030import org.nuxeo.ecm.core.api.validation.DocumentValidationReport; 031import org.nuxeo.ecm.core.io.marshallers.json.ExtensibleEntityJsonWriter; 032import org.nuxeo.ecm.core.io.marshallers.json.enrichers.AbstractJsonEnricher; 033import org.nuxeo.ecm.core.io.registry.reflect.Setup; 034import org.nuxeo.ecm.core.schema.types.constraints.Constraint; 035 036import com.thoughtworks.xstream.io.json.JsonWriter; 037 038/** 039 * Convert {@link DocumentValidationReport} to Json. 040 * <p> 041 * This marshaller is enrichable: register class implementing {@link AbstractJsonEnricher} and managing 042 * {@link DocumentValidationReport}. 043 * </p> 044 * <p> 045 * This marshaller is also extensible: extend it and simply override 046 * {@link ExtensibleEntityJsonWriter#extend(DocumentValidationReport, JsonWriter)}. 047 * </p> 048 * <p> 049 * Format is: 050 * 051 * <pre> 052 * {@code 053 * { 054 * "entity-type":"validation_report", 055 * "has_error": true|false, 056 * "number": 123, <- number of errors present in this report 057 * "violations": [ 058 * { 059 * "message": "TheErrorMessage", 060 * "invalid_value": null|"THE_INVALID_VALUE_AS_STRING", 061 * "constraint": { 062 * see {@link ConstraintJsonWriter} format 063 * } 064 * }, 065 * ... 066 * ] 067 * <-- contextParameters if there are enrichers activated 068 * <-- additional property provided by extend() method 069 * } 070 * </pre> 071 * 072 * </p> 073 * 074 * @since 7.2 075 */ 076@Setup(mode = SINGLETON, priority = REFERENCE) 077public class DocumentValidationReportJsonWriter extends ExtensibleEntityJsonWriter<DocumentValidationReport> { 078 079 public static final String ENTITY_TYPE = "validation_report"; 080 081 public DocumentValidationReportJsonWriter() { 082 super(ENTITY_TYPE, DocumentValidationReport.class); 083 } 084 085 @Override 086 protected void writeEntityBody(DocumentValidationReport report, JsonGenerator jg) throws IOException { 087 jg.writeBooleanField("has_error", report.hasError()); 088 jg.writeNumberField("number", report.numberOfErrors()); 089 // constraint violations 090 jg.writeArrayFieldStart("violations"); 091 for (ConstraintViolation violation : report.asList()) { 092 jg.writeStartObject(); 093 // violation message 094 String message = violation.getMessage(ctx.getLocale()); 095 jg.writeStringField("message", message); 096 // invalid value 097 Object invalidValue = violation.getInvalidValue(); 098 if (invalidValue == null) { 099 jg.writeNullField("invalid_value"); 100 } else { 101 jg.writeStringField("invalid_value", invalidValue.toString()); 102 } 103 // violated constraint 104 Constraint constraint = violation.getConstraint(); 105 writeEntityField("constraint", constraint, jg); 106 // violation place 107 jg.writeArrayFieldStart("path"); 108 for (PathNode node : violation.getPath()) { 109 jg.writeStartObject(); 110 jg.writeStringField("field_name", node.getField().getName().getPrefixedName()); 111 jg.writeBooleanField("is_list_item", node.isListItem()); 112 if (node.isListItem()) { 113 jg.writeNumberField("index", node.getIndex()); 114 } 115 jg.writeEndObject(); 116 } 117 jg.writeEndArray(); 118 jg.writeEndObject(); 119 } 120 jg.writeEndArray(); 121 } 122 123}