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.types; 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.apache.commons.lang.StringUtils; 026import org.codehaus.jackson.JsonGenerator; 027import org.nuxeo.ecm.core.io.marshallers.json.ExtensibleEntityJsonWriter; 028import org.nuxeo.ecm.core.io.marshallers.json.enrichers.AbstractJsonEnricher; 029import org.nuxeo.ecm.core.io.registry.reflect.Setup; 030import org.nuxeo.ecm.core.schema.types.ComplexType; 031import org.nuxeo.ecm.core.schema.types.Field; 032import org.nuxeo.ecm.core.schema.types.ListType; 033import org.nuxeo.ecm.core.schema.types.PrimitiveType; 034import org.nuxeo.ecm.core.schema.types.Schema; 035import org.nuxeo.ecm.core.schema.types.Type; 036 037import com.thoughtworks.xstream.io.json.JsonWriter; 038 039/** 040 * Convert {@link Schema} to Json. 041 * <p> 042 * This marshaller is enrichable: register class implementing {@link AbstractJsonEnricher} and managing {@link Schema}. 043 * </p> 044 * <p> 045 * This marshaller is also extensible: extend it and simply override 046 * {@link ExtensibleEntityJsonWriter#extend(Schema, JsonWriter)}. 047 * </p> 048 * <p> 049 * Format is: 050 * 051 * <pre> 052 * {@code 053 * { 054 * "entity-type":"schema", 055 * "name": "SCHEMA_NAME", 056 * "prefix: "SCHEMA_PREFIX", <- only if there's a prefix 057 * "fields", { 058 * "PRIMITIVE_FIELD_LOCAL_NAME": "FIELD_TYPE", <- where field type is {@link Type#getName()} (string, boolean, integer, ...) 059 * "PRIMITIVE_LIST_LOCAL_NAME": "FIELD_TYPE[]" <- where field type is {@link Type#getName()} (string, boolean, integer, ...) 060 * "COMPLEX_FIELD_LOCAL_NAME" : { 061 * "type": "complex", 062 * "fields": { 063 * loop the same format 064 * } 065 * }, 066 * "COMPLEX_LIST_FIELD_LOCAL_NAME" : { 067 * "type": "complex[]", 068 * "fields": { 069 * loop the same format 070 * } 071 * }, 072 * "CONTENT_FIELD": "blob", 073 * "CONTENT_LIST_FIELD": "blob[]", 074 * ... 075 * } 076 * <-- contextParameters if there are enrichers activated 077 * <-- additional property provided by extend() method 078 * } 079 * </pre> 080 * 081 * </p> 082 * 083 * @since 7.2 084 */ 085@Setup(mode = SINGLETON, priority = REFERENCE) 086public class SchemaJsonWriter extends ExtensibleEntityJsonWriter<Schema> { 087 088 public static final String ENTITY_TYPE = "schema"; 089 090 public SchemaJsonWriter() { 091 super(ENTITY_TYPE, Schema.class); 092 } 093 094 @Override 095 protected void writeEntityBody(Schema schema, JsonGenerator jg) throws IOException { 096 jg.writeStringField("name", schema.getName()); 097 String prefix = schema.getNamespace().prefix; 098 if (StringUtils.isNotBlank(prefix)) { 099 jg.writeStringField("prefix", prefix); 100 } 101 jg.writeObjectFieldStart("fields"); 102 for (Field field : schema.getFields()) { 103 writeField(jg, field); 104 } 105 jg.writeEndObject(); 106 } 107 108 protected void writeField(JsonGenerator jg, Field field) throws IOException { 109 if (!field.getType().isComplexType()) { 110 if (field.getType().isListType()) { 111 ListType lt = (ListType) field.getType(); 112 if (lt.getFieldType().isComplexType()) { 113 if (lt.getFieldType().getName().equals("content")) { 114 jg.writeStringField(field.getName().getLocalName(), "blob[]"); 115 } else { 116 jg.writeObjectFieldStart(field.getName().getLocalName()); 117 jg.writeStringField("type", "complex[]"); 118 jg.writeObjectFieldStart("fields"); 119 ComplexType cplXType = (ComplexType) lt.getField().getType(); 120 for (Field subField : cplXType.getFields()) { 121 writeField(jg, subField); 122 } 123 jg.writeEndObject(); 124 jg.writeEndObject(); 125 } 126 } else { 127 Type type = lt.getFieldType(); 128 while (!(type instanceof PrimitiveType)) { 129 type = type.getSuperType(); 130 } 131 jg.writeStringField(field.getName().getLocalName(), type.getName() + "[]"); 132 } 133 } else { 134 Type type = field.getType(); 135 while (!(type instanceof PrimitiveType)) { 136 type = type.getSuperType(); 137 } 138 jg.writeStringField(field.getName().getLocalName(), type.getName()); 139 } 140 } else { 141 if (field.getType().getName().equals("content")) { 142 jg.writeStringField(field.getName().getLocalName(), "blob"); 143 } else { 144 jg.writeObjectFieldStart(field.getName().getLocalName()); 145 ComplexType cplXType = (ComplexType) field.getType(); 146 jg.writeObjectFieldStart("fields"); 147 for (Field subField : cplXType.getFields()) { 148 writeField(jg, subField); 149 } 150 jg.writeEndObject(); 151 jg.writeStringField("type", "complex"); 152 jg.writeEndObject(); 153 } 154 } 155 } 156 157}