Class PropertiesConfigurationLayout
- java.lang.Object
-
- org.apache.commons.configuration2.PropertiesConfigurationLayout
-
- All Implemented Interfaces:
EventListener<ConfigurationEvent>
public class PropertiesConfigurationLayout extends java.lang.Object implements EventListener<ConfigurationEvent>
A helper class used by
PropertiesConfiguration
to keep the layout of a properties file.Instances of this class are associated with a
PropertiesConfiguration
object. They are responsible for analyzing properties files and for extracting as much information about the file layout (e.g. empty lines, comments) as possible. When the properties file is written back again it should be close to the original.The
PropertiesConfigurationLayout
object associated with aPropertiesConfiguration
object can be obtained using thegetLayout()
method of the configuration. Then the methods provided by this class can be used to alter the properties file's layout.Implementation note: This is a very simple implementation, which is far away from being perfect, i.e. the original layout of a properties file won't be reproduced in all cases. One limitation is that comments for multi-valued property keys are concatenated. Maybe this implementation can later be improved.
To get an impression how this class works consider the following properties file:
# A demo configuration file # for Demo App 1.42 # Application name AppName=Demo App # Application vendor AppVendor=DemoSoft # GUI properties # Window Color windowColors=0xFFFFFF,0x000000 # Include some setting include=settings.properties # Another vendor AppVendor=TestSoft
For this example the following points are relevant:
- The first two lines are set as header comment. The header comment is determined by the last blank line before the first property definition.
- For the property
AppName
one comment line and one leading blank line is stored. - For the property
windowColors
two comment lines and two leading blank lines are stored. - Include files is something this class cannot deal with well. When saving the properties configuration back, the included properties are simply contained in the original file. The comment before the include property is skipped.
- For all properties except for
AppVendor
the "single line" flag is set. This is relevant only forwindowColors
, which has multiple values defined in one line using the separator character. - The
AppVendor
property appears twice. The comment lines are concatenated, so thatlayout.getComment("AppVendor");
will result inApplication vendor<CR>Another vendor
, with<CR>
meaning the line separator. In addition the "single line" flag is set to false for this property. When the file is saved, two property definitions will be written (in series).
- Since:
- 1.3
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description (package private) static class
PropertiesConfigurationLayout.PropertyLayoutData
A helper class for storing all layout related information for a configuration property.
-
Field Summary
Fields Modifier and Type Field Description private static java.lang.String
COMMENT_PREFIX
Constant for the default comment prefix.private static java.lang.String
CR
Constant for the line break character.private java.lang.String
footerComment
Stores the footer comment.private boolean
forceSingleLine
Stores the force single line flag.private java.lang.String
globalSeparator
The global separator that will be used for all properties.private java.lang.String
headerComment
Stores the header comment.private java.util.Map<java.lang.String,PropertiesConfigurationLayout.PropertyLayoutData>
layoutData
Stores a map with the contained layout information.private java.lang.String
lineSeparator
The line separator.private java.util.concurrent.atomic.AtomicInteger
loadCounter
A counter for determining nested load calls.private java.util.ArrayDeque<java.net.URL>
seenStack
Seen includes.
-
Constructor Summary
Constructors Constructor Description PropertiesConfigurationLayout()
Creates a new, empty instance ofPropertiesConfigurationLayout
.PropertiesConfigurationLayout(PropertiesConfigurationLayout c)
Creates a new instance ofPropertiesConfigurationLayout
and copies the data of the specified layout object.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Deprecated Methods Modifier and Type Method Description private int
checkHeaderComment(java.util.List<java.lang.String> commentLines)
Checks if parts of the passed in comment can be used as header comment.private void
clear()
Removes all content from this layout object.private static java.lang.String
constructCanonicalComment(java.lang.String comment, boolean commentChar)
Helper method for generating a comment string.private void
copyFrom(PropertiesConfigurationLayout c)
Copies the data from the given layout object.private java.lang.String
extractComment(java.util.List<java.lang.String> commentLines, int from, int to)
Extracts a comment string from the given range of the specified comment lines.private PropertiesConfigurationLayout.PropertyLayoutData
fetchLayoutData(java.lang.String key)
Returns a layout data object for the specified key.int
getBlancLinesBefore(java.lang.String key)
Deprecated.int
getBlankLinesBefore(java.lang.String key)
Gets the number of blank lines before this property key.java.lang.String
getCanonicalComment(java.lang.String key, boolean commentChar)
Gets the comment for the specified property key in a canonical form.java.lang.String
getCanonicalFooterCooment(boolean commentChar)
Gets the footer comment of the represented properties file in a canonical form.java.lang.String
getCanonicalHeaderComment(boolean commentChar)
Gets the header comment of the represented properties file in a canonical form.java.lang.String
getComment(java.lang.String key)
Gets the comment for the specified property key.java.lang.String
getFooterComment()
Gets the footer comment of the represented properties file.java.lang.String
getGlobalSeparator()
Gets the global separator.java.lang.String
getHeaderComment()
Gets the header comment of the represented properties file.java.util.Set<java.lang.String>
getKeys()
Gets a set with all property keys managed by this object.java.lang.String
getLineSeparator()
Gets the line separator.java.lang.String
getSeparator(java.lang.String key)
Gets the separator for the property with the given key.(package private) static boolean
isCommentLine(java.lang.String line)
Tests whether a line is a comment, i.e.boolean
isForceSingleLine()
Returns the "force single line" flag.boolean
isSingleLine(java.lang.String key)
Returns a flag whether the specified property is defined on a single line.void
load(PropertiesConfiguration config, java.io.Reader reader)
Reads a properties file and stores its internal structure.void
onEvent(ConfigurationEvent event)
The event listener callback.void
save(PropertiesConfiguration config, java.io.Writer writer)
Writes the properties file to the given writer, preserving as much of its structure as possible.void
setBlancLinesBefore(java.lang.String key, int number)
Deprecated.void
setBlankLinesBefore(java.lang.String key, int number)
Sets the number of blank lines before the given property key.void
setComment(java.lang.String key, java.lang.String comment)
Sets the comment for the specified property key.void
setFooterComment(java.lang.String footerComment)
Sets the footer comment for the represented properties file.void
setForceSingleLine(boolean f)
Sets the "force single line" flag.void
setGlobalSeparator(java.lang.String globalSeparator)
Sets the global separator for properties.void
setHeaderComment(java.lang.String comment)
Sets the header comment for the represented properties file.void
setLineSeparator(java.lang.String lineSeparator)
Sets the line separator.void
setSeparator(java.lang.String key, java.lang.String sep)
Sets the separator to be used for the property with the given key.void
setSingleLine(java.lang.String key, boolean f)
Sets the "single line flag" for the specified property key.(package private) static java.lang.String
stripCommentChar(java.lang.String s, boolean comment)
Either removes the comment character from the given comment line or ensures that the line starts with a comment character.(package private) static java.lang.String
trimComment(java.lang.String s, boolean comment)
Trims a comment.private static void
writeComment(PropertiesConfiguration.PropertiesWriter writer, java.lang.String comment)
Helper method for writing a comment line.
-
-
-
Field Detail
-
CR
private static final java.lang.String CR
Constant for the line break character.- See Also:
- Constant Field Values
-
COMMENT_PREFIX
private static final java.lang.String COMMENT_PREFIX
Constant for the default comment prefix.- See Also:
- Constant Field Values
-
layoutData
private final java.util.Map<java.lang.String,PropertiesConfigurationLayout.PropertyLayoutData> layoutData
Stores a map with the contained layout information.
-
headerComment
private java.lang.String headerComment
Stores the header comment.
-
footerComment
private java.lang.String footerComment
Stores the footer comment.
-
globalSeparator
private java.lang.String globalSeparator
The global separator that will be used for all properties.
-
lineSeparator
private java.lang.String lineSeparator
The line separator.
-
loadCounter
private final java.util.concurrent.atomic.AtomicInteger loadCounter
A counter for determining nested load calls.
-
forceSingleLine
private boolean forceSingleLine
Stores the force single line flag.
-
seenStack
private final java.util.ArrayDeque<java.net.URL> seenStack
Seen includes.
-
-
Constructor Detail
-
PropertiesConfigurationLayout
public PropertiesConfigurationLayout()
Creates a new, empty instance ofPropertiesConfigurationLayout
.
-
PropertiesConfigurationLayout
public PropertiesConfigurationLayout(PropertiesConfigurationLayout c)
Creates a new instance ofPropertiesConfigurationLayout
and copies the data of the specified layout object.- Parameters:
c
- the layout object to be copied
-
-
Method Detail
-
constructCanonicalComment
private static java.lang.String constructCanonicalComment(java.lang.String comment, boolean commentChar)
Helper method for generating a comment string. Depending on the boolean argument the resulting string either has no comment characters or a leading comment character at each line.- Parameters:
comment
- the comment string to be processedcommentChar
- determines the presence of comment characters- Returns:
- the canonical comment string (can be null)
-
isCommentLine
static boolean isCommentLine(java.lang.String line)
Tests whether a line is a comment, i.e. whether it starts with a comment character.- Parameters:
line
- the line- Returns:
- a flag if this is a comment line
-
stripCommentChar
static java.lang.String stripCommentChar(java.lang.String s, boolean comment)
Either removes the comment character from the given comment line or ensures that the line starts with a comment character.- Parameters:
s
- the comment linecomment
- if true, a comment character will always be enforced; if false, it will be removed- Returns:
- the line without comment character
-
trimComment
static java.lang.String trimComment(java.lang.String s, boolean comment)
Trims a comment. This method either removes all comment characters from the given string, leaving only the plain comment text or ensures that every line starts with a valid comment character.- Parameters:
s
- the string to be processedcomment
- if true, a comment character will always be enforced; if false, it will be removed- Returns:
- the trimmed comment
-
writeComment
private static void writeComment(PropertiesConfiguration.PropertiesWriter writer, java.lang.String comment) throws java.io.IOException
Helper method for writing a comment line. This method ensures that the correct line separator is used if the comment spans multiple lines.- Parameters:
writer
- the writercomment
- the comment to write- Throws:
java.io.IOException
- if an IO error occurs
-
checkHeaderComment
private int checkHeaderComment(java.util.List<java.lang.String> commentLines)
Checks if parts of the passed in comment can be used as header comment. This method checks whether a header comment can be defined (i.e. whether this is the first comment in the loaded file). If this is the case, it is searched for the latest blank line. This line will mark the end of the header comment. The return value is the index of the first line in the passed in list, which does not belong to the header comment.- Parameters:
commentLines
- the comment lines- Returns:
- the index of the next line after the header comment
-
clear
private void clear()
Removes all content from this layout object.
-
copyFrom
private void copyFrom(PropertiesConfigurationLayout c)
Copies the data from the given layout object.- Parameters:
c
- the layout object to copy
-
extractComment
private java.lang.String extractComment(java.util.List<java.lang.String> commentLines, int from, int to)
Extracts a comment string from the given range of the specified comment lines. The single lines are added using a line feed as separator.- Parameters:
commentLines
- a list with comment linesfrom
- the start indexto
- the end index (inclusive)- Returns:
- the comment string (null if it is undefined)
-
fetchLayoutData
private PropertiesConfigurationLayout.PropertyLayoutData fetchLayoutData(java.lang.String key)
Returns a layout data object for the specified key. If this is a new key, a new object is created and initialized with default values.- Parameters:
key
- the key- Returns:
- the corresponding layout data object
-
getBlancLinesBefore
@Deprecated public int getBlancLinesBefore(java.lang.String key)
Deprecated.Gets the number of blank lines before this property key. If this key does not exist, 0 will be returned.- Parameters:
key
- the property key- Returns:
- the number of blank lines before the property definition for this key
-
getBlankLinesBefore
public int getBlankLinesBefore(java.lang.String key)
Gets the number of blank lines before this property key. If this key does not exist, 0 will be returned.- Parameters:
key
- the property key- Returns:
- the number of blank lines before the property definition for this key
-
getCanonicalComment
public java.lang.String getCanonicalComment(java.lang.String key, boolean commentChar)
Gets the comment for the specified property key in a canonical form. "Canonical" means that either all lines start with a comment character or none. If thecommentChar
parameter is false, all comment characters are removed, so that the result is only the plain text of the comment. Otherwise it is ensured that each line of the comment starts with a comment character. Also, line breaks in the comment are normalized to the line separator "\n".- Parameters:
key
- the key of the propertycommentChar
- determines whether all lines should start with comment characters or not- Returns:
- the canonical comment for this key (can be null)
-
getCanonicalFooterCooment
public java.lang.String getCanonicalFooterCooment(boolean commentChar)
Gets the footer comment of the represented properties file in a canonical form. This method works likegetCanonicalHeaderComment()
, but reads the footer comment.- Parameters:
commentChar
- determines the presence of comment characters- Returns:
- the footer comment (can be null)
- Since:
- 2.0
- See Also:
getCanonicalHeaderComment(boolean)
-
getCanonicalHeaderComment
public java.lang.String getCanonicalHeaderComment(boolean commentChar)
Gets the header comment of the represented properties file in a canonical form. With thecommentChar
parameter it can be specified whether comment characters should be stripped or be always present.- Parameters:
commentChar
- determines the presence of comment characters- Returns:
- the header comment (can be null)
-
getComment
public java.lang.String getComment(java.lang.String key)
Gets the comment for the specified property key. The comment is returned as it was set (either manually by callingsetComment()
or when it was loaded from a properties file). No modifications are performed.- Parameters:
key
- the key of the property- Returns:
- the comment for this key (can be null)
-
getFooterComment
public java.lang.String getFooterComment()
Gets the footer comment of the represented properties file. This method returns the footer comment exactly as it was set usingsetFooterComment()
or extracted from the loaded properties file.- Returns:
- the footer comment (can be null)
- Since:
- 2.0
-
getGlobalSeparator
public java.lang.String getGlobalSeparator()
Gets the global separator.- Returns:
- the global properties separator
- Since:
- 1.7
-
getHeaderComment
public java.lang.String getHeaderComment()
Gets the header comment of the represented properties file. This method returns the header comment exactly as it was set usingsetHeaderComment()
or extracted from the loaded properties file.- Returns:
- the header comment (can be null)
-
getKeys
public java.util.Set<java.lang.String> getKeys()
Gets a set with all property keys managed by this object.- Returns:
- a set with all contained property keys
-
getLineSeparator
public java.lang.String getLineSeparator()
Gets the line separator.- Returns:
- the line separator
- Since:
- 1.7
-
getSeparator
public java.lang.String getSeparator(java.lang.String key)
Gets the separator for the property with the given key.- Parameters:
key
- the property key- Returns:
- the property separator for this property
- Since:
- 1.7
-
isForceSingleLine
public boolean isForceSingleLine()
Returns the "force single line" flag.- Returns:
- the force single line flag
- See Also:
setForceSingleLine(boolean)
-
isSingleLine
public boolean isSingleLine(java.lang.String key)
Returns a flag whether the specified property is defined on a single line. This is meaningful only if this property has multiple values.- Parameters:
key
- the property key- Returns:
- a flag if this property is defined on a single line
-
load
public void load(PropertiesConfiguration config, java.io.Reader reader) throws ConfigurationException
Reads a properties file and stores its internal structure. The found properties will be added to the specified configuration object.- Parameters:
config
- the associated configuration objectreader
- the reader to the properties file- Throws:
ConfigurationException
- if an error occurs
-
onEvent
public void onEvent(ConfigurationEvent event)
The event listener callback. Here event notifications of the configuration object are processed to update the layout object properly.- Specified by:
onEvent
in interfaceEventListener<ConfigurationEvent>
- Parameters:
event
- the event object
-
save
public void save(PropertiesConfiguration config, java.io.Writer writer) throws ConfigurationException
Writes the properties file to the given writer, preserving as much of its structure as possible.- Parameters:
config
- the associated configuration objectwriter
- the writer- Throws:
ConfigurationException
- if an error occurs
-
setBlancLinesBefore
@Deprecated public void setBlancLinesBefore(java.lang.String key, int number)
Deprecated.Sets the number of blank lines before the given property key. This can be used for a logical grouping of properties.- Parameters:
key
- the property keynumber
- the number of blank lines to add before this property definition
-
setBlankLinesBefore
public void setBlankLinesBefore(java.lang.String key, int number)
Sets the number of blank lines before the given property key. This can be used for a logical grouping of properties.- Parameters:
key
- the property keynumber
- the number of blank lines to add before this property definition- Since:
- 2.8.0
-
setComment
public void setComment(java.lang.String key, java.lang.String comment)
Sets the comment for the specified property key. The comment (or its single lines if it is a multi-line comment) can start with a comment character. If this is the case, it will be written without changes. Otherwise a default comment character is added automatically.- Parameters:
key
- the key of the propertycomment
- the comment for this key (can be null, then the comment will be removed)
-
setFooterComment
public void setFooterComment(java.lang.String footerComment)
Sets the footer comment for the represented properties file. This comment will be output at the bottom of the file.- Parameters:
footerComment
- the footer comment- Since:
- 2.0
-
setForceSingleLine
public void setForceSingleLine(boolean f)
Sets the "force single line" flag. If this flag is set, all properties with multiple values are written on single lines. This mode provides more compatibility withProperties
, which cannot deal with multiple definitions of a single property. This mode has no effect if the list delimiter parsing is disabled.- Parameters:
f
- the force single line flag
-
setGlobalSeparator
public void setGlobalSeparator(java.lang.String globalSeparator)
Sets the global separator for properties. With this method a separator can be set that will be used for all properties when writing the configuration. This is an easy way of determining the properties separator globally. To be compatible with the properties format only the characters=
and:
(with or without whitespace) should be used, but this method does not enforce this - it accepts arbitrary strings. If the global separator is set to null, property separators are not changed. This is the default behavior as it produces results that are closer to the original properties file.- Parameters:
globalSeparator
- the separator to be used for all properties- Since:
- 1.7
-
setHeaderComment
public void setHeaderComment(java.lang.String comment)
Sets the header comment for the represented properties file. This comment will be output on top of the file.- Parameters:
comment
- the comment
-
setLineSeparator
public void setLineSeparator(java.lang.String lineSeparator)
Sets the line separator. When writing the properties configuration, all lines are terminated with this separator. If no separator was set, the platform-specific default line separator is used.- Parameters:
lineSeparator
- the line separator- Since:
- 1.7
-
setSeparator
public void setSeparator(java.lang.String key, java.lang.String sep)
Sets the separator to be used for the property with the given key. The separator is the string between the property key and its value. For new properties " = " is used. When a properties file is read, the layout tries to determine the separator for each property. With this method the separator can be changed. To be compatible with the properties format only the characters=
and:
(with or without whitespace) should be used, but this method does not enforce this - it accepts arbitrary strings. If the key refers to a property with multiple values that are written on multiple lines, this separator will be used on all lines.- Parameters:
key
- the key for the propertysep
- the separator to be used for this property- Since:
- 1.7
-
setSingleLine
public void setSingleLine(java.lang.String key, boolean f)
Sets the "single line flag" for the specified property key. This flag is evaluated if the property has multiple values (i.e. if it is a list property). In this case, if the flag is set, all values will be written in a single property definition using the list delimiter as separator. Otherwise multiple lines will be written for this property, each line containing one property value.- Parameters:
key
- the property keyf
- the single line flag
-
-