/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* Licensed 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.kie.workbench.common.stunner.core.processors.rule;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.MirroredTypeException;
import javax.lang.model.type.MirroredTypesException;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.kie.workbench.common.stunner.core.processors.MainProcessor;
import org.kie.workbench.common.stunner.core.processors.ProcessingContext;
import org.kie.workbench.common.stunner.core.processors.ProcessingRule;
import org.kie.workbench.common.stunner.core.rule.annotation.RuleExtension;
import org.kie.workbench.common.stunner.core.rule.annotation.RuleExtensions;
import org.uberfire.annotations.processors.AbstractGenerator;
import org.uberfire.annotations.processors.exceptions.GenerationException;
public class ExtensionRuleGenerator extends AbstractGenerator {
private final ProcessingContext processingContext = ProcessingContext.getInstance();
@Override
public StringBuffer generate(final String packageName,
final PackageElement packageElement,
final String className,
final Element element,
final ProcessingEnvironment processingEnvironment) throws GenerationException {
final Messager messager = processingEnvironment.getMessager();
messager.printMessage(Diagnostic.Kind.NOTE,
"Starting code generation for [" + className + "]");
//Extract required information
final TypeElement classElement = (TypeElement) element;
final String ruleNamePrefix = MainProcessor.toValidId(className);
final String ruleDefinitionId = ((TypeElement) element).getQualifiedName().toString();
final RuleExtensions extensions = classElement.getAnnotation(RuleExtensions.class);
if (null != extensions) {
for (final RuleExtension annotation : extensions.value()) {
processRuleExtension(ruleNamePrefix,
ruleDefinitionId,
annotation,
messager);
}
}
final RuleExtension extension = classElement.getAnnotation(RuleExtension.class);
if (null != extension) {
processRuleExtension(ruleNamePrefix,
ruleDefinitionId,
extension,
messager);
}
return null;
}
private void processRuleExtension(final String ruleNamePrefix,
final String ruleDefinitionId,
final RuleExtension annotation,
final Messager messager) throws GenerationException {
TypeMirror mirror = null;
try {
Class<?> handlerClass = annotation.handler();
} catch (MirroredTypeException mte) {
mirror = mte.getTypeMirror();
}
if (null == mirror) {
throw new RuntimeException("No handler class specifyed for @RuleExtension.");
}
final String rhc = mirror.toString();
// Type arguments.
List<? extends TypeMirror> argumentTypeMirrors = null;
try {
Class<?>[] defsClasses = annotation.typeArguments();
} catch (MirroredTypesException mte) {
argumentTypeMirrors = mte.getTypeMirrors();
}
String rawTypeArgs = "null";
if (null != argumentTypeMirrors) {
rawTypeArgs = "new Class<?>[] { ";
for (TypeMirror argTypeMirror : argumentTypeMirrors) {
String morphTargetMirrorClassName = argTypeMirror.toString();
rawTypeArgs += morphTargetMirrorClassName + ".class";
}
rawTypeArgs += " }";
}
// Raw arguments.
String rawArgs = "null";
final String[] arguments = annotation.arguments();
if (null != arguments) {
rawArgs = "new String[] { ";
for (String arg : arguments) {
rawArgs += "\"" + arg + "\"";
}
rawArgs += " }";
}
final String ruleName = ruleNamePrefix + "_" + MainProcessor.toClassMemberId(rhc);
final StringBuffer value = generateRule(messager,
ruleName,
ruleDefinitionId,
rawTypeArgs,
rawArgs,
rhc);
processingContext.addRule(ruleName,
ProcessingRule.TYPE.CARDINALITY,
value);
}
private StringBuffer generateRule(final Messager messager,
final String ruleName,
final String ruleDefinitionId,
final String rawTypeArgs,
final String rawArgs,
final String rhc) throws GenerationException {
Map<String, Object> root = new HashMap<String, Object>();
root.put("ruleId",
ruleDefinitionId);
root.put("args",
rawArgs);
root.put("typeArgs",
rawTypeArgs);
root.put("ruleName",
ruleName);
root.put("ruleHandlerClass",
rhc);
//Generate code
final StringWriter sw = new StringWriter();
final BufferedWriter bw = new BufferedWriter(sw);
try {
final Template template = config.getTemplate("RuleExtension.ftl");
template.process(root,
bw);
} catch (IOException ioe) {
throw new GenerationException(ioe);
} catch (TemplateException te) {
throw new GenerationException(te);
} finally {
try {
bw.close();
sw.close();
} catch (IOException ioe) {
throw new GenerationException(ioe);
}
}
return sw.getBuffer();
}
}