Skip to content

Instantly share code, notes, and snippets.

@sambatriste
Created May 25, 2020 12:42
Show Gist options
  • Save sambatriste/8ec4727d3b444a3115353d2573e7c55c to your computer and use it in GitHub Desktop.
Save sambatriste/8ec4727d3b444a3115353d2573e7c55c to your computer and use it in GitHub Desktop.
package com.github.sambatriste;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SequenceWriter;
import nablarch.core.repository.di.ComponentCreator;
import nablarch.core.repository.di.ComponentDefinition;
import nablarch.core.repository.di.ComponentReference;
import nablarch.core.repository.di.DiContainer;
import nablarch.core.repository.di.InjectionType;
import nablarch.core.repository.di.config.ListComponentCreator;
import nablarch.core.repository.di.config.LiteralComponentCreator;
import nablarch.core.repository.di.config.xml.XmlComponentDefinitionLoader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class EffectiveComponentDefinition {
public static void main(String[] args) throws IOException {
String componentFileFqcn = args.length < 1 ? "web-boot.xml" : args[0];
String pathToOutputFile = args.length < 2 ? "target/components.json" : args[1];
EffectiveComponentDefinition printer = new EffectiveComponentDefinition();
printer.show(componentFileFqcn, new File(pathToOutputFile));
}
public void show(String componentFileFqcn, File fileToWrite) throws IOException {
Writer writer = null;
try {
writer = new OutputStreamWriter(new FileOutputStream(fileToWrite), Charset.forName("UTF-8"));
show(componentFileFqcn, writer);
} finally {
if (writer != null) {
writer.close();
}
}
}
public void show(String componentFileFqcn, Writer writer) throws IOException {
ObjectGraphBuilder builder = new ObjectGraphBuilder(componentFileFqcn);
Map<String, Object> graph = builder.build();
doWrite(graph, writer);
}
private void doWrite(Map<String, Object> graph, Writer writer) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
//objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
SequenceWriter seqWriter = null;
try {
seqWriter = objectMapper.writerWithDefaultPrettyPrinter().writeValues(writer);
seqWriter.write(graph);
} finally {
if (seqWriter != null) {
seqWriter.close();
}
}
}
static class ObjectGraphBuilder {
private final List<ComponentDefinition> definitions;
private final DiContainer diContainer;
ObjectGraphBuilder(String componentFile) {
XmlComponentDefinitionLoader loader = new XmlComponentDefinitionLoader(componentFile);
diContainer = new DiContainer(loader);
definitions = loader.load(diContainer);
}
Map<String, Object> build() {
Map<String, Object> result = new TreeMap<String, Object>();
for (ComponentDefinition def : definitions) {
String name = def.getName();
if (name != null) {
Object value = evaluate(def);
result.put(name, value);
}
}
return result;
}
private Object evaluate(ComponentDefinition def) {
if (def == null) {
return null;
}
ComponentCreator creator = def.getCreator();
if (creator instanceof LiteralComponentCreator) {
return evaluate((LiteralComponentCreator) creator);
}
if (creator instanceof ListComponentCreator) {
return evaluate((ListComponentCreator) creator);
}
List<ComponentReference> refs = def.getReferences();
if (refs.isEmpty()) {
return def.getType();
}
return evaluate(refs);
}
private Object evaluate(ListComponentCreator creator) {
return creator.toString();
}
private static Pattern VALUE_PATTERN = Pattern.compile(".*,value=(.+)]$");
private static Pattern VARIABLE_PATTERN = Pattern.compile("\\$\\{(.+)}");
private Object evaluate(LiteralComponentCreator c) {
// "literal object = [type=java.lang.String,value=${nablarch.ibmExtendedCharset.allowedCharacters}]"
String orig = c.toString();
Matcher valueMatcher = VALUE_PATTERN.matcher(orig);
if (valueMatcher.find()) {
String value = valueMatcher.group(1);
Matcher variableMatcher = VARIABLE_PATTERN.matcher(value);
if (variableMatcher.find()) {
String varName = variableMatcher.group(1);
return diContainer.getComponentByName(varName);
}
return value;
}
return orig;
}
private Object evaluate(List<ComponentReference> refs) {
Map<String, Object> props = new TreeMap<String, Object>();
for (ComponentReference ref : refs) {
ComponentDefinition targetDef = find(ref);
String name = ref.getPropertyName();
Object value = evaluate(targetDef); // tail recursion でないがええじゃろ
props.put(name, value);
}
return props;
}
private ComponentDefinition find(ComponentReference ref) {
for (ComponentDefinition def : definitions) {
if (matches(def, ref)) {
return def;
}
}
return null;
}
private boolean matches(ComponentDefinition def, ComponentReference ref) {
InjectionType injectionType = ref.getInjectionType();
switch (injectionType) {
case ID:
return (ref.getTargetId() == def.getId());
case REF:
case BY_NAME:
return ref.getReferenceName().equals(def.getName());
case BY_TYPE:
return ref.getRequiredType().isAssignableFrom(def.getType());
default:
throw new IllegalStateException(injectionType.toString());
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment