/**
* Copyright (c) 2011 Cloudsmith Inc. and other contributors, as listed below.
* 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
*
* Contributors:
* Cloudsmith
*
*/
package org.cloudsmith.geppetto.forge.impl;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.cloudsmith.geppetto.common.os.StreamUtil;
import org.cloudsmith.geppetto.forge.ERB;
import org.cloudsmith.geppetto.forge.v2.model.Metadata;
import com.google.inject.Singleton;
@Singleton
class ERBImpl implements ERB {
private static Pattern expressionPattern = Pattern.compile("\\A\\s*metadata\\.([A-Za-z0-9_]+)\\s*\\z");
private void consumeComment(Reader input) throws IOException {
consumeUntilEndMark(input);
}
private String consumeUntilEndMark(Reader input) throws IOException {
StringBuilder bld = new StringBuilder();
int n1;
while((n1 = input.read()) >= 0) {
if(n1 == '%') {
int n2 = input.read();
if(n2 == '>')
return bld.toString();
if(n2 == '%') {
int n3 = input.read();
if(n3 == '>') {
bld.append("%>");
continue;
}
}
bld.append('%');
bld.append((char) n2);
continue;
}
bld.append((char) n1);
}
throw new IOException("Unbalanced construct. Missing end %>");
}
@Override
public void generate(Metadata metadata, File template, File dest) throws IOException {
BufferedWriter output = new BufferedWriter(new FileWriter(dest));
try {
BufferedReader input = new BufferedReader(new FileReader(template), 0x1000);
try {
generate(metadata, input, output);
}
finally {
StreamUtil.close(input);
}
}
finally {
StreamUtil.close(output);
}
}
@Override
public void generate(Metadata metadata, Reader input, Writer dest) throws IOException {
int n1;
while((n1 = input.read()) >= 0) {
if(n1 == '<') {
int n2 = input.read();
if(n2 == '%') {
int n3 = input.read();
if(n3 == '#')
consumeComment(input);
else if(n3 == '=')
handleExpression(metadata, input, dest);
else if(n3 == '%')
dest.write("<%");
else
handleCode(input, dest);
}
else {
dest.write(n1);
dest.write(n2);
}
}
else if(n1 == '%') {
int n2 = input.read();
if(n2 == '%') {
int n3 = input.read();
if(n3 == '>') {
dest.write("%>");
}
else {
dest.write(n1);
dest.write(n2);
dest.write(n3);
}
}
else {
dest.write(n1);
dest.write(n2);
}
}
else
dest.write(n1);
}
}
private void handleCode(Reader input, Writer dest) {
throw new UnsupportedOperationException("Ruby code not handled");
}
private void handleExpression(Metadata metadata, Reader input, Writer dest) throws IOException {
String expr = consumeUntilEndMark(input);
Matcher m = expressionPattern.matcher(expr);
if(!m.matches())
throw new UnsupportedOperationException("This very limited evaluator does not understand the expression: " +
expr);
String key = m.group(1);
if("full_name".equals(key) && metadata.getName() != null)
dest.write(metadata.getName().toString());
else if("name".equals(key) && metadata.getName() != null)
dest.write(metadata.getName().getName());
else if("user".equals(key) && metadata.getName() != null)
dest.write(metadata.getName().getOwner());
else if("author".equals(key) && metadata.getAuthor() != null)
dest.write(metadata.getAuthor());
else if("description".equals(key) && metadata.getDescription() != null)
dest.write(metadata.getDescription());
else if("license".equals(key) && metadata.getLicense() != null)
dest.write(metadata.getLicense());
else if("project_page".equals(key) && metadata.getProjectPage() != null)
dest.write(metadata.getProjectPage());
else if("source".equals(key) && metadata.getSource() != null)
dest.write(metadata.getSource());
else if("summary".equals(key) && metadata.getSummary() != null)
dest.write(metadata.getSummary());
else if("version".equals(key) && metadata.getVersion() != null)
dest.write(metadata.getVersion().toString());
}
}