blob: a9dd879a6c5ff4ee743b89c25809de478adc447a [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.camel.generator.swagger;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Collectors;
import com.squareup.javapoet.MethodSpec;
import static org.apache.commons.lang3.ClassUtils.isPrimitiveOrWrapper;
class MethodBodySourceCodeEmitter implements CodeEmitter<MethodSpec> {
private final MethodSpec.Builder builder;
private boolean first = true;
private final Deque<Integer> indentIntentStack = new ArrayDeque<>();
private final Deque<Integer> indentStack = new ArrayDeque<>();
MethodBodySourceCodeEmitter(final MethodSpec.Builder builder) {
this.builder = builder;
indentStack.push(0);
}
@Override
public CodeEmitter<MethodSpec> emit(final String method, final Object... args) {
final boolean hasArgs = args != null && args.length > 0;
final int indent = indentLevelOf(method);
if (!first) {
builder.addCode("\n");
}
builder.addCode(String.join("", Collections.nCopies(indentStack.peek(), "$<")));
builder.addCode(String.join("", Collections.nCopies(indent, "$>")));
if (!first) {
builder.addCode(".");
}
indentStack.push(indent);
if (hasArgs) {
builder.addCode("$L(" + invocationLiteralsFor(args) + ")", extend(method, argumentsFor(args)));
} else {
builder.addCode("$L()", method);
}
first = false;
return this;
}
@Override
public MethodSpec result() {
builder.addCode(String.join("", Collections.nCopies(indentStack.peek(), "$<")));
builder.addCode(";\n");
return builder.build();
}
Object[] argumentsFor(final Object[] args) {
final List<Object> arguments = new ArrayList<>(args.length);
for (final Object arg : args) {
if (isPrimitiveOrWrapper(arg.getClass())) {
arguments.add(arg);
} else if (arg instanceof String) {
arguments.add(arg);
} else if (arg instanceof Enum) {
arguments.add(arg.getClass());
arguments.add(arg);
} else if (arg instanceof String[]) {
arguments.add(Arrays.stream((String[]) arg).collect(Collectors.joining(",")));
}
}
return arguments.toArray(new Object[arguments.size()]);
}
Object[] extend(final Object first, final Object... others) {
if (others == null || others.length == 0) {
return new Object[] {first};
}
final Object[] ret = new Object[1 + others.length];
ret[0] = first;
System.arraycopy(others, 0, ret, 1, others.length);
return ret;
}
int indentLevelOf(final String method) {
switch (method) {
case "rest":
return 0;
case "post":
case "get":
case "put":
case "patch":
case "delete":
case "head":
case "options":
return 1;
case "param":
indentIntentStack.push(3);
return 2;
case "endParam":
indentIntentStack.pop();
return 2;
case "route":
indentIntentStack.push(3);
return 2;
case "endRest":
indentIntentStack.pop();
return 2;
default:
if (indentIntentStack.isEmpty()) {
return 2;
}
return indentIntentStack.peek();
}
}
String invocationLiteralsFor(final Object[] args) {
final StringJoiner literals = new StringJoiner(",");
for (final Object arg : args) {
if (isPrimitiveOrWrapper(arg.getClass())) {
literals.add("$L");
} else if (arg instanceof String) {
literals.add("$S");
} else if (arg instanceof Enum) {
literals.add("$T.$L");
} else if (arg instanceof String[]) {
literals.add("$S");
}
}
return literals.toString();
}
}