package org.simpleframework.xml.util;
import java.io.File;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class LanguageConverter extends Replace {
private static final List<Class<? extends ConversionPhase>> STAGE_ONE = new ArrayList<Class<? extends ConversionPhase>>();
private static final List<Class<? extends SubstitutionPhase>> STAGE_TWO = new ArrayList<Class<? extends SubstitutionPhase>>();
private static final Map<String, String> NAMESPACE = new LinkedHashMap<String, String>();
private static final Map<String, String> USING = new LinkedHashMap<String, String>();
private static final Map<String, String> FILES = new LinkedHashMap<String, String>();
private static Map<String, String> IMPORT_TO_USING = new LinkedHashMap<String, String>();
private static final String INDENT = " ";
static {
IMPORT_TO_USING.put("org.simpleframework.xml.core.*", "using SimpleFramework.Xml.Core;");
IMPORT_TO_USING.put("org.simpleframework.xml.convert.*", "using SimpleFramework.Xml.Convert;");
IMPORT_TO_USING.put("org.simpleframework.xml.strategy.*", "using SimpleFramework.Xml.Strategy;");
IMPORT_TO_USING.put("org.simpleframework.xml.filter.*", "using SimpleFramework.Xml.Filter;");
IMPORT_TO_USING.put("org.simpleframework.xml.stream.*", "using SimpleFramework.Xml.Stream;");
IMPORT_TO_USING.put("org.simpleframework.xml.transform.*", "using SimpleFramework.Xml.Transform;");
IMPORT_TO_USING.put("org.simpleframework.xml.util.*", "using SimpleFramework.Xml.Util;");
IMPORT_TO_USING.put("org.simpleframework.xml.util.*", "using SimpleFramework.Xml;");
IMPORT_TO_USING.put("java.util.*","using System.Collections.Generic;");
IMPORT_TO_USING.put("junit.framework.*", "using SimpleFramework.Xml;");
}
static {
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\test\\java\\org\\simpleframework\\xml", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\test\\java\\org\\simpleframework\\xml\\core", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Core");
//FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\test\\java\\org\\simpleframework\\xml\\filter", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Filter");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\test\\java\\org\\simpleframework\\xml\\strategy", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Strategy");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\test\\java\\org\\simpleframework\\xml\\stream", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Stream");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\test\\java\\org\\simpleframework\\xml\\convert", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Convert");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\test\\java\\org\\simpleframework\\xml\\transform", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Transform");
//FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\test\\java\\org\\simpleframework\\xml\\util", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Util");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\main\\java\\org\\simpleframework\\xml", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\main\\java\\org\\simpleframework\\xml\\core", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Core");
//FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\main\\java\\org\\simpleframework\\xml\\filter", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Filter");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\main\\java\\org\\simpleframework\\xml\\strategy", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Strategy");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\main\\java\\org\\simpleframework\\xml\\stream", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Stream");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\main\\java\\org\\simpleframework\\xml\\convert", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Convert");
FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\main\\java\\org\\simpleframework\\xml\\transform", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Transform");
//FILES.put("C:\\Users\\niall\\Workspace\\xml\\src\\main\\java\\org\\simpleframework\\xml\\util", "C:\\Users\\niall\\Workspace\\SimpleFramework\\SimpleFramework\\SimpleFramework\\src\\main\\Xml\\Util");
}
static {
USING.put("import org.simpleframework.xml.convert.*","using SimpleFramework.Xml.Util;");
USING.put("import org.simpleframework.xml.filter.*", "using SimpleFramework.Xml.Filter;");
USING.put("import org.simpleframework.xml.strategy.*", "using SimpleFramework.Xml.Strategy;");
USING.put("import org.simpleframework.xml.core.*","using SimpleFramework.Xml.Core;");
USING.put("import org.simpleframework.xml.util.*", "using SimpleFramework.Xml.Util;");
USING.put("import org.simpleframework.xml.stream.*","using SimpleFramework.Xml.Stream;");
USING.put("import org.simpleframework.xml.*","using SimpleFramework.Xml;");
USING.put("import java.util.*","using System.Collections.Generic;");
}
static {
NAMESPACE.put("package org.simpleframework.xml;","namespace SimpleFramework.Xml {");
NAMESPACE.put("package org.simpleframework.xml.convert;","namespace SimpleFramework.Xml.Util {");
NAMESPACE.put("package org.simpleframework.xml.filter;", "namespace SimpleFramework.Xml.Filter {");
NAMESPACE.put("package org.simpleframework.xml.strategy;", "namespace SimpleFramework.Xml.Strategy {");
NAMESPACE.put("package org.simpleframework.xml.core;","namespace SimpleFramework.Xml.Core {");
NAMESPACE.put("package org.simpleframework.xml.util;", "namespace SimpleFramework.Xml.Util {");
NAMESPACE.put("package org.simpleframework.xml.stream;","namespace SimpleFramework.Xml.Stream {");
}
static {
STAGE_ONE.add(CanonicalizeFile.class);
STAGE_ONE.add(DefineType.class);
STAGE_ONE.add(PopulateUsing.class);
STAGE_ONE.add(StripImports.class);
STAGE_ONE.add(AddUsing.class);
STAGE_ONE.add(CreateNamespace.class);
STAGE_ONE.add(GetFields.class);
STAGE_ONE.add(ReplaceComments.class);
STAGE_ONE.add(ReplaceDocumentation.class);
STAGE_ONE.add(ReplaceKeyWords.class);
STAGE_ONE.add(ConvertAnnotationAttributes.class);
STAGE_ONE.add(ReplaceMethodConventions.class);
STAGE_ONE.add(StripCrap.class);
STAGE_ONE.add(ReplaceLicense.class);
STAGE_ONE.add(SubstituteAnnotations.class);
STAGE_ONE.add(SetAnnotationAttributes.class);
STAGE_ONE.add(ConvertClassBeanMethods.class);
STAGE_ONE.add(ReplaceAnnotations.class);
}
static {
STAGE_TWO.add(SubstituteMethods.class);
STAGE_TWO.add(StripPublicFromInterfaces.class);
}
public static void main(String list[]) throws Exception {
Set<String> filesDone = new HashSet<String>();
SourceProject project = new SourceProject();
for(String from : FILES.keySet()) {
List<File> files = getFiles(new File(from), false);
String to = FILES.get(from);
for(File file : files) {
File result = new File(to, file.getName().replaceAll("\\.java", ".cs"));
if(filesDone.contains(file.getCanonicalPath())) {
throw new IllegalStateException("File '"+file.getCanonicalPath()+"' has already been examined");
}
if(filesDone.contains(result.getCanonicalPath())) {
throw new IllegalStateException("Result '"+result.getCanonicalPath()+"' has already been written");
}
filesDone.add(file.getCanonicalPath());
filesDone.add(result.getCanonicalPath());
SourceDetails details = new SourceDetails(file, result);
String text = getFile(file);
details.setText(text);
for(Class<? extends ConversionPhase> phaseType : STAGE_ONE) {
Constructor<? extends ConversionPhase> factory = phaseType.getDeclaredConstructor();
if(!factory.isAccessible()) {
factory.setAccessible(true);
}
ConversionPhase phase = factory.newInstance();
details.setText(phase.convert(details.getText(), details));
}
project.addSource(details);
}
}
for(SourceDetails details : project.getDetails()) {
for(Class<? extends SubstitutionPhase> phaseType : STAGE_TWO) {
Constructor<? extends SubstitutionPhase> factory = phaseType.getDeclaredConstructor();
if(!factory.isAccessible()) {
factory.setAccessible(true);
}
SubstitutionPhase phase = factory.newInstance();
details.setText(phase.convert(details.getText(), details, project));
}
}
List<String> newFiles = new ArrayList<String>();
for(SourceDetails details : project.getDetails()) {
File saveAs = details.getDestination();
save(saveAs, details.getText());
if(!filesDone.contains(saveAs.getCanonicalPath())) {
throw new IllegalStateException("Can not save to '"+saveAs.getCanonicalPath()+"' it has not a valid path");
}
newFiles.add(saveAs.getCanonicalPath().replaceAll("^.*src", "src"));
}
for(String entry : newFiles) {
System.out.println(" <Compile Include=\""+entry+"\"/>");
}
}
private static String convertMethod(String originalMethod, MethodType type) {
if(type == null || type == MethodType.NORMAL) {
if(originalMethod != null && !Character.isUpperCase(originalMethod.charAt(0))){
StringBuilder builder = new StringBuilder(originalMethod.length());
char first = originalMethod.charAt(0);
builder.append(Character.toUpperCase(first));
builder.append(originalMethod.substring(1));
return builder.toString();
}
} else if(type == MethodType.GET) {
if(originalMethod != null){
return originalMethod.substring(3);
}
} else if(type == MethodType.SET) {
if(originalMethod != null){
return originalMethod.substring(3);
}
}
return originalMethod;
}
private static enum SourceType {
ANNOTATION,
INTERFACE,
CLASS,
ENUM
}
private static class SourceDetails {
private Set<String> using = new TreeSet<String>();
private Map<String, String> attributes = new LinkedHashMap<String, String>();
private Map<String, String> fields = new LinkedHashMap<String, String>();
private List<String> imports = new ArrayList<String>();
private List<MethodSignature> methods = new ArrayList<MethodSignature>();
private String packageName;
private SourceType type;
private String name;
private File destination;
private File source;
private String text;
public SourceDetails(File source, File destination) {
this.using.add("using System;");
this.destination = destination;
this.source = source;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public File getDestination() {
return destination;
}
public File getSource() {
return source;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPackage() {
return packageName;
}
public void setPackage(String packageName) {
this.packageName = packageName;
}
public String getFullyQualifiedName() {
return String.format("%s.%s", packageName, name);
}
public SourceType getType() {
return type;
}
public void setType(SourceType type) {
this.type = type;
}
public Set<String> getUsing() {
return using;
}
public void addMethod(MethodSignature method) {
methods.add(method);
}
public List<MethodSignature> getMethods() {
return methods;
}
public void addImport(String importClass) {
for(String pattern : IMPORT_TO_USING.keySet()) {
if(importClass.matches(pattern)) {
using.add(IMPORT_TO_USING.get(pattern));
}
}
imports.add(importClass);
}
public List<String> getImports() {
return imports;
}
public Map<String, String> getAttributes() {
return attributes;
}
public void addAttribute(String type, String attribute) {
attributes.put(attribute, type);
}
public void addUsing(String usingValue) {
using.add(usingValue);
}
public Map<String, String> getFields() {
return fields;
}
public void addField(String name, String type) {
fields.put(name, type);
}
}
private static enum MethodType {
GET,
SET,
NORMAL
}
private static class MethodSignature {
private final String name;
private final String value;
private final MethodType type;
public MethodSignature(String name, MethodType type, String value) {
this.name = name;
this.type = type;
this.value = value;
}
public String toString() {
return String.format("[%s][%s][%s]", name, type, value);
}
}
private static class SourceProject {
private Map<String, List<SourceDetails>> packages = new HashMap<String, List<SourceDetails>>();
private Map<String, SourceDetails> names = new HashMap<String, SourceDetails>();
private List<SourceDetails> all = new ArrayList<SourceDetails>();
public List<SourceDetails> getDetails() {
return all;
}
public void addSource(SourceDetails details) {
String packageName = details.getPackage();
String name = details.getName();
List<SourceDetails> packageFiles = packages.get(packageName);
if(packageFiles == null) {
packageFiles = new ArrayList<SourceDetails>();
packages.put(packageName, packageFiles);
}
packageFiles.add(details);
all.add(details);
names.put(name, details);
}
public SourceDetails getDetails(String name) {
return names.get(name);
}
}
private static abstract class SubstitutionPhase {
public Map<String, String> calculateSubstututions(SourceDetails details, SourceProject project) throws Exception {
Map<String, String> substitutes = new HashMap<String, String>();
for(String field : details.getFields().keySet()) {
String type = details.getFields().get(field);
SourceDetails fieldDetails = project.getDetails(type);
if(fieldDetails != null) {
populateFrom(fieldDetails, field, substitutes);
}
}
populateFrom(details, null, substitutes);
return substitutes;
}
private void populateFrom(SourceDetails details, String field, Map<String, String> substitutes) {
List<MethodSignature> methods = details.getMethods();
for(MethodSignature originalMethod : details.getMethods()) {
if(originalMethod.type == MethodType.GET) {
substitutes.put(originalMethod.name+"\\(\\)", convertMethod(originalMethod.name, originalMethod.type));
} else if(originalMethod.type == MethodType.SET) {
substitutes.put(originalMethod.name+"\\([a-zA-Z\\s]+\\)", convertMethod(originalMethod.name, originalMethod.type) + " = "+originalMethod.value);
} else {
substitutes.put(originalMethod.name+"\\(", convertMethod(originalMethod.name, MethodType.NORMAL)+"\\(");
}
}
if(field != null && !field.equals("")) {
for(MethodSignature originalMethod : methods) {
String originalToken = String.format("%s.%s", field, originalMethod.name);
if(originalMethod.type == MethodType.GET) {
String token = String.format("%s.%s", field, convertMethod(originalMethod.name, originalMethod.type));
substitutes.put(originalToken+"\\(\\)", token);
} else if(originalMethod.type == MethodType.SET) {
String token = String.format("%s.%s = %s", field, convertMethod(originalMethod.name, originalMethod.type), originalMethod.value);
substitutes.put(originalToken+"\\([a-zA-Z\\s]+\\)", token);
} else {
String token = String.format("%s.%s\\(", field, convertMethod(originalMethod.name, MethodType.NORMAL));
substitutes.put(originalToken+"\\(", token);
}
}
}
}
public abstract String convert(String source, SourceDetails details, SourceProject project) throws Exception;
}
public static class SubstituteMethods extends SubstitutionPhase {
public String convert(String source, SourceDetails details, SourceProject project) throws Exception {
List<String> lines = stripLines(source);
Map<String, String> substitutions = calculateSubstututions(details, project);
StringWriter writer = new StringWriter();
for(String line : lines) {
for(String substitute : substitutions.keySet()) {
line = line.replaceAll(substitute, substitutions.get(substitute));
}
writer.append(line);
writer.append("\n");
}
return writer.toString();
}
}
public static class StripPublicFromInterfaces extends SubstitutionPhase {
public String convert(String source, SourceDetails details, SourceProject project) throws Exception {
if(details.getType() == SourceType.INTERFACE) {
Pattern pattern = Pattern.compile("^(\\s+)public\\s+(.*\\)\\s*;.*$)");
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
for(String line : lines) {
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
String indent = matcher.group(1);
String remainder = matcher.group(2);
writer.append(indent);
writer.append(remainder);
writer.append("\n");
} else {
writer.append(line);
writer.append("\n");
}
}
return writer.toString();
}
return source;
}
}
private static interface ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception;
}
public static class CanonicalizeFile implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
return source.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
}
}
public static class GetFields implements ConversionPhase {
private static final List<String> MODIFIERS = new ArrayList<String>();
static {
MODIFIERS.add("private final");
MODIFIERS.add("private");
MODIFIERS.add("protected");
MODIFIERS.add("protected final");
}
public String convert(String source, SourceDetails details) throws Exception {
List<Pattern> patterns = new ArrayList<Pattern>();
for(String modifier : MODIFIERS) {
patterns.add(Pattern.compile("^\\s+"+modifier+"\\s+([a-zA-Z]+)\\s+([a-zA-Z]+)\\s*;.*$"));
}
List<String> lines = stripLines(source);
for(String line : lines) {
for(Pattern pattern : patterns) {
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
String type = matcher.group(1);
String name = matcher.group(2);
details.addField(name, type);
break;
}
}
}
return source;
}
}
public static class ConvertAnnotationAttributes implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
Pattern pattern = Pattern.compile("^(\\s+)public\\s+(.*)\\s+([a-zA-Z]+)\\(\\)\\s+default\\s+.+;.*$");
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
for(String line : lines) {
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
String indent = matcher.group(1);
String type = matcher.group(2);
String method = matcher.group(3);
String attribute = method.toLowerCase();
details.addAttribute(type, attribute);
writer.append(indent);
writer.append("public ");
writer.append(type);
writer.append(" ");
writer.append(convertMethod(method, MethodType.NORMAL));
writer.append(" {\n");
writer.append(indent);
writer.append(" get {\n");
writer.append(indent);
writer.append(" return ").append(attribute).append(";\n");
writer.append(indent);
writer.append(" }\n");
writer.append(indent);
writer.append(" set {\n");
writer.append(indent);
writer.append(" ").append(attribute).append(" = value;\n");
writer.append(indent);
writer.append(" }\n");
writer.append(indent);
writer.append("}\n");
} else {
writer.append(line);
writer.append("\n");
}
}
return writer.toString();
}
}
private static class ConvertClassBeanMethods implements ConversionPhase {
private static final Pattern RIGHT_BRACE = Pattern.compile("^.*\\{.*$");
private static final Pattern LEFT_BRACE = Pattern.compile("^.*\\}.*$");
private static final List<String> TYPE_MODIFIERS = new ArrayList<String>();
private static final List<String> METHOD_MODIFIERS = new ArrayList<String>();
static {
TYPE_MODIFIERS.add("class");
TYPE_MODIFIERS.add("public class");
TYPE_MODIFIERS.add("abstract class");
TYPE_MODIFIERS.add("static class");
TYPE_MODIFIERS.add("sealed class");
TYPE_MODIFIERS.add("private static abstract class");
TYPE_MODIFIERS.add("private sealed class");
TYPE_MODIFIERS.add("private class");
TYPE_MODIFIERS.add("private static sealed class");
TYPE_MODIFIERS.add("private static class");
TYPE_MODIFIERS.add("public sealed class");
TYPE_MODIFIERS.add("public static sealed class");
TYPE_MODIFIERS.add("public static class");
TYPE_MODIFIERS.add("protected sealed class");
TYPE_MODIFIERS.add("protected class");
TYPE_MODIFIERS.add("protected static sealed class");
TYPE_MODIFIERS.add("protected static class");
TYPE_MODIFIERS.add("static sealed class");
}
static {
METHOD_MODIFIERS.add("public abstract");
METHOD_MODIFIERS.add("public");
METHOD_MODIFIERS.add("protected abstract");
METHOD_MODIFIERS.add("protected");
METHOD_MODIFIERS.add("private");
}
private Matcher match(String line, MethodType type) {
for(String modifier : METHOD_MODIFIERS) {
if(type == MethodType.GET) {
Pattern pattern = Pattern.compile("^(\\s+)"+modifier+"\\s+(.*)\\s+Get([a-zA-Z]+)\\(\\)\\s*.*$");
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
return matcher;
}
} else if(type == MethodType.SET) {
Pattern pattern = Pattern.compile("^(\\s+)"+modifier+"\\s+void\\s+Set([a-zA-Z]+)\\((.*)\\s+([a-zA-Z]+)\\)\\s*.*$");
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
return matcher;
}
}
}
return null;
}
public String convert(String source, SourceDetails details) throws Exception {
if(details.getType() == SourceType.CLASS || details.getType() == SourceType.INTERFACE) {
List<String> lines = stripLines(source);
PropertyMap properties = new PropertyMap(details);
StringWriter writer = new StringWriter();
String qualifier = "";
extract(source, details, properties);
for(int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
qualifier += qualifier(line);
Matcher getter = match(line, MethodType.GET);
if(getter != null) {
String name = getter.group(3);
String fullName = qualifier+"."+name;
Property property = properties.getProperty(fullName);
if(!property.isGettable()) {
throw new IllegalStateException("The line '"+line+"' was not extracted from "+details.getFullyQualifiedName());
}
if(!property.isDone()) {
write(details, property.get().indent, property, writer);
}
String indent = property.get().indent;
int indentLength = indent.length();
for(int j = 0; j <= property.get().lineCount; j++) {
line = lines.get(i++);
writer.append(indent);
writer.append("//");
if(line.length() < indentLength) {
throw new IllegalStateException("Line '"+line+"' is out of place in " + writer.toString());
}
writer.append(line.substring(indentLength));
writer.append("\n");
}
} else {
Matcher setter = match(line, MethodType.SET);
if(setter != null) {
String name = setter.group(2);
String fullName = qualifier+"."+name;
Property property = properties.getProperty(fullName);
if(!property.isSettable()) {
throw new IllegalStateException("The line '"+line+"' was not extracted from "+details.getFullyQualifiedName());
}
if(!property.isDone()) {
write(details, property.set().indent, property, writer);
}
if(property.set() == null) {
throw new IllegalStateException("Can not find setter '"+fullName+"' from line '"+line+"' from "+writer.toString());
}
String indent = property.set().indent;
int indentLength = indent.length();
for(int j = 0; j <= property.set().lineCount; j++) {
line = lines.get(i++);
writer.append(indent);
writer.append("//");
if(line.length() < indentLength) {
throw new IllegalStateException("Line '"+line+"' is out of place in " + writer.toString());
}
writer.append(line.substring(indentLength));
writer.append("\n");
}
} else {
writer.append(line);
writer.append("\n");
}
}
}
return writer.toString();
}
return source;
}
private void write(SourceDetails details, String indent, Property property, StringWriter writer) throws Exception {
if(property.verify()) {
if(property.get != null) {
writer.append(property.get.indent);
writer.append("public ");
if(property.get.isAbstract && details.getType() == SourceType.CLASS) {
writer.append("abstract ");
}
writer.append(property.get.type);
writer.append(" ");
writer.append(property.get.name);
writer.append(" {\n");
writer.append(property.get.indent);
if(property.get.isAbstract) {
writer.append(" get;\n");
} else {
writer.append(" get {\n");
List<String> lines = stripLines(property.get.content);
for(String line : lines) {
writer.append(" ");
writer.append(line);
writer.append("\n");
}
}
}
if(property.set != null) {
if(property.get == null) {
writer.append(property.set.indent);
writer.append("public ");
if(property.set.isAbstract && details.getType() == SourceType.CLASS) {
writer.append("abstract ");
}
writer.append(property.set.type);
writer.append(" ");
writer.append(property.set.name);
writer.append(" {\n");
}
writer.append(property.set.indent);
if(property.set.isAbstract) {
writer.append(" set;\n");
} else {
writer.append(" set {\n");
List<String> lines = stripLines(property.set.content);
for(String line : lines) {
writer.append(" ");
writer.append(line);
writer.append("\n");
}
}
}
writer.append(indent);
writer.append("}");
writer.append("\n");
}
property.done();
}
private void extract(String source, SourceDetails details, PropertyMap properties) throws Exception {
List<String> lines = stripLines(source);
String qualifier = "";
for(int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
qualifier += qualifier(line);
Matcher getter = match(line, MethodType.GET);
if(getter != null) {
String indent = getter.group(1);
String type = getter.group(2);
String name = getter.group(3);
StringBuilder writer = new StringBuilder();
boolean isAbstract = false;
int lineCount = 0;
int braces = 0;
i++;
if(!line.matches(".*;\\s*$") && !line.matches(".*abstract.*")) { // abstract ends in ;
for(; braces >= 0 && i < lines.size(); i++) {
line = lines.get(i);
Matcher right = RIGHT_BRACE.matcher(line);
if(right.matches()) {
braces++;
}
Matcher left = LEFT_BRACE.matcher(line);
if(left.matches()) {
braces--;
}
writer.append(line);
writer.append("\n");
lineCount++;
}
} else {
isAbstract = true;
}
String fullName = qualifier+"."+name;
if(properties.getProperty(fullName) != null && properties.getProperty(fullName).isGettable()) {
throw new IllegalStateException("The property '"+fullName+"' is defined twice in "+details.getFullyQualifiedName()+" on line '"+line+"' in "+writer.toString());
}
properties.addGetProperty(fullName, new MethodDetail(name, type, indent, writer.toString(), lineCount, isAbstract));
} else {
Matcher setter = match(line, MethodType.SET);
if(setter != null) {
String indent = setter.group(1);
String name = setter.group(2);
String type = setter.group(3);
String value = setter.group(4);
StringBuilder writer = new StringBuilder();
boolean isAbstract = false;
int lineCount = 0;
int braces = 0;
i++;
if(!line.matches(".*;\\s*$") && !line.matches(".*abstract.*")) { // abstract ends in ;
for(; braces >= 0 && i < lines.size(); i++) {
line = lines.get(i);
Matcher right = RIGHT_BRACE.matcher(line);
if(right.matches()) {
braces++;
}
Matcher left = LEFT_BRACE.matcher(line);
if(left.matches()) {
braces--;
}
writer.append(line);
writer.append("\n");
lineCount++;
}
} else {
isAbstract = true;
}
String fullName = qualifier+"."+name;
if(properties.getProperty(fullName) != null && properties.getProperty(fullName).isSettable()) {
throw new IllegalStateException("The property '"+fullName+"' is defined twice in "+details.getFullyQualifiedName());
}
String content = writer.toString();
content = content.replaceAll(" value\\)", " _value)");
content = content.replaceAll(" value;", " _value;");
content = content.replaceAll(" value=", " _value=\\");
content = content.replaceAll(" value\\.", " _value.");
content = content.replaceAll("\\(value\\)", "(_value)");
content = content.replaceAll("\\(value\\.", "(_value.");
content = content.replaceAll("=value;", "=_value;");
content = content.replaceAll("=value\\.", "=_value.");
content = content.replaceAll(" "+value+"\\)", " value)");
content = content.replaceAll(" "+value+";", " value;");
content = content.replaceAll(" "+value+"=", " value=\\");
content = content.replaceAll(" "+value+"\\.", " value.");
content = content.replaceAll("\\("+value+"\\)", "(value)");
content = content.replaceAll("\\("+value+"\\.", "(value.");
content = content.replaceAll("="+value+";", "=value;");
content = content.replaceAll("="+value+"\\.", "=value.");
properties.addSetProperty(fullName, new MethodDetail(name, type, indent, content, lineCount, isAbstract));
}
}
}
}
private String qualifier(String line) {
for(String modifier : TYPE_MODIFIERS) {
Pattern pattern = Pattern.compile("^\\s*"+modifier+"\\s+([a-zA-Z]+).*$");
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
return "."+matcher.group(1);
}
}
return "";
}
private class MethodDetail {
public final String type;
public final String name;
public final String indent;
public final String content;
public final int lineCount;
public final boolean isAbstract;
public MethodDetail(String name, String type, String indent, String content, int lineCount, boolean isAbstract) {
this.name = name;
this.type = type;
this.indent = indent;
this.content = content;
this.lineCount = lineCount;
this.isAbstract = isAbstract;
}
public String toString() {
return String.format("[%s][%s][%s]", name, type, isAbstract);
}
}
private class PropertyMap {
private Map<String, Property> properties = new HashMap<String, Property>();
private SourceDetails details;
public PropertyMap(SourceDetails details) {
this.details = details;
}
public Property getProperty(String name) {
return properties.get(name);
}
public void addSetProperty(String name, MethodDetail detail) {
Property property = properties.get(name);
if(property == null) {
property = new Property();
properties.put(name, property);
}
if(property.set() != null) {
throw new IllegalStateException("The property '"+name+"' is defined twice in "+details.getFullyQualifiedName());
}
if(detail == null) {
throw new IllegalStateException("Can not set a null property");
}
property.addSetMethod(detail);
}
public void addGetProperty(String name, MethodDetail detail) {
Property property = properties.get(name);
if(property == null) {
property = new Property();
properties.put(name, property);
}
if(property.get() != null) {
throw new IllegalStateException("The property '"+name+"' is defined twice in "+details.getFullyQualifiedName());
}
if(detail == null) {
throw new IllegalStateException("Can not set a null property");
}
property.addGetMethod(detail);
}
}
private class Property {
private MethodDetail get;
private MethodDetail set;
private boolean done;
public MethodDetail get() {
return get;
}
public MethodDetail set() {
return set;
}
public boolean isGettable() {
return get != null;
}
public boolean isSettable() {
return set != null;
}
public void addSetMethod(MethodDetail detail) {
this.set = detail;
}
public void addGetMethod(MethodDetail detail) {
this.get = detail;
}
public boolean isDone() {
return done;
}
public void done() {
done = true;
}
public boolean verify() throws Exception {
if(get != null && set != null) {
if(!get.name.equals(set.name)) {
throw new IllegalStateException("Property names do not match for '"+get.name+"' and '"+set.name+"'");
}
if(!get.type.equals(set.type)) {
throw new IllegalStateException("Property types do not match for '"+get.type+"' and '"+set.type+"'");
}
}
return true;
}
public String toString() {
return String.format("GET -> %s SET -> %s", get, set);
}
}
}
public static class SetAnnotationAttributes implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
if(details.getType() == SourceType.ANNOTATION) {
Pattern pattern = Pattern.compile("^(\\s+)public\\s+class\\s+[a-zA-Z]+.*$");
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
Map<String, String> attributes = details.getAttributes();
for(String line : lines) {
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
String indent = matcher.group(1);
writer.append(line);
writer.append("\n");
for(String attribute : attributes.keySet()){
String type = attributes.get(attribute);
writer.append(indent);
writer.append(" private ");
writer.append(type);
writer.append(" ");
writer.append(attribute);
writer.append(";\n");
}
} else {
writer.append(line);
writer.append("\n");
}
}
return writer.toString();
}
return source;
}
}
private static class DefineType implements ConversionPhase {
private static final Map<Pattern, SourceType> PATTERNS = new HashMap<Pattern, SourceType>();
static {
PATTERNS.put(Pattern.compile("^public\\s+class\\s+([a-zA-Z]*).*"), SourceType.CLASS);
PATTERNS.put(Pattern.compile("^public\\s+final\\s+class\\s+([a-zA-Z]*).*"), SourceType.CLASS);
PATTERNS.put(Pattern.compile("^class\\s+([a-zA-Z]*).*"), SourceType.CLASS);
PATTERNS.put(Pattern.compile("^public\\s+abstract\\s+class\\s+([a-zA-Z]*).*"), SourceType.CLASS);
PATTERNS.put(Pattern.compile("^abstract\\s+class\\s+([a-zA-Z]*).*"), SourceType.CLASS);
PATTERNS.put(Pattern.compile("^final\\s+class\\s+([a-zA-Z]*).*"), SourceType.CLASS);
PATTERNS.put(Pattern.compile("^public\\s+@interface\\s+([a-zA-Z]*).*"), SourceType.ANNOTATION);
PATTERNS.put(Pattern.compile("^@interface\\s+([a-zA-Z]*).*"), SourceType.ANNOTATION);
PATTERNS.put(Pattern.compile("^public\\s+interface\\s+([a-zA-Z]*).*"), SourceType.INTERFACE);
PATTERNS.put(Pattern.compile("^interface\\s+([a-zA-Z]*).*"), SourceType.INTERFACE);
PATTERNS.put(Pattern.compile("^public\\s+enum\\s+([a-zA-Z]*).*"), SourceType.ENUM);
PATTERNS.put(Pattern.compile("^enum\\s+([a-zA-Z]*).*"), SourceType.ENUM);
}
public String convert(String source, SourceDetails details) throws Exception{
List<String> lines = stripLines(source);
for(String line : lines) {
for(Pattern pattern : PATTERNS.keySet()) {
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
SourceType type = PATTERNS.get(pattern);
String name = matcher.group(1);
details.setType(type);
details.setName(name);
return source;
}
}
}
throw new IllegalStateException("File can not be classified " + details.getSource());
}
}
private static class PopulateUsing implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
List<String> lines = stripLines(source);
for(String line : lines) {
if(line.matches("^import.*")) {
line = line.trim();
for(String importName : USING.keySet()) {
if(line.matches(importName)) {
importName = USING.get(importName);
details.addUsing(importName);
break;
}
}
}
}
return source;
}
}
private static class AddUsing implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
Pattern pattern = Pattern.compile("^package\\s+([a-zA-Z\\.]*)\\s*;.*");
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
boolean importsDone = false;
for(String line : lines) {
if(!importsDone) {
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
String packageName = matcher.group(1);
writer.append("\n#region Using directives\n");
for(String using : details.getUsing()) {
writer.append(using);
writer.append("\n");
}
writer.append("\n#endregion\n");
details.setPackage(packageName);
importsDone = true;
}
}
writer.append(line);
writer.append("\n");
}
return writer.toString();
}
}
private static class StripImports implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
Pattern pattern = Pattern.compile("^import\\s+([a-zA-Z\\.]*)\\s*;.*$");
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
for(String line : lines) {
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
String importClass = matcher.group(1);
details.addImport(importClass);
} else {
writer.append(line);
writer.append("\n");
}
}
return writer.toString();
}
}
private static class CreateNamespace implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
String indent = "";
for(String line : lines) {
line = line.replaceAll("\\s*$", "");
writer.append(indent);
if(indent == null || indent.equals("")){
for(String packageName : NAMESPACE.keySet()) {
if(line.matches(packageName + ".*")) {
indent = INDENT;
line = NAMESPACE.get(packageName);
break;
}
}
}
writer.append(line);
writer.append("\n");
}
writer.append("}");
return writer.toString();
}
}
private static class ReplaceAnnotations implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
Pattern withAttributes = Pattern.compile("(\\s+)@([a-zA-Z]+)\\((.*)\\).*");
Pattern withoutAttributes = Pattern.compile("(\\s+)@([a-zA-Z]+).*");
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
for(String line : lines) {
Matcher with = withAttributes.matcher(line);
if(with.matches()) {
String indent = with.group(1);
String name = with.group(2);
String signature = with.group(3);
writer.append(indent);
writer.append("[");
writer.append(name);
if(signature != null && !signature.equals("")) {
writer.append("(");
String[] attributes = signature.split("\\s*,\\s*");
String separator = "";
for(String attribute : attributes) {
writer.append(separator);
writer.append(convertMethod(attribute, MethodType.NORMAL));
separator = ", ";
}
writer.append(")");
}
writer.append("]\n");
} else {
Matcher without = withoutAttributes.matcher(line);
if(without.matches()) {
String indent = without.group(1);
String name = without.group(2);
writer.append(indent);
writer.append("[");
writer.append(name);
writer.append("]\n");
} else {
writer.append(line);
writer.append("\n");
}
}
}
return writer.toString();
}
}
private static class ReplaceMethodConventions implements ConversionPhase {
private static final List<String> MODIFIERS = new ArrayList<String>();
static {
MODIFIERS.add("public static");
MODIFIERS.add("private static");
MODIFIERS.add("protected static");
MODIFIERS.add("public");
MODIFIERS.add("private");
MODIFIERS.add("protected");;
}
public String convert(String source, SourceDetails details) throws Exception {
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
main: for(String line : lines) {
for(String modifier : MODIFIERS) {
Pattern methodMatch = Pattern.compile("^(\\s*)"+modifier+"\\s+([a-zA-Z\\[\\]\\<\\>\\s]+)\\s+([a-zA-Z]+)\\((.*)\\).*$");
Matcher matcher = methodMatch.matcher(line);
if(matcher.matches()) {
String indent = matcher.group(1);
String type = matcher.group(2);
String originalMethod = matcher.group(3);;
String signature = matcher.group(4);
String method = convertMethod(originalMethod, MethodType.NORMAL);
writer.append(indent);
writer.append("public ");
writer.append(type);
writer.append(" ");
writer.append(method);
writer.append("(");
writer.append(signature);
if(line.matches(".*;\\s*") || details.getType() == SourceType.INTERFACE) {
writer.append(");\n");
} else {
writer.append(") {\n");
}
add(details, originalMethod, signature, type);
continue main;
}
}
writer.append(line);
writer.append("\n");
}
return writer.toString();
}
private void add(SourceDetails details, String originalMethod, String signature, String type) {
if(originalMethod.startsWith("get")) {
if(signature == null || signature.equals("")) {
details.addMethod(new MethodSignature(originalMethod, MethodType.GET, null));
} else {
details.addMethod(new MethodSignature(originalMethod, MethodType.NORMAL, null));
}
} else if(originalMethod.startsWith("set")) {
if(signature != null && signature.indexOf(" ") != -1 && signature.indexOf(",") == -1 && type.equals("void")) {
details.addMethod(new MethodSignature(originalMethod, MethodType.SET, signature.split("\\s+")[1]));
}else {
details.addMethod(new MethodSignature(originalMethod, MethodType.NORMAL, null));
}
} else {
details.addMethod(new MethodSignature(originalMethod, MethodType.NORMAL, null));
}
}
}
private static class StripCrap implements ConversionPhase {
private static final List<String> TOKENS = new ArrayList<String>();
static {
TOKENS.add("^\\s*\\/\\/\\/\\s*$");
TOKENS.add("^\\s*$");
TOKENS.add("^\\s+.*@author.*$");
TOKENS.add("^\\s+.*@throws.*$");
TOKENS.add("^\\s+.*@exception.*$");
}
public String convert(String source, SourceDetails details) throws Exception {
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
main: for(String line : lines) {
for(String token : TOKENS) {
if(token.startsWith("^") && line.matches(token)) {
continue main;
}
}
writer.append(line);
writer.append("\n");
}
return writer.toString();
}
}
private static class ReplaceKeyWords implements ConversionPhase {
private static final Map<String, String> TOKENS = new LinkedHashMap<String, String>();
static {
TOKENS.put("<code>", "<c>");
TOKENS.put("</code>", "</c>");
TOKENS.put("<pre>", "</code>");
TOKENS.put("</pre>", "</code>");
TOKENS.put("\\(List ", "(List ");
TOKENS.put(" List ", " List ");
TOKENS.put(",List ", ",List ");
TOKENS.put("HashMap ", "Dictionary ");
TOKENS.put("\\(Map ", "(Dictionary ");
TOKENS.put(" Map ", " Dictionary ");
TOKENS.put(",Map ", ",Dictionary ");
TOKENS.put("ArrayList ", "List ");
TOKENS.put("static final", "const");
TOKENS.put("final", "readonly");
TOKENS.put("readonlyly", "finally");
TOKENS.put("readonly class", "sealed class");
TOKENS.put("final class", "sealed class");
TOKENS.put("boolean", "bool");
TOKENS.put("implements", ":");
TOKENS.put("extends", ":");
TOKENS.put("\\)\\s*throws\\s.*\\{", ") {");
TOKENS.put("\\)\\s*throws\\s.*;", ");");
TOKENS.put("assertEquals\\(", "AssertEquals(");
TOKENS.put("assertNull\\(", "AssertNull(");
TOKENS.put("assertNotNull\\(", "AssertNotNull(");
TOKENS.put("org.simpleframework.xml.convert","SimpleFramework.Xml.Util");
TOKENS.put("org.simpleframework.xml.filter", "SimpleFramework.Xml.Filter");
TOKENS.put("org.simpleframework.xml.strategy", "SimpleFramework.Xml.Strategy");
TOKENS.put("org.simpleframework.xml.core","SimpleFramework.Xml.Core");
TOKENS.put("org.simpleframework.xml.util", "SimpleFramework.Xml.Util");
TOKENS.put("org.simpleframework.xml.stream","SimpleFramework.Xml.Stream");
TOKENS.put("org.simpleframework.xml","SimpleFramework.Xml");
TOKENS.put("@Retention\\(RetentionPolicy.RUNTIME\\)", "[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field | AttributeTargets.Method)]");
}
public String convert(String source, SourceDetails details) throws Exception {
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
for(String line : lines) {
for(String token : TOKENS.keySet()) {
String value = TOKENS.get(token);
if(line.startsWith("^") && line.matches(token)) {
line = line.replaceAll(token, value);
} else if(line.matches(".*" +token+".*")) {
line = line.replaceAll(token, value);
}
}
writer.append(line);
writer.append("\n");
}
return writer.toString();
}
}
private static class ReplaceDocumentation implements ConversionPhase {
private static final Map<String, String> TOKENS = new HashMap<String, String>();
static {
TOKENS.put("return", "returns");
TOKENS.put("see", "seealso");
}
public String convert(String source, SourceDetails details) throws Exception {
Pattern paramComment = Pattern.compile("^(\\s*)///.*@param\\s*([a-zA-Z]*)\\s*(.*)$");
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
main: for(String line : lines) {
Matcher paramMatcher = paramComment.matcher(line);
if(paramMatcher.matches()) {
String indent = paramMatcher.group(1);
String name = paramMatcher.group(2);
String description = paramMatcher.group(3);
writer.append(indent);
writer.append("/// <param name=\"");
writer.append(name);
writer.append("\">\n");
writer.append(indent);
writer.append("/// ");
writer.append(description);
writer.append("\n");
writer.append(indent);
writer.append("/// </param>\n");
} else {
for(String token : TOKENS.keySet()) {
Pattern tokenComment = Pattern.compile("^(\\s*)///.*@"+token+"\\s(.*)$");
Matcher tokenMatcher = tokenComment.matcher(line);
if(tokenMatcher.matches()) {
String replace = TOKENS.get(token);
String indent = tokenMatcher.group(1);
String description = tokenMatcher.group(2);
writer.append(indent);
writer.append("/// <"+replace+">\n");
writer.append(indent);
writer.append("/// ");
writer.append(description);
writer.append("\n");
writer.append(indent);
writer.append("/// </"+replace+">\n");
continue main;
}
}
writer.append(line);
writer.append("\n");
}
}
return writer.toString();
}
}
private static class ReplaceComments implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
List<String> lines = stripLines(source);
Iterator<String> iterator = lines.iterator();
StringWriter writer = new StringWriter();
while(iterator.hasNext()) {
String line = iterator.next();
if(line.matches("\\s*\\/\\*\\*")) {
comment(iterator, writer, line);
} else {
writer.append(line);
writer.append("\n");
}
}
return writer.toString();
}
private void comment(Iterator<String> lines, StringWriter writer, String line) throws Exception {
Pattern normalComment = Pattern.compile("^(\\s*)\\*.*$");
Pattern parameterComment = Pattern.compile("^(\\s*)\\*.*@.*$");
boolean endSummary = false;
writer.append(line.replaceAll("\\/\\*\\*", "/// <summary>"));
writer.append("\n");
while(lines.hasNext()) {
String nextLine = lines.next();
nextLine = nextLine.substring(1);
if(nextLine.matches("^\\s*\\*\\/")) {
if(!endSummary) {
writer.append(nextLine.replaceAll("\\*\\/", "/// </summary>"));
} else {
writer.append(nextLine.replaceAll("\\*\\/", "///"));
}
writer.append("\n");
return;
}
if(!endSummary) {
Matcher parameterMatch = parameterComment.matcher(nextLine);
if(parameterMatch.matches()) {
writer.append(parameterMatch.group(1));
writer.append("/// </summary>");
writer.append("\n");
writer.append(parameterMatch.group(1));
writer.append(nextLine.replaceAll("^\\s*\\*", "///"));
writer.append("\n");
endSummary = true;
} else {
Matcher normalMatch = normalComment.matcher(nextLine);
if(normalMatch.matches()) {
writer.append(normalMatch.group(1));
writer.append(nextLine.replaceAll("^\\s*\\*", "///"));
writer.append("\n");
}
}
} else {
Matcher normalMatch = normalComment.matcher(nextLine);
if(normalMatch.matches()) {
writer.append(normalMatch.group(1));
writer.append(nextLine.replaceAll("^\\s*\\*", "///"));
writer.append("\n");
}else {
throw new IllegalStateException("Comment does not end well " + nextLine);
}
}
}
}
}
private static class ReplaceLicense implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
List<String> lines = stripLines(source);
Iterator<String> iterator = lines.iterator();
StringWriter writer = new StringWriter();
boolean licenseDone = false;
while(iterator.hasNext()) {
String line = iterator.next();
if(!licenseDone && line.matches("\\s*\\/\\*")) {
writer.append("#region License\n");
license(details, iterator, writer, line);
writer.append("#endregion\n");
licenseDone = true;
} else {
if(!line.matches("^\\s*$")) {
licenseDone = true; // no license found
}
writer.append(line);
writer.append("\n");
}
}
return writer.toString();
}
private void license(SourceDetails details, Iterator<String> lines, StringWriter writer, String line) throws Exception {
Pattern comment = Pattern.compile("^(\\s*)\\*.*$");
writer.append(line.replaceAll("\\/\\*", "//"));
writer.append("\n");
while(lines.hasNext()) {
String nextLine = lines.next();
nextLine = nextLine.substring(1);
if(nextLine.matches("^\\s*\\*\\/")) {
writer.append(nextLine.replaceAll("\\*\\/", "//"));
writer.append("\n");
return;
}
Matcher matcher = comment.matcher(nextLine);
if(matcher.matches()) {
if(nextLine.matches(".*\\.java.*")) {
nextLine = nextLine.replaceAll("\\.java", ".cs");
}
writer.append(matcher.group(1));
writer.append(nextLine.replaceAll("^\\s*\\*", "//"));
writer.append("\n");
}else {
throw new IllegalStateException("Comment does not end well '" + nextLine+"' in file "+details.getSource().getCanonicalPath());
}
}
}
}
private static class SubstituteAnnotations implements ConversionPhase {
public String convert(String source, SourceDetails details) throws Exception {
Pattern pattern = Pattern.compile("^(.+) @interface (.+)\\{.*");
List<String> lines = stripLines(source);
StringWriter writer = new StringWriter();
for(String line : lines) {
Matcher matcher = pattern.matcher(line);
if(matcher.matches()) {
String start = matcher.group(1);
String type = matcher.group(2);
writer.append(start);
writer.append(" class ");
writer.append(type);
writer.append(": System.Attribute {\n");
} else {
writer.append(line);
writer.append("\n");
}
}
return writer.toString();
}
}
}