001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.marshall.ini; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020 021import java.io.*; 022 023import org.apache.juneau.marshall.*; 024import org.apache.juneau.marshall.serializer.*; 025 026/** 027 * Specialized writer for serializing INI format. 028 * 029 * <p> 030 * Extends {@link SerializerWriter} with INI-specific methods for sections, key-value pairs, 031 * comments, and quoted strings. 032 * 033 * <h5 class='section'>Notes:</h5><ul> 034 * <li class='note'>This class is not intended for external use. 035 * </ul> 036 * 037 * <h5 class='section'>See Also:</h5><ul> 038 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Ini">INI Basics</a> 039 * </ul> 040 */ 041@SuppressWarnings({ 042 "resource" // Writer resource managed by calling code 043}) 044public class IniWriter extends SerializerWriter<IniWriter> { 045 046 /** Key-value separator character. */ 047 protected final char kvSeparator; 048 049 /** Whether to add spaces around the separator. */ 050 protected final boolean spacedSeparator; 051 052 /** 053 * Constructor. 054 * 055 * @param out The writer being wrapped. 056 * @param useWhitespace If <jk>true</jk>, use blank lines between sections. 057 * @param maxIndent The maximum indentation level (unused for INI). 058 * @param trimStrings If <jk>true</jk>, trim strings before serialization. 059 * @param kvSeparator The key-value separator ('=' or ':'). 060 * @param spacedSeparator If <jk>true</jk>, add spaces around separator. 061 * @param uriResolver The URI resolver. 062 */ 063 protected IniWriter(Writer out, boolean useWhitespace, int maxIndent, boolean trimStrings, char kvSeparator, boolean spacedSeparator, UriResolver uriResolver) { 064 super(out, useWhitespace, maxIndent, trimStrings, '\'', uriResolver); 065 this.kvSeparator = kvSeparator; 066 this.spacedSeparator = spacedSeparator; 067 } 068 069 /** 070 * Writes a section header with optional preceding blank line. 071 * 072 * @param name The section name or path (e.g. "address" or "employment/company"). 073 * <br>Must not be <jk>null</jk>. 074 * @return This object. 075 */ 076 public IniWriter section(String name) { 077 w('\n'); 078 w('[').w(name).w(']').w('\n'); 079 return this; 080 } 081 082 /** 083 * Writes a comment line. 084 * 085 * @param text The comment text. 086 * <br>Can be <jk>null</jk> (writes an empty comment). 087 * @return This object. 088 */ 089 public IniWriter comment(String text) { 090 w("# "); 091 if (ine(text)) { 092 var lines = text.split("\n"); 093 for (var i = 0; i < lines.length; i++) { 094 if (i > 0) 095 w("\n# "); 096 w(lines[i]); 097 } 098 } 099 w('\n'); 100 return this; 101 } 102 103 /** 104 * Writes a key-value pair. 105 * 106 * @param key The key name. 107 * <br>Must not be <jk>null</jk>. 108 * @param value The value (already formatted as string). 109 * <br>Can be <jk>null</jk> (written as the literal <js>"null"</js>). 110 * @return This object. 111 */ 112 public IniWriter keyValue(String key, String value) { 113 w(key); 114 if (spacedSeparator) 115 w(" ").w(kvSeparator).w(" "); 116 else 117 w(kvSeparator); 118 w(or(value, "null")); 119 w('\n'); 120 return this; 121 } 122 123 /** 124 * Writes a single-quoted string value with escaping. 125 * 126 * <p> 127 * Single quotes within the value are escaped as <c>''</c>. 128 * 129 * @param value The raw string value. 130 * <br>Can be <jk>null</jk> (emitted as the literal <js>"null"</js>). 131 * @return This object. 132 */ 133 public IniWriter quotedString(String value) { 134 if (value == null) { 135 w("null"); 136 return this; 137 } 138 w('\'').w(value.replace("'", "''")).w('\''); 139 return this; 140 } 141 142 /** 143 * Writes a blank line. 144 * 145 * @return This object. 146 */ 147 public IniWriter blankLine() { 148 w('\n'); 149 return this; 150 } 151}