package com.robotoworks.mechanoid.net.generator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.xtext.serializer.ISerializer;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import com.google.common.collect.Lists;
import com.robotoworks.mechanoid.net.netModel.BodyBlock;
import com.robotoworks.mechanoid.net.netModel.BooleanLiteral;
import com.robotoworks.mechanoid.net.netModel.BooleanType;
import com.robotoworks.mechanoid.net.netModel.Client;
import com.robotoworks.mechanoid.net.netModel.DoubleType;
import com.robotoworks.mechanoid.net.netModel.EnumMember;
import com.robotoworks.mechanoid.net.netModel.EnumTypeDeclaration;
import com.robotoworks.mechanoid.net.netModel.GenericListType;
import com.robotoworks.mechanoid.net.netModel.HeaderBlock;
import com.robotoworks.mechanoid.net.netModel.HttpMethod;
import com.robotoworks.mechanoid.net.netModel.IntegerType;
import com.robotoworks.mechanoid.net.netModel.IntrinsicType;
import com.robotoworks.mechanoid.net.netModel.Literal;
import com.robotoworks.mechanoid.net.netModel.LongType;
import com.robotoworks.mechanoid.net.netModel.Member;
import com.robotoworks.mechanoid.net.netModel.NumericLiteral;
import com.robotoworks.mechanoid.net.netModel.ParamsBlock;
import com.robotoworks.mechanoid.net.netModel.ResponseBlock;
import com.robotoworks.mechanoid.net.netModel.StringLiteral;
import com.robotoworks.mechanoid.net.netModel.StringType;
import com.robotoworks.mechanoid.net.netModel.Type;
import com.robotoworks.mechanoid.net.netModel.TypedMember;
import com.robotoworks.mechanoid.net.netModel.UserType;
import com.robotoworks.mechanoid.text.Strings;
public class ModelExtensions {
private static final Set<String> reservedWords = new HashSet<String>();
static {
reservedWords.add("source");
reservedWords.add("target");
reservedWords.add("abstract");
reservedWords.add("continue");
reservedWords.add("for");
reservedWords.add("new");
reservedWords.add("switch");
reservedWords.add("assert");
reservedWords.add("default");
reservedWords.add("goto");
reservedWords.add("package");
reservedWords.add("synchronized");
reservedWords.add("boolean");
reservedWords.add("do");
reservedWords.add("if");
reservedWords.add("private");
reservedWords.add("this");
reservedWords.add("break");
reservedWords.add("double");
reservedWords.add("implements");
reservedWords.add("protected");
reservedWords.add("throw");
reservedWords.add("byte");
reservedWords.add("else");
reservedWords.add("import");
reservedWords.add("public");
reservedWords.add("throws");
reservedWords.add("case");
reservedWords.add("enum");
reservedWords.add("instanceof");
reservedWords.add("return");
reservedWords.add("transient");
reservedWords.add("catch");
reservedWords.add("extends");
reservedWords.add("int");
reservedWords.add("short");
reservedWords.add("try");
reservedWords.add("char");
reservedWords.add("final");
reservedWords.add("interface");
reservedWords.add("static");
reservedWords.add("void");
reservedWords.add("class");
reservedWords.add("finally");
reservedWords.add("long");
reservedWords.add("strictfp");
reservedWords.add("volatile");
reservedWords.add("const");
reservedWords.add("float");
reservedWords.add("native");
reservedWords.add("super");
reservedWords.add("while");
}
public static String getBoxedTypeSignature(IntrinsicType type) {
if(type instanceof StringType) {
return "String";
} else if (type instanceof BooleanType) {
return "Boolean";
} else if (type instanceof IntegerType) {
return "Integer";
} else if (type instanceof LongType) {
return "Long";
} else if (type instanceof DoubleType) {
return "Double";
}
return "[unsupported]";
}
public static String signature(Type type){
if(type instanceof IntrinsicType){
return ((IntrinsicType) type).getId();
} else if(type instanceof UserType) {
return ((UserType) type).getDeclaration().getName();
} else if(type instanceof GenericListType){
GenericListType genType = (GenericListType) type;
if(genType.getElementType() instanceof UserType){
return "List<" + ((UserType)genType.getElementType()).getDeclaration().getName() + ">";
} else {
return "List<" + getBoxedTypeSignature((IntrinsicType)genType.getElementType()) + ">";
}
}
return "[unsupported]";
}
public static String innerSignature(Type type){
if(type instanceof IntrinsicType){
return ((IntrinsicType) type).getId();
} else if(type instanceof UserType) {
return ((UserType) type).getDeclaration().getName();
} else if(type instanceof GenericListType){
GenericListType genType = (GenericListType) type;
if(genType.getElementType() instanceof UserType){
return ((UserType)genType.getElementType()).getDeclaration().getName();
} else {
return ((IntrinsicType)genType.getElementType()).getId();
}
}
return "[unsupported]";
}
public static String toJSONPropertyGetMethod(IntrinsicType type){
return "get" + Strings.pascalize(type.getId());
}
public static String toJSONOptPropertyGetMethod(IntrinsicType type){
return "opt" + Strings.pascalize(type.getId());
}
public static boolean hasBody(HttpMethod method){
Iterable<BodyBlock> bodies = IterableExtensions.filter(method.getBlocks(), BodyBlock.class);
return IterableExtensions.size(bodies) > 0;
}
public static BodyBlock getBody(HttpMethod method){
Iterable<BodyBlock> bodies = IterableExtensions.filter(method.getBlocks(), BodyBlock.class);
return IterableExtensions.head(bodies);
}
public static ParamsBlock getParamsBlock(Client client){
Iterable<ParamsBlock> blocks = IterableExtensions.filter(client.getBlocks(), ParamsBlock.class);
return IterableExtensions.head(blocks);
}
public static HeaderBlock getHeaderBlock(Client client){
Iterable<HeaderBlock> blocks = IterableExtensions.filter(client.getBlocks(), HeaderBlock.class);
return IterableExtensions.head(blocks);
}
public static ParamsBlock getParamsBlock(HttpMethod method){
Iterable<ParamsBlock> blocks = IterableExtensions.filter(method.getBlocks(), ParamsBlock.class);
return IterableExtensions.head(blocks);
}
public static HeaderBlock getHeaderBlock(HttpMethod method){
Iterable<HeaderBlock> blocks = IterableExtensions.filter(method.getBlocks(), HeaderBlock.class);
return IterableExtensions.head(blocks);
}
public static ResponseBlock getResponseBlock(HttpMethod method){
Iterable<ResponseBlock> blocks = IterableExtensions.filter(method.getBlocks(), ResponseBlock.class);
return IterableExtensions.head(blocks);
}
public static String generateEnumMembers(EnumTypeDeclaration decl){
Set<Integer> set = new HashSet<Integer>();
EList<EnumMember> members = decl.getLiteral().getMembers();
StringBuilder builder = new StringBuilder();
boolean someAssigned = false;
int numAssigned = 0;
for(EnumMember member : members){
if(member.isAssignment()){
someAssigned = true;
numAssigned++;
}
set.add(member.getValue());
}
if(someAssigned){
// First one is assigned
if(numAssigned == 1 && members.get(0).isAssignment()){
int idx = members.get(0).getValue();
for(int i=0; i < members.size(); i++){
builder.append(Strings.underscore(members.get(i).getName()).toUpperCase());
builder.append("(").append(idx++).append(")");
if(i < members.size() - 1){
builder.append(", \n");
}
}
return builder.toString();
}
else if(set.size() == members.size()){
for(int i=0; i < members.size(); i++){
builder.append(Strings.underscore(members.get(i).getName()).toUpperCase());
builder.append("(").append(members.get(i).getValue()).append(")");
if(i < members.size() - 1){
builder.append(", \n");
}
}
return builder.toString();
} else {
for(int i=0; i < members.size(); i++){
builder.append(Strings.underscore(members.get(i).getName()).toUpperCase());
builder.append("(").append(i).append(")");
if(i < members.size() - 1){
builder.append(", \n");
}
}
return builder.toString();
}
} else {
for(int i=0; i < members.size(); i++){
builder.append(Strings.underscore(members.get(i).getName()).toUpperCase());
builder.append("(").append(i).append(")");
if(i < members.size() - 1){
builder.append(", \n");
}
}
return builder.toString();
}
}
public static String resolveGetJSONValueMethodName(EnumTypeDeclaration decl){
if(decl.getSuperType() != null){
return "optInt";
} else {
return "optString";
}
}
public static String resolveJsonReaderMethodName(EnumTypeDeclaration decl){
if(decl.getSuperType() != null){
return "nextInt";
} else {
return "nextString";
}
}
/**
* Adds an _ to the start if the string is a reserved word
* @param value
* @return
*/
public static String escapeReserved(String value){
// Reserved
if(reservedWords.contains(value)){
return "_" + value;
} else {
return value;
}
}
public static String toIdentifierOrGetMethodName(Member member, boolean asGetMethod){
if(asGetMethod){
return toGetMethodName(member);
} else {
return toIdentifier(member, null);
}
}
public static String toIdentifier(Member member){
return toIdentifier(member, null);
}
public static String maybeMethodize(String identifier, boolean methodize){
if(methodize){
return identifier + "()";
} else {
return identifier;
}
}
public static String toGetMethodName(Member member){
if(!(member instanceof TypedMember)) {
return null;
}
TypedMember typedMember = (TypedMember) member;
if(typedMember.getType() instanceof BooleanType){
String name = member.getName().toLowerCase();
if(name.startsWith("is") ||
name.startsWith("has") ||
name.startsWith("contains")){
return toIdentifier(member, null);
} else {
return toIdentifier(member, "is");
}
} else {
return toIdentifier(member, "get");
}
}
public static String toSetMethodName(Member member){
return toIdentifier(member, "set");
}
public static String ifTrue(boolean option, String str){
return option ? str : "";
}
/**
* Takes a string (identifier) and prefixes it with ownerName seperated by a .
* ie:- given the identifier getQux, and an ownerName of this, the result would be this.getQux,
* by setting the methodize flag to true, it will append () on the end, ie:- this.getQux()
* @param identifier The identifier to memberize
* @param ownerName The owner of the member
* @param methodize Adds () on the end of the result
* @return
*/
public static String memberize(String identifier, String ownerName, boolean methodize){
if(ownerName == null || ownerName.length() == 0){
return identifier + (methodize ? "()" : "");
} else {
return ownerName + "." + identifier + (methodize ? "()" : "");
}
}
public static String memberize(String identifier, String ownerName){
return memberize(identifier, ownerName, false);
}
public static String toIdentifier(Member member, String prefix){
String name = member.getName();
name = spacesToUnderscores(name);
if(prefix != null){
return prefix + Strings.pascalize(name);
} else {
return escapeReserved(Strings.camelize(name));
}
}
private static String spacesToUnderscores(String name) {
if(name.contains(" ")) {
StringBuffer result = new StringBuffer(name.length());
for(int i=0; i < name.length(); i++){
char ch = name.charAt(i);
if(Character.isWhitespace(ch)){
result.append('_');
}
else if(Character.isJavaIdentifierPart(ch)){
result.append(ch);
}
}
name = result.toString();
}
return name;
}
public static String toReference(String name, boolean getter, String prefix){
if(getter){
return prefix == null ? "get" + Strings.pascalize(name) : prefix + ".get" + Strings.pascalize(name) + "()";
} else {
return prefix == null ? Strings.camelize(name) : prefix + "." + Strings.camelize(name);
}
}
public static String getPathAsFormatString(HttpMethod method, ISerializer serializer){
if(method.getPath() == null) {
return "";
}
String path = serializer.serialize(method.getPath()).trim();
return path.replaceAll("[\\^a-zA-Z_0-9]+:[a-zA-Z_0-9]+", "%s");
}
public static Iterable<String> getArgsFromPath(String path) {
if(path == null) {
return new ArrayList<String>();
}
return IterableExtensions.filter(Lists.newArrayList(path.split("/|\\.")), new Function1<String, Boolean>(){public Boolean apply(String p) {
return p.startsWith(":");
}});
}
public static String getDefaultValueLiteral(IntrinsicType type) {
if(type instanceof StringType) {
return "null";
} else if (type instanceof BooleanType) {
return "false";
} else if (type instanceof IntegerType) {
return "0";
} else if (type instanceof LongType) {
return "0L";
} else if (type instanceof DoubleType) {
return "0.0d";
}
return "INVALID_TYPE";
}
public static String convertToJavaLiteral(Literal literal) {
if(literal instanceof StringLiteral) {
return "\"" + org.eclipse.xtext.util.Strings.convertToJavaString(((StringLiteral) literal).getLiteral()) + "\"";
} else if(literal instanceof BooleanLiteral) {
return ((BooleanLiteral)literal).getLiteral().getLiteral();
} else if(literal instanceof NumericLiteral) {
return ((NumericLiteral)literal).getLiteral().toString();
}
return "";
}
}