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