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.config.internal; 018 019import static org.apache.juneau.commons.utils.CollectionUtils.*; 020import static org.apache.juneau.commons.utils.StringUtils.*; 021import static org.apache.juneau.commons.utils.Utils.*; 022 023import java.io.*; 024import java.util.*; 025 026import org.apache.juneau.commons.lang.*; 027 028/** 029 * Represents a single entry in a configuration. 030 * 031 * This is a read-only object. 032 */ 033public class ConfigMapEntry { 034 static final ConfigMapEntry NULL = new ConfigMapEntry(null, null, null, null, null); 035 private static final AsciiSet REPLACE_CHARS = AsciiSet.of("\\#"); 036 final String rawLine; 037 final String key, value, comment; 038 039 final String modifiers; 040 041 final List<String> preLines; 042 043 ConfigMapEntry(String line, List<String> preLines) { 044 this.rawLine = line; 045 var i = line.indexOf('='); 046 var key2 = line.substring(0, i).trim(); 047 048 var m1 = key2.indexOf('<'); 049 var m2 = key2.indexOf('>'); 050 051 modifiers = nullIfEmpty((m1 > -1 && m2 > m1) ? key2.substring(m1 + 1, m2) : null); 052 053 this.key = m1 == -1 ? key2 : key2.substring(0, m1); 054 055 line = line.substring(i + 1); 056 057 i = line.indexOf('#'); 058 if (i != -1) { 059 var l2 = splita(line, '#', 2); 060 line = l2[0]; 061 if (l2.length == 2) 062 this.comment = l2[1].trim(); 063 else 064 this.comment = null; 065 } else { 066 this.comment = null; 067 } 068 069 this.value = replaceUnicodeSequences(line.trim()); 070 071 this.preLines = preLines == null ? Collections.emptyList() : u(copyOf(preLines)); 072 } 073 074 ConfigMapEntry(String key, String value, String modifiers, String comment, List<String> preLines) { 075 this.rawLine = null; 076 this.key = key; 077 this.value = value; 078 this.comment = comment; 079 this.modifiers = modifiers; 080 this.preLines = preLines == null ? Collections.emptyList() : u(copyOf(preLines)); 081 } 082 083 /** 084 * Returns the same-line comment of this entry. 085 * 086 * @return The same-line comment of this entry. 087 */ 088 public String getComment() { return comment; } 089 090 /** 091 * Returns the name of this entry. 092 * 093 * @return The name of this entry. 094 */ 095 public String getKey() { return key; } 096 097 /** 098 * Returns the modifiers for this entry. 099 * 100 * @return The modifiers for this entry, or <jk>null</jk> if it has no modifiers. 101 */ 102 public String getModifiers() { return modifiers; } 103 104 /** 105 * Returns the pre-lines of this entry. 106 * 107 * @return The pre-lines of this entry as an unmodifiable list. 108 */ 109 public List<String> getPreLines() { return preLines; } 110 111 /** 112 * Returns the raw value of this entry. 113 * 114 * @return The raw value of this entry. 115 */ 116 public String getValue() { return value; } 117 118 Writer writeTo(Writer w) throws IOException { 119 if (value == null) 120 return w; 121 for (var pl : preLines) 122 w.append(pl).append('\n'); 123 if (nn(rawLine)) { 124 for (var i = 0; i < rawLine.length(); i++) { 125 var c = rawLine.charAt(i); 126 if (c == '\n') 127 w.append('\n').append('\t'); 128 else if (c != '\r') 129 w.append(c); 130 } 131 w.append('\n'); 132 } else { 133 w.append(key); 134 if (nn(modifiers)) 135 w.append('<').append(modifiers).append('>'); 136 w.append(" = "); 137 138 var val = value; 139 for (var i = 0; i < val.length(); i++) { 140 var c = val.charAt(i); 141 if (c == '\n') 142 w.append('\n').append('\t'); 143 else if (c != '\r') { 144 if (REPLACE_CHARS.contains(c) || (Character.isISOControl(c) && ! (c == '\n' || c == '\r' || c == '\t'))) { 145 w.append(unicodeSequence(c)); 146 } else { 147 w.append(c); 148 } 149 } 150 } 151 152 if (ne(comment)) 153 w.append(" # ").append(comment); 154 155 w.append('\n'); 156 } 157 return w; 158 } 159}