package org.radargun.config;
import java.io.File;
import java.lang.reflect.Modifier;
import java.util.*;
import org.radargun.utils.Utils;
import org.w3c.dom.Element;
/**
* @author Radim Vansa <rvansa@redhat.com>
*/
public class StagesSchemaGenerator extends SchemaGenerator {
private final Collection<Class<? extends org.radargun.Stage>> stages;
private final Collection<Class<?>> extraClasses;
public StagesSchemaGenerator(String namespace, Collection<Class<? extends org.radargun.Stage>> stages, Collection<Class<?>> extraClasses) {
super(StageHelper.NAMESPACE_ROOT, namespace, "radargun-");
this.stages = stages;
this.extraClasses = extraClasses;
}
@Override
protected String findDocumentation(Class<?> clazz) {
org.radargun.config.Stage stageAnnotation = clazz.getAnnotation(org.radargun.config.Stage.class);
if (stageAnnotation != null) return stageAnnotation.doc();
return null;
}
@Override
protected void generate() {
schema = createSchemaElement(namespace);
Set<Class<? extends org.radargun.Stage>> generatedStages = new HashSet<>();
for (Class<? extends org.radargun.Stage> stage : stages) {
generateStage(schema, stage, generatedStages);
}
for (Class<?> extra : extraClasses) {
generateClass(extra);
}
}
void generateStage(Element parent, Class stage, Set<Class<? extends org.radargun.Stage>> generatedStages) {
if (generatedStages.contains(stage)) return;
NamespaceHelper.Coords coords = NamespaceHelper.getCoords(namespaceRoot, stage, omitPrefix);
if (coords != null && !coords.namespace.equals(this.namespace)) {
requireImport(coords.namespace);
return;
}
// boolean hasParentStage = org.radargun.Stage.class.isAssignableFrom(stage.getSuperclass());
// if (hasParentStage) {
// generateStage(parent, stage.getSuperclass(), generatedStages);
// }
org.radargun.config.Stage stageAnnotation = (org.radargun.config.Stage) stage.getAnnotation(org.radargun.config.Stage.class);
if (stageAnnotation == null) return; // not a proper stage
XmlType stageType = generateClass(stage);
if (parent != null && !Modifier.isAbstract(stage.getModifiers()) && !stageAnnotation.internal()) {
createReference(parent, XmlHelper.camelCaseToDash(StageHelper.getStageName(stage)), stageType.toString());
if (!stageAnnotation.deprecatedName().equals(org.radargun.config.Stage.NO_DEPRECATED_NAME)) {
createReference(parent, XmlHelper.camelCaseToDash(stageAnnotation.deprecatedName()), stageType.toString());
}
}
generatedStages.add(stage);
}
/**
* Generate the XSD files for stages. First argument is directory where the XSD files should be placed.
*/
public static void main(String[] args) {
if (args.length < 1 || args[0] == null)
throw new IllegalArgumentException("No schema location directory specified!");
// We have to ensure that all definition elements are defined in given namespace in case these would
// be referenced from another namespace
Map<String, List<Class<?>>> definitions = new HashMap<>();
ClasspathScanner.scanClasspath(null, DefinitionElement.class, "org.radargun",
clazz -> indexClass(definitions, clazz));
Set<String> allNamespaces = new HashSet<>(definitions.keySet());
ClasspathScanner.scanClasspath(null, EnsureInSchema.class, "org.radargun",
clazz -> indexClass(definitions, clazz));
allNamespaces.addAll(StageHelper.getStages().keySet());
for (String namespace : allNamespaces) {
Map<String, Class<? extends org.radargun.Stage>> stages = StageHelper.getStages().get(namespace);
List<Class<?>> extraClasses = definitions.get(namespace);
if (stages == null) {
stages = Collections.EMPTY_MAP;
}
if (extraClasses == null) {
extraClasses = Collections.EMPTY_LIST;
}
new StagesSchemaGenerator(namespace, stages.values(), extraClasses).generate(args[0], NamespaceHelper.getJarMajorMinor(namespace) + ".xsd");
}
}
protected static void indexClass(Map<String, List<Class<?>>> definitions, Class<?> clazz) {
NamespaceHelper.Coords coords = NamespaceHelper.suggestCoordinates(StageHelper.NAMESPACE_ROOT, clazz, "radargun-");
File[] codepaths = new File[] {new File(Utils.getCodePath(clazz))};
NamespaceHelper.registerNamespace(coords.namespace, codepaths, coords.jarMajorMinor);
List<Class<?>> byNamespace = definitions.get(coords.namespace);
if (byNamespace == null) {
definitions.put(coords.namespace, byNamespace = new ArrayList<>());
}
byNamespace.add(clazz);
}
}