/**
* Copyright (c) 2012 to original author or authors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
/**
*
*/
package org.sonatype.maven.polyglot.ruby;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Map;
import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.sonatype.maven.polyglot.ruby.ConfigVisitor.Config;
import org.sonatype.maven.polyglot.ruby.ConfigVisitor.ListItem;
import org.sonatype.maven.polyglot.ruby.ConfigVisitor.Node;
class RubyPrintWriter extends PrintWriter {
private static final String INDENT = " ";
private String current = "";
RubyPrintWriter(Writer writer) {
super(writer);
}
void inc() {
current += INDENT;
}
void dec() {
current = current.substring(INDENT.length());
}
public void print(String value) {
append(current).append(value);
}
void print(String name, String... values) {
if ( values.length == 1 && values[0] == null) {
return;
}
append( current ).append( name ).append( " " );
boolean first = true;
for (String value : values) {
if (value != null) {
if (first) {
first = false;
} else {
append(", ");
}
if(value.startsWith(":")){
append(value);
}
else {
append("'").append( escape( value ) ).append("'");
}
}
}
}
private String escape( String value )
{
return value.replaceAll( "([^\\\\])'", "$1\\\\'" );
}
public void println(String name) {
print(name);
println();
}
void println(String name, String... values) {
if ( values.length == 1 && values[0] == null )
{
return;
}
print( name, values );
println();
}
void printWithOptions( String prefix, Map<String, Object> options, String... args ){
printWithOptions( prefix, options, null, args );
}
void printWithOptions( String prefix, Map<String, Object> options, boolean newLine, String... args ){
printWithOptions( prefix, options, null, newLine, args );
}
void printWithOptions( String prefix, Map<String, Object> options, Object config, String... args)
{
printWithOptions( prefix, options, config, true, args );
}
void printWithOptions( String prefix, Map<String, Object> options, Object config, boolean newLine, String... args)
{
if ( !options.isEmpty() || config != null )
{
prefix += "(";
print( prefix, args );
String indent = prefix.replaceAll( ".", " " ) + ' ';
boolean first = args.length == 0;
for( Map.Entry<String, Object> item: options.entrySet() )
{
if ( first )
{
first = false;
}
else
{
append(",").println();
print( indent );
}
appendName( item.getKey() ).append( " => " );
if ( item.getValue() instanceof String )
{
append( "'" ).append( escape( item.getValue().toString() ) ).append( "'" );
}
else {
append( item.getValue().toString() );
}
}
if ( config != null )
{
printConfiguration( indent, config );
if (newLine )
{
println();
}
}
else
{
append( " )" );
if (newLine )
{
println();
}
}
}
else
{
println( prefix, args );
}
}
void printConfiguration( String indent, Object config ) {
if (config != null ){
Xpp3Dom configuration = (Xpp3Dom) config;
if (configuration.getChildCount() != 0) {
append(",");
println();
ConfigVisitor visitor = new ConfigVisitor();
visitor.visit( new Node( configuration ) );
printHashConfig( indent, visitor.config.map );
}
append( " )");
}
}
void printHashConfig(String indent, Map<String, Config> base) {
printHashConfig( indent, base, false );
}
RubyPrintWriter appendName( String name )
{
if ( name.matches( "^[a-zA-Z_]*$" ) )
{
append( ":" ).append( name );
}
else
{
append( "'" ).append( escape( name ) ).append( "'" );
}
return this;
}
void printHashConfig(String indent, Map<String, Config> base, boolean skipFirst ) {
boolean first = true;
for( Map.Entry<String, Config> entry: base.entrySet() )
{
if ( first )
{
first = false;
if ( !skipFirst )
{
print( indent );
}
}
else
{
append( "," ).println();
print( indent );
}
Config config = entry.getValue();
switch ( config.type )
{
case SINGLE:
append( "'" ).append( entry.getKey() ).append( "' => " );
if ( config.value != null )
{
append( " '" ).append( escape( config.value ) ).append( "'" );
}
else
{
append( "nil" );
}
break;
case MULTI:
append( "'" ).append( entry.getKey() ).append( "' => [" );
String ind = indent + " " + entry.getKey().replaceAll( ".", " " );
int count = config.stringList.size();
for (int j = 0; j < count; )
{
String c = config.stringList.get(j);
if ( c != null )
{
append( " '" ).append( escape( c ) ).append( "'" );
}
else
{
append( "nil" );
}
if( ++j < count )
{
append( "," );
println();
print( ind );
}
}
append( " ]" );
break;
case MIXED:
append( "'" ).append( entry.getKey() ).append( "' => [" );
ind = indent + " " + entry.getKey().replaceAll( ".", " " );
count = config.list.size();
for (int j = 0; j < count; )
{
ListItem c = config.list.get(j);
if ( c.isXml() )
{
append( " xml( '" ).append( escape( c.xml ) ).append( "' )" );
}
else
{
append( " '" ).append( escape( c.value ) ).append( "'" );
}
if( ++j < count )
{
append( "," );
println();
print( ind );
}
}
append( " ]" );
break;
case MAPS:
append( "'" ).append( entry.getKey() ).append( "' => [" );
ind = indent + " " + entry.getKey().replaceAll( ".", " " );
count = config.mapList.size();
for (int j = 0; j < count; )
{
Map<String, Config> c = config.mapList.get(j);
append( " { " );
printHashConfig( " " + ind + INDENT, c, true );
append( " }" );
if( ++j < count )
{
append( "," );
println();
print( ind );
}
}
append( " ]" );
break;
case MAP:
append( "'" ).append( entry.getKey() ).append( "' => {" ).println();
printHashConfig( indent + INDENT,
entry.getValue().map, false );
println();
print( indent );
append( "}" );
break;
default:
}
}
}
void printStartBlock(String name) {
print(name);
printStartBlock();
}
void printStartBlock(String name, String... values) {
printStartBlock( name, null, values );
}
void printStartBlock(String name, Map<String, Object> options, String... values) {
if ( options != null )
{
printWithOptions( name, options, false, values );
}
else
{
print( name, values );
}
printStartBlock();
}
void printStartBlock() {
append(" do");
println();
inc();
}
void printEndBlock() {
dec();
append(current).append("end");
println();
}
}