001// *************************************************************************************************************************** 002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file * 003// * distributed with this work for additional information regarding copyright ownership. The ASF licenses this file * 004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance * 005// * with the License. You may obtain a copy of the License at * 006// * * 007// * http://www.apache.org/licenses/LICENSE-2.0 * 008// * * 009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an * 010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 011// * specific language governing permissions and limitations under the License. * 012// *************************************************************************************************************************** 013package org.apache.juneau.plaintext; 014 015import java.util.*; 016import java.util.concurrent.*; 017 018import org.apache.juneau.*; 019import org.apache.juneau.annotation.*; 020import org.apache.juneau.serializer.*; 021import org.apache.juneau.transform.*; 022 023/** 024 * Serializes POJOs to plain text using just the <c>toString()</c> method on the serialized object. 025 * 026 * <h5 class='topic'>Media types</h5> 027 * 028 * Handles <c>Accept</c> types: <bc>text/plain</bc> 029 * <p> 030 * Produces <c>Content-Type</c> types: <bc>text/plain</bc> 031 * 032 * <h5 class='topic'>Description</h5> 033 * 034 * Essentially converts POJOs to plain text using the <c>toString()</c> method. 035 * 036 * <p> 037 * Also serializes objects using a transform if the object class has an {@link PojoSwap PojoSwap<?,String>} 038 * transform defined on it. 039 */ 040@ConfigurableContext 041public class PlainTextSerializer extends WriterSerializer implements PlainTextMetaProvider, PlainTextCommon { 042 043 //------------------------------------------------------------------------------------------------------------------- 044 // Configurable properties 045 //------------------------------------------------------------------------------------------------------------------- 046 047 static final String PREFIX = "PlainTextSerializer"; 048 049 //------------------------------------------------------------------------------------------------------------------- 050 // Predefined instances 051 //------------------------------------------------------------------------------------------------------------------- 052 053 /** Default serializer, all default settings.*/ 054 public static final PlainTextSerializer DEFAULT = new PlainTextSerializer(PropertyStore.DEFAULT); 055 056 057 //------------------------------------------------------------------------------------------------------------------- 058 // Instance 059 //------------------------------------------------------------------------------------------------------------------- 060 061 private final Map<ClassMeta<?>,PlainTextClassMeta> plainTextClassMetas = new ConcurrentHashMap<>(); 062 private final Map<BeanPropertyMeta,PlainTextBeanPropertyMeta> plainTextBeanPropertyMetas = new ConcurrentHashMap<>(); 063 064 /** 065 * Constructor. 066 * 067 * @param ps 068 * The property store containing all the settings for this object. 069 */ 070 public PlainTextSerializer(PropertyStore ps) { 071 this(ps, "text/plain", (String)null); 072 } 073 074 /** 075 * Constructor. 076 * 077 * @param ps 078 * The property store containing all the settings for this object. 079 * @param produces 080 * The media type that this serializer produces. 081 * @param accept 082 * The accept media types that the serializer can handle. 083 * <p> 084 * Can contain meta-characters per the <c>media-type</c> specification of {@doc RFC2616.section14.1} 085 * <p> 086 * If empty, then assumes the only media type supported is <c>produces</c>. 087 * <p> 088 * For example, if this serializer produces <js>"application/json"</js> but should handle media types of 089 * <js>"application/json"</js> and <js>"text/json"</js>, then the arguments should be: 090 * <p class='bcode w800'> 091 * <jk>super</jk>(ps, <js>"application/json"</js>, <js>"application/json,text/json"</js>); 092 * </p> 093 * <br>...or... 094 * <p class='bcode w800'> 095 * <jk>super</jk>(ps, <js>"application/json"</js>, <js>"*​/json"</js>); 096 * </p> 097 * <p> 098 * The accept value can also contain q-values. 099 */ 100 public PlainTextSerializer(PropertyStore ps, String produces, String accept) { 101 super(ps, produces, accept); 102 } 103 104 105 @Override /* Context */ 106 public PlainTextSerializerBuilder builder() { 107 return new PlainTextSerializerBuilder(getPropertyStore()); 108 } 109 110 /** 111 * Instantiates a new clean-slate {@link PlainTextSerializerBuilder} object. 112 * 113 * <p> 114 * This is equivalent to simply calling <code><jk>new</jk> PlainTextSerializerBuilder()</code>. 115 * 116 * <p> 117 * Note that this method creates a builder initialized to all default settings, whereas {@link #builder()} copies 118 * the settings of the object called on. 119 * 120 * @return A new {@link PlainTextSerializerBuilder} object. 121 */ 122 public static PlainTextSerializerBuilder create() { 123 return new PlainTextSerializerBuilder(); 124 } 125 126 @Override /* Context */ 127 public PlainTextSerializerSession createSession() { 128 return createSession(createDefaultSessionArgs()); 129 } 130 131 @Override /* Serializer */ 132 public PlainTextSerializerSession createSession(SerializerSessionArgs args) { 133 return new PlainTextSerializerSession(this, args); 134 } 135 136 //----------------------------------------------------------------------------------------------------------------- 137 // Extended metadata 138 //----------------------------------------------------------------------------------------------------------------- 139 140 @Override /* PlainTextMetaProvider */ 141 public PlainTextClassMeta getPlainTextClassMeta(ClassMeta<?> cm) { 142 PlainTextClassMeta m = plainTextClassMetas.get(cm); 143 if (m == null) { 144 m = new PlainTextClassMeta(cm, this); 145 plainTextClassMetas.put(cm, m); 146 } 147 return m; 148 } 149 150 @Override /* PlainTextMetaProvider */ 151 public PlainTextBeanPropertyMeta getPlainTextBeanPropertyMeta(BeanPropertyMeta bpm) { 152 if (bpm == null) 153 return PlainTextBeanPropertyMeta.DEFAULT; 154 PlainTextBeanPropertyMeta m = plainTextBeanPropertyMetas.get(bpm); 155 if (m == null) { 156 m = new PlainTextBeanPropertyMeta(bpm.getDelegateFor(), this); 157 plainTextBeanPropertyMetas.put(bpm, m); 158 } 159 return m; 160 } 161 162 //----------------------------------------------------------------------------------------------------------------- 163 // Other methods 164 //----------------------------------------------------------------------------------------------------------------- 165 166 @Override /* Context */ 167 public ObjectMap toMap() { 168 return super.toMap() 169 .append("PlainTextSerializer", new DefaultFilteringObjectMap() 170 ); 171 } 172}