Class Layout
The syntax of a layout in EBNF (Extended Backus–Naur Form) is recursively defined as follows:
layout = [ entryList, [EOL] ]
entryList = indEntry, { EOL, indEntry }
indEntry = [ comment ], indent, entry
indent = level * INDENT
entry = KEY, WS, "=", WS, VALUE |
KEY, "[]", seqVal |
KEY, layoutVal
layoutVal = [ EOL, entryList ]
seqVal = { EOL, [ comment ], indent, element }
element = TEXT |
"[]", seqVal |
".", EOL, layoutVal
comment = cLine, { cLine }
cLine = indent, "#", CTEXT, EOL
EOL = ? any predefined non-empty sequence of characters
identifying the end of a line. ?
INDENT = ? any predefined non-empty sequence of characters with
codes less than or equal to SPACE U+0020 and not
containing EOL. ?
WS = ? any empty or non-empty sequence of characters with
codes less than or equal to SPACE U+0020 and not
containing EOL. ?
KEY = ? any non-empty sequence of characters that starts
and ends with a character having a code greater than
SPACE U+0020 and that starts with a character different from
the NUMBER SIGN ('#') U+0023 and that neither
contains the EQUALS SIGN ('=') U+003D nor EOL. ?
VALUE = ? any empty or non-empty sequence of characters that
starts and ends with a character having a code greater
than SPACE U+0020 and that does not contain EOL. ?
TEXT = ? any non-empty sequence of characters that starts
and ends with a character having a code greater than
SPACE U+0020 and that starts with a character different from
the NUMBER SIGN ('#') U+0023 and that does not
contain EOL. ?
CTEXT = ? any empty or non-empty sequence of characters that does not
contain EOL. ?
The terminal symbol EOL denotes a line terminator and the symbol level denotes an integer
variable called the level of indentation.
Initially this variable is set to 0 and it is incremented by one each time a
layoutVal or seqVal non-terminal symbol is started to be
applied and it is decremented by one each time that layoutVal or that
seqVal non-terminal symbol is finished to be applied.
Thus, a layout can roughly be seen as a collection of key-value pairs where
the key is some text and the value is either a string, a sequence or again a
layout.
A key-value pair with a value being a string is also known as a
property, e.g., "age = 38".
An element of a sequence can be a string, again a sequence or a layout.
Applying three space characters for indentation, a database with a name equal to "TriasDB" containing a single table "Configuration" may be laid out like this:
name = TriasDB
version = 1.5
consistencyNumber = 0
# cipherFactoryClassName = com.example.CipherFactory
# cipherChallenge = 29jxv5pqc56i69ys
forceWriteCommit = off
recFile = rec
tables
Configuration
columns[]
.
name = ID
typeDesc = s!i58v
.
name = Locales
typeDesc = s!i40v
.
name = Timestamp
typeDesc = l!i8
store
nobsRowRef = 1
flDataFile = Configuration_fld
Due to its recursive definition the entries under tables,
Configuration, store, and the dots (.) are themselves
layouts.
Note that empty layouts, empty sequences and even empty string property
values are allowed.
Indentation is the only way to give a layout a more complex structure than just a flat set of key-value pairs. Changing the indentations manually within a file containing a layout must be done with care. It is an error if a line of text starts with a sequence of white spaces that can't be matched to an indentation. (A white space is a character with a code less than or equal to SPACE U+0020.) It is also an error if any line of text forming an entry in a layout or forming an element in a sequence has an indentation level that is too large, like the last line of text in the following example:
store
nobsRowRef = 1
flDataFile = Configuration_fld
Note, however, that
store
nobsRowRef = 1
flDataFile = Configuration_fld
is perfectly correct, though, this might not be what the user wanted
because the last entry is an entry of the "root" layout and not an entry of
the nested store layout.
Note that comments must be properly indented. Therefore
#
# This is a store
#
store
nobsRowRef = 1
# The backing file of the store
flDataFile = Configuration_fld
is perfectly correct, whereas
store
nobsRowRef = 1
# The backing file of the store
flDataFile = Configuration_fld
and
store
nobsRowRef = 1
# Now comes the table class name
flDataFile = Configuration_fld
raise an exception because the comment is not properly indented.
This class provides the following operations:
- Two factory methods for creating a layout by reading it from a UTF-8 encoded text file and input stream, respectively.
- A constructor for creating an empty layout.
- A copy constructor for creating a memory independent copy of an already existing layout.
- Methods for creating, returning and manipulating the entries of a layout.
- A method for saving the changes made to a layout.
- Two methods for writing a layout to a UTF-8 encoded text file and output stream, respectively.
- Author:
- Beat Hörmann
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classA layout entry.static final classDefines the sequence value type of a layout. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionfinal LayoutAdds the specified layout with the specified key.final Layoutadd(String key, Layout.Seq seq) Adds the specified sequence with the specified key.final LayoutAdds the specified string value with the specified key.final LayoutCreates a new layout, adds it to this layout with the specified key and returns the new layout.final Layout.SeqCreates a new sequence, adds it to this layout with the specified key and returns the new sequence.final booleanReturnstrueif this layout contains an entry with the specified key.final Layout.LtEntry[]entries()Returns the entries of this layout.static final LayoutConstructs a layout by reading it from the specified file.static final LayoutfromInputStream(InputStream inputStream) Constructs a layout by reading it from the specified input stream.final LayoutReturns the layout with the specified key.final LayoutgetLayoutByQualKey(String qualKey) Returns the layout with the specified qualified key.final LayoutgetLayoutByQualKey(String qualKey, char separator) Returns the layout with the specified qualified key, the keys separated by the specified separator character.final Layout.SeqReturns the sequence with the specified key.final Layout.SeqgetSeqByQualKey(String qualKey) Returns the sequence with the specified qualified key.final Layout.SeqgetSeqByQualKey(String qualKey, char separator) Returns the sequence with the specified qualified key, the keys separated by the specified separator character.final StringReturns the string with the specified key.final StringgetStringByQualKey(String qualKey) Returns the string with the specified qualified key.final StringgetStringByQualKey(String qualKey, char separator) Returns the string with the specified qualified key, the keys separated by the specified separator character.final Stringindent()Returns the indentation discovered in the file or input stream when this layout was constructed with thefromFile(java.nio.file.Path)orfromInputStream(java.io.InputStream)factory method, respectively.final LayoutRemoves the entry with the specified key.final LayoutReplaces the stored layout having the specified key with the specified layout.final Layoutreplace(String key, Layout.Seq seq) Replaces the stored sequence having the specified key with the specified sequence.final LayoutReplaces the stored string value having the specified key with the specified string value.final LayoutreplaceKey(String key, String newKey) Replaces the specified current key with the specified new key.final voidsave()Invokes thetoFile(java.nio.file.Path, java.lang.String, java.nio.file.OpenOption...)method with the file identical to thefileargument of thefromFile(java.nio.file.Path)factory method and with no open options.final intsize()Returns the number of entries in this layout.final voidtoFile(Path file, String indent, OpenOption... options) Writes this layout to the specified file.toMap()Converts this layout to anunmodifiablemap.final voidtoOutputStream(OutputStream stream, String indent) Writes this layout to the specified output stream.
-
Constructor Details
-
Layout
public Layout()Constructs a new empty layout. -
Layout
Copy constructor. Creates a new layout and deeply copies the elements of the specified layout into it. The created layout is memory independent of the specified layout.- Parameters:
layout- The layout to copy, not allowed to benull.- Throws:
NullPointerException- Iflayoutisnull.
-
-
Method Details
-
fromFile
public static final Layout fromFile(Path file) throws NullPointerException, IndentationException, DanglingCommentException, IOException Constructs a layout by reading it from the specified file. By convention, the first line of text that does not contain white spaces only and that starts with a (series of) white space(s) defines the indentation. (A white space is a character with a code less than or equal to '\u0020', the code of SPACE U+0020.)Blank lines, hence, lines of text containing white spaces only or even no characters at all are tolerated as well as lines of text ending with white spaces immediately before the
line terminator. Note, however, that such extra sugar, unlike comments, is not retained when the layout is written back to the same file or to another file or output stream calling thetoFile(java.nio.file.Path, java.lang.String, java.nio.file.OpenOption...),save()ortoOutputStream(java.io.OutputStream, java.lang.String)method.This method assumes the characters in the file to be coded in UTF-8.
- Parameters:
file- The file containing the layout, not allowed to benull.- Returns:
- The layout.
- Throws:
NullPointerException- Iffileisnull.IndentationException- If a line of text is not properly indented. (See the class description to learn about a line of text that is not properly indented.)DanglingCommentException- If there exists a comment that is not properly followed or not followed at all by an entry or an element of a sequence.IOException- If the specified file does not exist or if another I/O error occurs.
-
fromInputStream
public static final Layout fromInputStream(InputStream inputStream) throws NullPointerException, IndentationException, DanglingCommentException, IOException Constructs a layout by reading it from the specified input stream. Apart from reading the layout from a stream rather than from a file invoking this factory method has exactly the same effect as invoking thefromFile(java.nio.file.Path)factory method.The specified input stream is not closed.
- Parameters:
inputStream- The input stream from where to read the layout, not allowed to benull.- Returns:
- The layout, never
nullbut may be an empty layout. - Throws:
NullPointerException- IfinputStreamisnull.IndentationException- If a line of text is not properly indented. (See the class description to learn about a line of text that is not properly indented.)DanglingCommentException- If there exists a comment that is not properly followed or not followed at all by an entry or an element of a sequence.IOException- If an I/O error occurs.
-
toMap
Converts this layout to anunmodifiablemap. The keys and the values of the returned map are the keys and the values of this layout. The values are of typeString,SeqorLayout.- Returns:
- The layout as an unmodifiable map.
-
entries
Returns the entries of this layout. The entries are sorted in the order of their creation. For example, if this layout was obtained from a file or an input stream then the entries appear in the same order as they were originally read from the input stream or the file.- Returns:
- The sorted array of entries of this layout, never
null.
-
size
public final int size()Returns the number of entries in this layout.- Returns:
- The number of entries in this layout.
-
contains
Returnstrueif this layout contains an entry with the specified key.- Parameters:
key- The key whose presence in the layout is to be tested.- Returns:
- The boolean value
trueif this layout contains an entry with the specified key. - Throws:
NullPointerException- If the specified key isnull.
-
getString
public final String getString(String key) throws MissingEntryException, NullPointerException, ClassCastException Returns the string with the specified key.- Parameters:
key- The key whose associated string is to be returned.- Returns:
- The string with the specified key, never
null. - Throws:
MissingEntryException- If the layout contains no entry with the specified key.NullPointerException- If the specified key isnull.ClassCastException- If the stored value with the specified key is not a string.
-
getSeq
public final Layout.Seq getSeq(String key) throws MissingEntryException, NullPointerException, ClassCastException Returns the sequence with the specified key.- Parameters:
key- The key whose associated sequence is to be returned.- Returns:
- The sequence with the specified key, never
null. - Throws:
MissingEntryException- If the layout contains no entry with the specified key.NullPointerException- If the specified key isnull.ClassCastException- If the stored value with the specified key is not a sequence.
-
getLayout
public final Layout getLayout(String key) throws MissingEntryException, NullPointerException, ClassCastException Returns the layout with the specified key.- Parameters:
key- The key whose associated layout is to be returned.- Returns:
- The layout with the specified key, never
null. - Throws:
MissingEntryException- If the layout contains no entry with the specified key.NullPointerException- If the specified key isnull.ClassCastException- If the stored value with the specified key is not a layout.
-
getStringByQualKey
public final String getStringByQualKey(String qualKey) throws MissingEntryException, NullPointerException, ClassCastException Returns the string with the specified qualified key.The result and behaviour of invoking this method is identical to the result and behaviour of invoking the
getStringByQualKey(String, char)method with a separator character equal to the dot ('.') character.- Parameters:
qualKey- The qualified key whose associated string is to be returned.- Returns:
- The string with the specified qualified key, never
null. - Throws:
MissingEntryException- If the layout contains no entry with the specified qualified key.NullPointerException- If the specified qualified key isnull.ClassCastException- If the stored value of one of the layout keys of the specified qualified key is not a layout or if the stored value with the last key is not a string.
-
getStringByQualKey
public final String getStringByQualKey(String qualKey, char separator) throws MissingEntryException, NullPointerException, ClassCastException Returns the string with the specified qualified key, the keys separated by the specified separator character.A qualified key denotes a sequence of normal keys where the keys are separated from each other by the specified separator character, as, for instance, in
profession.words.tableClassNamewith a separator character equal to the dot ('.'). All but the last key must map to a layout and are therefore called the layout keys. (In the example above,professionandwordsare layout keys.)A qualified key not containing the separator character has no layout keys and thus reduces to a normal key.
- Parameters:
qualKey- The qualified key whose associated string is to be returned.separator- The separator character.- Returns:
- The string with the specified qualified key, never
null. - Throws:
MissingEntryException- If the layout contains no entry with the specified qualified key.NullPointerException- If the specified qualified key isnull.ClassCastException- If the stored value of one of the layout keys of the specified qualified key is not a layout or if the stored value with the last key is not a string.
-
getSeqByQualKey
public final Layout.Seq getSeqByQualKey(String qualKey) throws MissingEntryException, NullPointerException, ClassCastException Returns the sequence with the specified qualified key.The result and behaviour of invoking this method is identical to the result and behaviour of invoking the
getSeqByQualKey(String, char)method with a separator character equal to the dot ('.') character.- Parameters:
qualKey- The qualified key whose associated sequence is to be returned.- Returns:
- The sequence with the specified qualified key, never
null. - Throws:
MissingEntryException- If the layout contains no entry with the specified qualified key.NullPointerException- If the specified qualified key isnull.ClassCastException- If the stored value of one of the layout keys of the specified qualified key is not a layout or if the stored value with the last key is not a sequence.
-
getSeqByQualKey
public final Layout.Seq getSeqByQualKey(String qualKey, char separator) throws MissingEntryException, NullPointerException, ClassCastException Returns the sequence with the specified qualified key, the keys separated by the specified separator character.A qualified key denotes a sequence of normal keys where the keys are separated from each other by the specified separator character, as, for instance, in
profession.words.tableClassNamewith a separator character equal to the dot ('.'). All but the last key must map to a layout and are therefore called the layout keys. (In the example above,professionandwordsare layout keys.)A qualified key not containing the separator character has no layout keys and thus reduces to a normal key.
- Parameters:
qualKey- The qualified key whose associated sequence is to be returned.separator- The separator character.- Returns:
- The sequence with the specified qualified key, never
null. - Throws:
MissingEntryException- If the layout contains no entry with the specified qualified key.NullPointerException- If the specified qualified key isnull.ClassCastException- If the stored value of one of the layout keys of the specified qualified key is not a layout or if the stored value with the last key is not a sequence.
-
getLayoutByQualKey
public final Layout getLayoutByQualKey(String qualKey) throws MissingEntryException, NullPointerException, ClassCastException Returns the layout with the specified qualified key.The result and behaviour of invoking this method is identical to the result and behaviour of invoking the
getLayoutByQualKey(String, char)method with a separator character equal to the dot ('.') character.- Parameters:
qualKey- The qualified key whose associated layout is to be returned.- Returns:
- The layout with the specified qualified key, never
null. - Throws:
MissingEntryException- If the layout contains no entry with the specified qualified key.NullPointerException- If the specified qualified key isnull.ClassCastException- If the stored value of one of the keys of the specified qualified key is not a layout.
-
getLayoutByQualKey
public final Layout getLayoutByQualKey(String qualKey, char separator) throws MissingEntryException, NullPointerException, ClassCastException Returns the layout with the specified qualified key, the keys separated by the specified separator character.A qualified key denotes a sequence of normal keys where the keys are separated from each other by the specified separator character, as, for instance, in
profession.words.tableClassNamewith a separator character equal to the dot ('.'). All but the last key must map to a layout and are therefore called the layout keys. (In the example above,professionandwordsare layout keys.)A qualified key not containing the separator character has no layout keys and thus reduces to a normal key.
- Parameters:
qualKey- The qualified key whose associated layout is to be returned.separator- The separator character.- Returns:
- The layout with the specified qualified key, never
null. - Throws:
MissingEntryException- If the layout contains no entry with the specified qualified key.NullPointerException- If the specified qualified key isnull.ClassCastException- If the stored value of one of the keys of the specified qualified key is not a layout.
-
add
public final Layout add(String key, String value) throws IllegalArgumentException, NullPointerException Adds the specified string value with the specified key.- Parameters:
key- The key with which the specified string value is to be associated.value- The string value to be associated with the specified key.- Returns:
- This layout.
- Throws:
IllegalArgumentException- If the layout already contains an entry with the specified key.NullPointerException- If the specified key or string value isnull.
-
addSeq
Creates a new sequence, adds it to this layout with the specified key and returns the new sequence.- Parameters:
key- The key with which the new sequence is to be associated.- Returns:
- The newly created empty sequence, never
null. - Throws:
IllegalArgumentException- If the layout already contains an entry with the specified key.NullPointerException- If the specified key isnull.
-
add
public final Layout add(String key, Layout.Seq seq) throws IllegalArgumentException, NullPointerException Adds the specified sequence with the specified key.- Parameters:
key- The key with which the specified sequence is to be associated.seq- The sequence to be associated with the specified key.- Returns:
- This layout.
- Throws:
IllegalArgumentException- If the layout already contains an entry with the specified key.NullPointerException- If the specified key or sequence isnull.
-
addLayout
Creates a new layout, adds it to this layout with the specified key and returns the new layout.- Parameters:
key- The key with which the new layout is to be associated.- Returns:
- The newly created empty layout, never
null. - Throws:
IllegalArgumentException- If the layout already contains an entry with the specified key.NullPointerException- If the specified key isnull.
-
add
public final Layout add(String key, Layout layout) throws IllegalArgumentException, NullPointerException Adds the specified layout with the specified key.- Parameters:
key- The key with which the specified layout is to be associated.layout- The layout to be associated with the specified key.- Returns:
- This layout.
- Throws:
IllegalArgumentException- If the layout already contains an entry with the specified key.NullPointerException- If the specified key or layout isnull.
-
replace
public final Layout replace(String key, String value) throws MissingEntryException, NullPointerException, ClassCastException Replaces the stored string value having the specified key with the specified string value.- Parameters:
key- The key whose value is to be replaced.value- The string value, not allowed to benull.- Returns:
- This layout.
- Throws:
MissingEntryException- If the layout contains no entry with the specified key.NullPointerException- If the specified key or string value isnull.ClassCastException- If the stored value with the specified key is not a string.
-
replace
public final Layout replace(String key, Layout.Seq seq) throws MissingEntryException, NullPointerException, ClassCastException Replaces the stored sequence having the specified key with the specified sequence.- Parameters:
key- The key whose value is to be replaced.seq- The sequence, not allowed to benull.- Returns:
- This layout.
- Throws:
MissingEntryException- If the layout contains no entry with the specified key.NullPointerException- If the specified key or sequence isnull.ClassCastException- If the stored value with the specified key is not a sequence.
-
replace
public final Layout replace(String key, Layout layout) throws MissingEntryException, NullPointerException, ClassCastException Replaces the stored layout having the specified key with the specified layout.- Parameters:
key- The key whose value is to be replaced.layout- The layout, not allowed to benull.- Returns:
- This layout.
- Throws:
MissingEntryException- If the layout contains no entry with the specified key.NullPointerException- If the specified key or layout isnull.ClassCastException- If the stored value with the specified key is not a layout.
-
replaceKey
public final Layout replaceKey(String key, String newKey) throws MissingEntryException, IllegalArgumentException, NullPointerException Replaces the specified current key with the specified new key.This method has no effect if the current key is equal to the new key.
- Parameters:
key- The current key.newKey- The new key.- Returns:
- This layout.
- Throws:
MissingEntryException- If the layout contains no entry with the specified current key.IllegalArgumentException- If the layout already contains an entry with the specified new key.NullPointerException- If one of the arguments isnull.
-
remove
Removes the entry with the specified key.- Parameters:
key- The key whose entry is to be removed.- Returns:
- This layout.
- Throws:
MissingEntryException- If the layout contains no entry for the specified key.NullPointerException- If the specified key isnull.
-
indent
Returns the indentation discovered in the file or input stream when this layout was constructed with thefromFile(java.nio.file.Path)orfromInputStream(java.io.InputStream)factory method, respectively.- Returns:
- The indentation, never an empty string.
The value is
nullif the layout was not constructed with one of the factory methods mentioned above or if the layout has no indented elements.
-
toFile
public final void toFile(Path file, String indent, OpenOption... options) throws IllegalArgumentException, NullPointerException, UnsupportedOperationException, IOException Writes this layout to the specified file. Nested layouts and sequences are indented using the specified indentation or the tab character (CHARACTER TABULATION (U+0009)) if the specified indentation isnullor an empty string. The written layout strictly conforms to the syntax rules given in the class description.The entries of a layout appear in the order of their creation. This guarantees that a layout that was originally read from a file or an input stream (see
fromFile(java.nio.file.Path)orfromInputStream(java.io.InputStream)) looks "similar" to the layout later written back to the same file or to another file. Comments are retained. However, blank lines in the original file and the character (or sequence of characters) used for indendation, as well as extra white spaces immediately before the end of a line of text are not retained. Furthermore, the equal character ('=') in a property is surrounded by a single space character, ignoring any other surrounding sequences of white spaces in the original file or input stream.Uses UTF-8 for character encoding.
This method fails if the file is locked.
- Parameters:
file- The file to which to write this layout, not allowed to benull.indent- The indentation to use for nested layouts ornullin which case an indentation equal to CHARACTER TABULATION U+0009 is used.options- The options specifying how the file is opened, see theFiles.writemethod description for any details.- Throws:
IllegalArgumentException- If the specified indentation contains at least one character that is not a white space.NullPointerException- If the specified file isnull.UnsupportedOperationException- If an unsupported option is specified.IOException- If an I/O error occurs.
-
save
Invokes thetoFile(java.nio.file.Path, java.lang.String, java.nio.file.OpenOption...)method with the file identical to thefileargument of thefromFile(java.nio.file.Path)factory method and with no open options.- Throws:
UnsupportedOperationException- If this layout was constructed with a constructor different from thefromFilefactory method.IOException- If an I/O error occurs.
-
toOutputStream
public final void toOutputStream(OutputStream stream, String indent) throws IllegalArgumentException, NullPointerException, IOException Writes this layout to the specified output stream. Apart from writing the layout to a stream rather than to a file invoking this method has exactly the same effect as invoking thetoFile(java.nio.file.Path, java.lang.String, java.nio.file.OpenOption...)method.The specified output stream is not closed.
- Parameters:
stream- The output stream to which to write this layout, not allowed to benull.indent- The indentation to use for nested layouts ornullin which case an indentation equal to CHARACTER TABULATION U+0009 is used.- Throws:
IllegalArgumentException- If the specified indentation contains at least one character that is not a white space.NullPointerException- If the specified stream isnull.IOException- If an I/O error occurs.
-