| Author | djarvis <email> |
|---|---|
| Date | 2017-11-18 11:51:02 GMT-0800 |
| Commit | 168add4fe1140591e059a5cb65b2bae4a6a4843a |
| Parent | 08eda35 |
| Delta | 276 lines added, 68 lines removed, 208-line increase |
|---|
| package com.whitemagicsoftware.yamlp; | ||
| +import static com.whitemagicsoftware.yamlp.FileType.JSON; | ||
| +import static com.whitemagicsoftware.yamlp.FileType.XML; | ||
| +import static com.whitemagicsoftware.yamlp.FileType.YAML; | ||
| +import java.io.File; | ||
| +import java.io.FileInputStream; | ||
| +import java.io.IOException; | ||
| +import java.io.InputStream; | ||
| import org.kohsuke.args4j.CmdLineParser; | ||
| import org.kohsuke.args4j.Option; | ||
| * File name given on the command line. | ||
| */ | ||
| - private String filename; | ||
| + private String inputFilename; | ||
| + | ||
| + /** | ||
| + * File name given on the command line. | ||
| + */ | ||
| + private String outputFilename; | ||
| /** | ||
| /** | ||
| - * Export in XML format. | ||
| + * Export format. | ||
| */ | ||
| - private boolean exportXml = false; | ||
| + private FileType exportFormat; | ||
| /** | ||
| * Returns the name of the YAML file to parse. This is set by parsing the | ||
| * command line. | ||
| * | ||
| - * @return | ||
| + * @return The filename to read. | ||
| */ | ||
| - public String getFilename() { | ||
| - return this.filename; | ||
| + public String getInputFilename() { | ||
| + return this.inputFilename; | ||
| + } | ||
| + | ||
| + public InputStream getInputStream() throws IOException { | ||
| + final String filename = getInputFilename(); | ||
| + | ||
| + final InputStream stream = isEmpty( filename ) | ||
| + ? System.in | ||
| + : createFileInputStream( filename ); | ||
| + | ||
| + return stream; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Open a file. | ||
| + * | ||
| + * @param filename The file name to open. | ||
| + * | ||
| + * @throws IOException Could not open the file. | ||
| + */ | ||
| + private InputStream createFileInputStream( final String filename ) | ||
| + throws IOException { | ||
| + final File file = new File( filename ); | ||
| + final InputStream stream = new FileInputStream( file ); | ||
| + | ||
| + return stream; | ||
| } | ||
| /** | ||
| * Sets name of the YAML file to parse. | ||
| * | ||
| - * @param filename File containing a YAML document. | ||
| + * @param inputFilename File containing a YAML document. | ||
| */ | ||
| @Option( name = "--input", | ||
| - required = true, metaVar = "filename.yaml", usage = "YAML filename" ) | ||
| - public void setFilename( final String filename ) { | ||
| - this.filename = filename; | ||
| + required = false, metaVar = "input.yaml", usage = "YAML filename" ) | ||
| + public void setInputFilename( final String inputFilename ) { | ||
| + this.inputFilename = inputFilename; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Returns the name of the YAML file to write. This is set by parsing the | ||
| + * command line. | ||
| + * | ||
| + * @return The filename to write. | ||
| + */ | ||
| + public String getOutputFilename() { | ||
| + return this.outputFilename; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Sets name of the file to export. | ||
| + * | ||
| + * @param inputFilename File containing a YAML document. | ||
| + */ | ||
| + @Option( name = "--output", | ||
| + metaVar = "output.json", | ||
| + usage = "Destination filename (XML, JSON, YAML)" ) | ||
| + public void setOutputFilename( final String inputFilename ) { | ||
| + this.inputFilename = inputFilename; | ||
| } | ||
| metaVar = DEFAULT_SEPERATOR, | ||
| usage = "Default variable expression separator" ) | ||
| - private void setSeparator( String separator ) { | ||
| + private void setSeparator( final String separator ) { | ||
| this.separator = separator; | ||
| } | ||
| @Option( name = "--quiet", | ||
| usage = "Disables writing to standard error" ) | ||
| - private void setLogging( boolean logging ) { | ||
| + private void setLogging( final boolean logging ) { | ||
| this.logging = logging; | ||
| } | ||
| @Option( name = "--variables", | ||
| usage = "Write variables to standard error" ) | ||
| - private void setShowVariables( boolean showVariables ) { | ||
| + private void setShowVariables( final boolean showVariables ) { | ||
| this.showVariables = showVariables; | ||
| + } | ||
| + | ||
| + private boolean isExportFormat( final FileType type ) { | ||
| + return this.exportFormat == type || type.matches( getOutputFilename() ); | ||
| + } | ||
| + | ||
| + /** | ||
| + * Answers whether to write the variables in JSON format. | ||
| + * | ||
| + * @return true Export in JSON format. | ||
| + */ | ||
| + public boolean isExportJson() { | ||
| + return isExportFormat( JSON ); | ||
| + } | ||
| + | ||
| + @Option( name = "--json", usage = "Force export in JSON format" ) | ||
| + private void setExportJson( final boolean exportJson ) { | ||
| + if( exportJson ) { | ||
| + this.exportFormat = JSON; | ||
| + } | ||
| } | ||
| /** | ||
| * Answers whether to write the variables in XML format. | ||
| * | ||
| - * @return false Don't write in XML format. | ||
| + * @return true Export in XML format. | ||
| */ | ||
| public boolean isExportXml() { | ||
| - return this.exportXml; | ||
| + return isExportFormat( XML ); | ||
| } | ||
| - @Option( name = "--xml", usage = "Export in XML format" ) | ||
| - private void setExportXml( boolean exportXml ) { | ||
| - this.exportXml = exportXml; | ||
| + @Option( name = "--xml", usage = "Force export in XML format" ) | ||
| + private void setExportXml( final boolean exportXml ) { | ||
| + if( exportXml ) { | ||
| + this.exportFormat = XML; | ||
| + } | ||
| + } | ||
| + | ||
| + /** | ||
| + * Answers whether to write the variables in YAML format. | ||
| + * | ||
| + * @return true Export in YAML format. | ||
| + */ | ||
| + public boolean isExportYaml() { | ||
| + return isExportFormat( YAML ); | ||
| + } | ||
| + | ||
| + @Option( name = "--yaml", usage = "Force export in YAML format" ) | ||
| + private void setExportYaml( final boolean exportYaml ) { | ||
| + if( exportYaml ) { | ||
| + this.exportFormat = YAML; | ||
| + } | ||
| } | ||
| /** | ||
| * Writes the message to standard error if logging is enabled. | ||
| * | ||
| * @param message Conditionally written to standard error. | ||
| */ | ||
| - public void log( String message ) { | ||
| + public void log( final String message ) { | ||
| if( isLogging() ) { | ||
| stderr( message ); | ||
| * @param message Written to standard error. | ||
| */ | ||
| - public void stderr( String message ) { | ||
| + public void stderr( final String message ) { | ||
| System.err.println( message ); | ||
| } | ||
| /** | ||
| * Shows the command line parameters. | ||
| * | ||
| * @param clp CLI option parser. | ||
| */ | ||
| - public void usage( CmdLineParser clp ) { | ||
| + public void usage( final CmdLineParser clp ) { | ||
| stderr( "Usage:" ); | ||
| clp.printUsage( System.err ); | ||
| + } | ||
| + | ||
| + /** | ||
| + * Returns true iff s is null or empty. | ||
| + * | ||
| + * @param s The string to check for content. | ||
| + * | ||
| + * @return true The string has no content (or is null). | ||
| + */ | ||
| + private boolean isEmpty( final String s ) { | ||
| + return s == null ? true : s.isEmpty(); | ||
| } | ||
| } | ||
| +/* | ||
| + * The MIT License | ||
| + * | ||
| + * Copyright 2017 White Magic Software, Ltd.. | ||
| + * | ||
| + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| + * of this software and associated documentation files (the "Software"), to deal | ||
| + * in the Software without restriction, including without limitation the rights | ||
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| + * copies of the Software, and to permit persons to whom the Software is | ||
| + * furnished to do so, subject to the following conditions: | ||
| + * | ||
| + * The above copyright notice and this permission notice shall be included in | ||
| + * all copies or substantial portions of the Software. | ||
| + * | ||
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| + * THE SOFTWARE. | ||
| + */ | ||
| +package com.whitemagicsoftware.yamlp; | ||
| + | ||
| +/** | ||
| + * List of supported export formats. | ||
| + * | ||
| + * @author White Magic Software, Ltd. | ||
| + */ | ||
| +public enum FileType { | ||
| + JSON( ".json", ".jsn" ), | ||
| + XML( ".xml" ), | ||
| + YAML( ".yaml", ".yml" ); | ||
| + | ||
| + private String[] extensions; | ||
| + | ||
| + private FileType( final String... extensions ) { | ||
| + setExtensions( extensions ); | ||
| + } | ||
| + | ||
| + /** | ||
| + * Returns true if the given filename matches this extension. | ||
| + * | ||
| + * @param filename The filename to compare against the extensions. | ||
| + * @return true The filename matches this type of file. | ||
| + */ | ||
| + public boolean matches( final String filename ) { | ||
| + boolean result = false; | ||
| + final String safeFilename = filename == null ? "" : filename.toLowerCase(); | ||
| + | ||
| + for( final String ext : getExtensions() ) { | ||
| + if( safeFilename.endsWith( ext ) ) { | ||
| + result = true; | ||
| + break; | ||
| + } | ||
| + } | ||
| + | ||
| + return result; | ||
| + } | ||
| + | ||
| + private void setExtensions( final String[] extensions ) { | ||
| + this.extensions = extensions; | ||
| + } | ||
| + | ||
| + private String[] getExtensions() { | ||
| + return extensions; | ||
| + } | ||
| +} | ||
| +/* | ||
| + * The MIT License | ||
| + * | ||
| + * Copyright 2017 White Magic Software, Ltd.. | ||
| + * | ||
| + * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| + * of this software and associated documentation files (the "Software"), to deal | ||
| + * in the Software without restriction, including without limitation the rights | ||
| + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| + * copies of the Software, and to permit persons to whom the Software is | ||
| + * furnished to do so, subject to the following conditions: | ||
| + * | ||
| + * The above copyright notice and this permission notice shall be included in | ||
| + * all copies or substantial portions of the Software. | ||
| + * | ||
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
| + * THE SOFTWARE. | ||
| + */ | ||
| +package com.whitemagicsoftware.yamlp.parser; | ||
| + | ||
| +import com.fasterxml.jackson.core.JsonGenerationException; | ||
| +import com.fasterxml.jackson.core.JsonGenerator; | ||
| +import com.fasterxml.jackson.databind.JsonSerializer; | ||
| +import com.fasterxml.jackson.databind.SerializerProvider; | ||
| +import java.io.IOException; | ||
| + | ||
| +/** | ||
| + * @author White Magic Software, Ltd. | ||
| + */ | ||
| +public class StringValueSerializer extends JsonSerializer<String> { | ||
| + | ||
| + private YamlParser parser; | ||
| + | ||
| + public StringValueSerializer( final YamlParser parser ) { | ||
| + setParser( parser ); | ||
| + } | ||
| + | ||
| + @Override | ||
| + public Class<String> handledType() { | ||
| + return String.class; | ||
| + } | ||
| + | ||
| + @Override | ||
| + public void serialize( final String value, | ||
| + final JsonGenerator jgen, | ||
| + final SerializerProvider provider ) | ||
| + throws IOException, JsonGenerationException { | ||
| + | ||
| + System.out.println( "debug" ); | ||
| + | ||
| + final String fieldName = jgen.getOutputContext().getCurrentName(); | ||
| + final String fieldValue = getParser().substitute( value ); | ||
| + | ||
| + jgen.writeStringField( fieldName, fieldValue ); | ||
| + } | ||
| + | ||
| + private YamlParser getParser() { | ||
| + return this.parser; | ||
| + } | ||
| + | ||
| + private void setParser( final YamlParser parser ) { | ||
| + this.parser = parser; | ||
| + } | ||
| +} | ||
| public void process() throws IOException { | ||
| preprocess(); | ||
| - process( getFilename() ); | ||
| + process( getInputStream() ); | ||
| postprocess(); | ||
| - } | ||
| - | ||
| - /** | ||
| - * Open a file and process its YAML contents. The underlying file stream is | ||
| - * closed on success or error. | ||
| - * | ||
| - * @param filename The file name to process. | ||
| - * | ||
| - * @throws IOException Could not read the file contents. | ||
| - */ | ||
| - public void process( final String filename ) throws IOException { | ||
| - process( new File( filename ) ); | ||
| } | ||
| /** | ||
| - * Open a file and process its YAML contents. The underlying file stream is | ||
| - * closed on success or error. | ||
| - * | ||
| - * @param file The file to process. | ||
| + * Opens the configured input stream (could be a file or standard input). | ||
| * | ||
| - * @throws IOException Could not read the file contents. | ||
| + * @throws IOException Could not open the stream for reading. | ||
| */ | ||
| - public void process( final File file ) throws IOException { | ||
| - try( final InputStream in = new FileInputStream( file ) ) { | ||
| - process( in ); | ||
| - } | ||
| + private InputStream getInputStream() throws IOException { | ||
| + return getConfiguration().getInputStream(); | ||
| } | ||
| private XmlFactory createXmlFactory() { | ||
| return new ResolverXmlFactory( this ); | ||
| - } | ||
| - | ||
| - private String getFilename() { | ||
| - return getConfiguration().getFilename(); | ||
| } | ||
| import com.whitemagicsoftware.yamlp.parser.YamlParser; | ||
| import java.io.IOException; | ||
| -import java.io.OutputStream; | ||
| +import javax.xml.stream.XMLStreamWriter; | ||
| /** | ||
| - * Responsible for | ||
| - * | ||
| * @author White Magic Software, Ltd. | ||
| */ | ||
| public final class ResolverXmlMapper extends XmlMapper { | ||
| - | ||
| - private static final long serialVersionUID = 1L; | ||
| private YamlParser yamlParser; | ||
| public ResolverXmlMapper( final YamlParser yamlParser ) { | ||
| setYamlParser( yamlParser ); | ||
| } | ||
| - /** | ||
| - * Writes the given value to the given writer. | ||
| - * | ||
| - * @param out The writer to receive content to include in an XML document. | ||
| - * @param value The value to write to the writer. | ||
| - * | ||
| - * @throws IOException Could not write to the given stream. | ||
| - */ | ||
| @Override | ||
| - public void writeValue( final OutputStream out, final Object value ) | ||
| + public void writeValue( final XMLStreamWriter output, final Object value ) | ||
| throws IOException { | ||
| - if( value instanceof String ) { | ||
| - super.writeValue( out, "resolve" + value.toString() ); | ||
| - } | ||
| - else { | ||
| - super.writeValue( out, value ); | ||
| - } | ||
| + super.writeValue( output, getYamlParser().substitute( value.toString() ) ); | ||
| } | ||
| - | ||
| + | ||
| /** | ||
| * Returns the YAML parser used when constructing this instance. |