diff --git a/.gitignore b/.gitignore
index 5f7922b..e7e2929 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,5 @@ hs_err_pid*
target
.DS_Store
+
+_mess
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 1d91acc..d3dc90e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
UTF-8
UTF-8
- 1.8
+ 11
${maven.build.timestamp}
yyyy-MM-dd HH:mm
@@ -22,8 +22,24 @@
1.72
2.1.0
2.6
+ 2.1
+ 4.0.1
+ 7.1.0
+
+
+ evolveum
+ Evolveum Public Releases
+ https://nexus.evolveum.com/nexus/content/groups/public/
+
+
+ evolveum-snapshots
+ Evolveum Snapshots
+ https://nexus.evolveum.com/nexus/content/repositories/snapshots/
+
+
+
philosopher
@@ -134,5 +150,23 @@
asciidoctorj
${asciidoctorj.version}
+
+
+ org.apache.velocity
+ velocity-engine-core
+ ${velocity.version}
+
+
+
+ com.evolveum.midpoint.client
+ midpoint-client-impl-rest-jaxb
+ ${midpoint.client.version}
+
+
+
+ org.testng
+ testng
+ ${testng.version}
+
\ No newline at end of file
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/Command.java b/src/main/java/com/evolveum/midpoint/philosopher/Command.java
index 26ff55c..d562580 100644
--- a/src/main/java/com/evolveum/midpoint/philosopher/Command.java
+++ b/src/main/java/com/evolveum/midpoint/philosopher/Command.java
@@ -1,5 +1,8 @@
package com.evolveum.midpoint.philosopher;
+import com.evolveum.midpoint.philosopher.generator.GenerateAction;
+import com.evolveum.midpoint.philosopher.generator.GenerateOptions;
+
/**
* @author Viliam Repan (lazyman)
*/
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/GenerateAction.java b/src/main/java/com/evolveum/midpoint/philosopher/GenerateAction.java
deleted file mode 100644
index 72f8d3e..0000000
--- a/src/main/java/com/evolveum/midpoint/philosopher/GenerateAction.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.evolveum.midpoint.philosopher;
-
-/**
- * Created by Viliam Repan (lazyman).
- */
-public class GenerateAction implements Action {
-
- @Override
- public void init(GenerateOptions options) throws Exception {
-
- }
-
- @Override
- public void execute() throws Exception {
-
- }
-}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/GenerateOptions.java b/src/main/java/com/evolveum/midpoint/philosopher/GenerateOptions.java
deleted file mode 100644
index baca19f..0000000
--- a/src/main/java/com/evolveum/midpoint/philosopher/GenerateOptions.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package com.evolveum.midpoint.philosopher;
-
-import com.beust.jcommander.Parameter;
-import com.beust.jcommander.Parameters;
-
-import java.io.File;
-
-/**
- * Created by Viliam Repan (lazyman).
- */
-@Parameters(resourceBundle = "messages", commandDescriptionKey = "generate")
-public class GenerateOptions {
-
- public static final String P_TEMPLATE = "-template";
- public static final String P_TEMPLATE_LONG = "--template";
-
- @Parameter(names = {P_TEMPLATE, P_TEMPLATE_LONG}, descriptionKey = "generate.template")
- private File dbPath = new File("./data");
-
-}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/PhilosopherMain.java b/src/main/java/com/evolveum/midpoint/philosopher/PhilosopherMain.java
index 482b262..8717d4b 100644
--- a/src/main/java/com/evolveum/midpoint/philosopher/PhilosopherMain.java
+++ b/src/main/java/com/evolveum/midpoint/philosopher/PhilosopherMain.java
@@ -109,6 +109,7 @@ private JCommander setupCommandLineParser() {
BaseOptions base = new BaseOptions();
JCommander.Builder builder = JCommander.newBuilder()
+ .expandAtSign(false)
.addObject(base);
for (Command cmd : Command.values()) {
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/ConnectionOptions.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/ConnectionOptions.java
new file mode 100644
index 0000000..a1b4b64
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/ConnectionOptions.java
@@ -0,0 +1,69 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+import com.evolveum.midpoint.philosopher.util.URIConverter;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+@Parameters(resourceBundle = "messages")
+public class ConnectionOptions {
+
+ public static final String P_URL = "-U";
+ public static final String P_URL_LONG = "--url";
+
+ public static final String P_USERNAME = "-u";
+ public static final String P_USERNAME_LONG = "--username";
+
+ public static final String P_PASSWORD = "-p";
+ public static final String P_PASSWORD_LONG = "--password";
+
+ public static final String P_ASK_PASSWORD = "-P";
+ public static final String P_ASK_PASSWORD_LONG = "--password-ask";
+
+ @Parameter(names = {P_URL, P_URL_LONG}, validateWith = URIConverter.class, descriptionKey = "connection.url")
+ private String url;
+
+ @Parameter(names = {P_USERNAME, P_USERNAME_LONG}, descriptionKey = "connection.username")
+ private String username;
+
+ @Parameter(names = {P_PASSWORD, P_PASSWORD_LONG}, descriptionKey = "connection.password")
+ private String password;
+
+ @Parameter(names = {P_ASK_PASSWORD, P_ASK_PASSWORD_LONG}, password = true,
+ descriptionKey = "connection.askPassword")
+ private String askPassword;
+
+ public String getAskPassword() {
+ return askPassword;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public void setAskPassword(String askPassword) {
+ this.askPassword = askPassword;
+ }
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/ExportFormat.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/ExportFormat.java
new file mode 100644
index 0000000..4dfe242
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/ExportFormat.java
@@ -0,0 +1,11 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public enum ExportFormat {
+
+ PDF,
+
+ HTML;
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/Exporter.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/Exporter.java
new file mode 100644
index 0000000..d7dcbd5
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/Exporter.java
@@ -0,0 +1,12 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public interface Exporter {
+
+ void export(File adocFile, File output) throws IOException;
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/GenerateAction.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/GenerateAction.java
new file mode 100644
index 0000000..31c371b
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/GenerateAction.java
@@ -0,0 +1,36 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import com.evolveum.midpoint.client.api.Service;
+import com.evolveum.midpoint.client.impl.restjaxb.AuthenticationType;
+import com.evolveum.midpoint.client.impl.restjaxb.RestJaxbServiceBuilder;
+import com.evolveum.midpoint.philosopher.Action;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public class GenerateAction implements Action {
+
+ private GenerateOptions options;
+
+ @Override
+ public void init(GenerateOptions options) throws Exception {
+ this.options = options;
+ }
+
+ @Override
+ public void execute() throws Exception {
+ ConnectionOptions con = options.getConnection();
+
+ String pwd = con.getPassword() != null ? con.getPassword() : con.getAskPassword();
+
+ Service client = new RestJaxbServiceBuilder()
+ .url(con.getUrl())
+ .username(con.getUsername())
+ .password(pwd)
+ .authentication(AuthenticationType.BASIC)
+ .build();
+
+ Generator generator = new Generator(options, client);
+ generator.generate();
+ }
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/GenerateOptions.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/GenerateOptions.java
new file mode 100644
index 0000000..c372a2e
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/GenerateOptions.java
@@ -0,0 +1,67 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import com.beust.jcommander.Parameter;
+import com.beust.jcommander.Parameters;
+import com.beust.jcommander.ParametersDelegate;
+
+import java.io.File;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+@Parameters(resourceBundle = "messages", commandDescriptionKey = "generate")
+public class GenerateOptions {
+
+ public static final String P_EXPORT_FORMAT = "-ef";
+ public static final String P_EXPORT_FORMAT_LONG = "--export-format";
+
+ public static final String P_TEMPLATE = "-t";
+ public static final String P_TEMPLATE_LONG = "--template";
+
+ public static final String P_OUTPUT = "-o";
+ public static final String P_OUTPUT_LONG = "--output";
+
+ @ParametersDelegate
+ private ConnectionOptions connection;
+
+ @Parameter(names = {P_EXPORT_FORMAT, P_EXPORT_FORMAT_LONG}, descriptionKey = "generate.exportFormat")
+ private ExportFormat exportFormat;
+
+ @Parameter(names = {P_TEMPLATE, P_TEMPLATE_LONG}, descriptionKey = "generate.template")
+ private File template;
+
+ @Parameter(names = {P_OUTPUT, P_OUTPUT_LONG}, descriptionKey = "generate.output")
+ private File output;
+
+ public ConnectionOptions getConnection() {
+ return connection;
+ }
+
+ public File getTemplate() {
+ return template;
+ }
+
+ public File getOutput() {
+ return output;
+ }
+
+ public ExportFormat getExportFormat() {
+ return exportFormat;
+ }
+
+ public void setExportFormat(ExportFormat exportFormat) {
+ this.exportFormat = exportFormat;
+ }
+
+ public void setConnection(ConnectionOptions connection) {
+ this.connection = connection;
+ }
+
+ public void setTemplate(File template) {
+ this.template = template;
+ }
+
+ public void setOutput(File output) {
+ this.output = output;
+ }
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/Generator.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/Generator.java
new file mode 100644
index 0000000..48a9fe4
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/Generator.java
@@ -0,0 +1,109 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import com.evolveum.midpoint.client.api.Service;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public class Generator {
+
+ private static final Logger LOG = LoggerFactory.getLogger(Generator.class);
+
+ private static final String ADOC_EXTENSION = ".adoc";
+
+ private static final Map EXPORTERS;
+
+ static {
+ Map exporters = new HashMap<>();
+ exporters.put(ExportFormat.PDF, new PdfExporter());
+ exporters.put(ExportFormat.HTML, new HtmlExporter());
+
+ EXPORTERS = Collections.unmodifiableMap(exporters);
+ }
+
+ private GenerateOptions configuration;
+
+ private Service client;
+
+ public Generator(GenerateOptions configuration, Service client) {
+ this.configuration = configuration;
+ this.client = client;
+ }
+
+ public void generate() throws Exception {
+ Map, Set> types = createDefaultTypes();
+
+ File adocFile = createAsciidocFile();
+ if (adocFile.exists()) {
+ adocFile.delete();
+ }
+
+ adocFile.createNewFile();
+
+ try (Writer output = new BufferedWriter(
+ new OutputStreamWriter(new FileOutputStream(adocFile), StandardCharsets.UTF_8))) {
+
+ VelocityGeneratorProcessor processor = new VelocityGeneratorProcessor();
+
+ GeneratorContext ctx = new GeneratorContext(configuration, client);
+ processor.process(output, ctx);
+ } catch (IOException ex) {
+ // todo error handling
+ ex.printStackTrace();
+ }
+
+ LOG.info("Asciidoc file '{}' generated for all objects", adocFile.getPath());
+
+ if (configuration.getExportFormat() == null) {
+ return;
+ }
+
+ Exporter exporter = EXPORTERS.get(configuration.getExportFormat());
+ if (exporter == null) {
+ LOG.info("No exporter defined, finishing");
+ return;
+ }
+
+ File output = configuration.getOutput();
+ if (output.exists()) {
+ output.delete();
+ }
+
+ try {
+ output.createNewFile();
+
+ exporter.export(adocFile, output);
+ } catch (IOException ex) {
+ // todo error handling
+ ex.printStackTrace();
+ }
+ }
+
+ private File createAsciidocFile() {
+ File output = configuration.getOutput();
+ if (configuration.getExportFormat() == null) {
+ return output;
+ }
+
+ return new File(output.getParent(), output.getName() + ADOC_EXTENSION);
+ }
+
+ private Map, Set> createDefaultTypes() {
+ Map, Set> map = new HashMap<>();
+ map.put(ResourceType.class, new HashSet<>());
+ map.put(ObjectTemplateType.class, new HashSet<>());
+ map.put(FunctionLibraryType.class, new HashSet<>());
+ map.put(ConnectorType.class, new HashSet<>());
+
+ // todo figure out which types should be used by default
+
+ return map;
+ }
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/GeneratorContext.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/GeneratorContext.java
new file mode 100644
index 0000000..dd7c639
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/GeneratorContext.java
@@ -0,0 +1,25 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import com.evolveum.midpoint.client.api.Service;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public class GeneratorContext {
+
+ private Service client;
+ private GenerateOptions configuration;
+
+ public GeneratorContext(GenerateOptions configuration, Service client) {
+ this.configuration = configuration;
+ this.client = client;
+ }
+
+ public GenerateOptions getConfiguration() {
+ return configuration;
+ }
+
+ public Service getClient() {
+ return client;
+ }
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/HtmlExporter.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/HtmlExporter.java
new file mode 100644
index 0000000..fc2477c
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/HtmlExporter.java
@@ -0,0 +1,47 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import org.apache.commons.io.FileUtils;
+import org.asciidoctor.Asciidoctor;
+import org.asciidoctor.AttributesBuilder;
+import org.asciidoctor.OptionsBuilder;
+import org.asciidoctor.SafeMode;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public class HtmlExporter implements Exporter {
+
+ // todo figure out templates
+
+ @Override
+ public void export(File adocFile, File output) throws IOException {
+ File dir = output.getParentFile();
+ File file = new File(output.getName());
+
+ FileUtils.forceMkdir(dir);
+
+ if (output.exists()) {
+ output.delete();
+ }
+ output.createNewFile();
+
+ OptionsBuilder builder = OptionsBuilder.options()
+ .safe(SafeMode.UNSAFE)
+ .toDir(dir)
+ .toFile(file)
+ .headerFooter(true)
+ .attributes(AttributesBuilder.attributes());
+// .templateDir(new File("./src/test/resources/css"));
+
+ Map options = builder.asMap();
+
+ File adoc = new File("./src/test/resources/test.adoc");
+
+ Asciidoctor doctor = Asciidoctor.Factory.create();
+ doctor.convertFile(adoc, options);
+ }
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/PdfExporter.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/PdfExporter.java
new file mode 100644
index 0000000..7a46cce
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/PdfExporter.java
@@ -0,0 +1,15 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public class PdfExporter implements Exporter {
+
+ @Override
+ public void export(File adocFile, File output) throws IOException {
+
+ }
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/ProcessorUtils.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/ProcessorUtils.java
new file mode 100644
index 0000000..6750f86
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/ProcessorUtils.java
@@ -0,0 +1,83 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import com.evolveum.midpoint.client.api.SearchResult;
+import com.evolveum.midpoint.client.api.Service;
+import com.evolveum.midpoint.client.api.exception.ObjectNotFoundException;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.FunctionLibraryType;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectTemplateType;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public class ProcessorUtils {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ProcessorUtils.class);
+
+ private GeneratorContext context;
+
+ public ProcessorUtils(GeneratorContext context) {
+ this.context = context;
+ }
+
+ public List loadTemplates() throws Exception {
+ return loadObjects(ObjectTemplateType.class);
+ }
+
+ public List loadResources() throws Exception {
+ return loadObjects(ResourceType.class);
+ }
+
+ public List loadFunctionLibraries() throws Exception {
+ return loadObjects(FunctionLibraryType.class);
+ }
+
+ private List loadObjects(Class type) throws Exception {
+// Map> types = context.getConfiguration().includedObjectTypes();
+// Set oids = types.get(type);
+
+ // todo filter by oids
+
+ List objects = new ArrayList<>();
+
+ Service service = context.getClient();
+ try {
+ SearchResult result = service.collection(type).search().queryFor(type).build().get();
+ if (result != null) {
+ objects.addAll(result);
+ Collections.sort(objects, new ObjectTypeComparator());
+ }
+ } catch (ObjectNotFoundException ex) {
+ LOG.warn("Couldn't find objects of type {}", type);
+ }
+
+ return objects;
+ }
+
+ private static class ObjectTypeComparator implements Comparator {
+
+ @Override
+ public int compare(ObjectType o1, ObjectType o2) {
+ String s1 = getName(o1);
+ String s2 = getName(o2);
+
+ return String.CASE_INSENSITIVE_ORDER.compare(s1, s2);
+ }
+
+ private String getName(ObjectType o) {
+ if (o == null) {
+ return null;
+ }
+
+ return TemplateUtils.getOrig(o.getName());
+ }
+ }
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/TemplateUtils.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/TemplateUtils.java
new file mode 100644
index 0000000..47a5329
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/TemplateUtils.java
@@ -0,0 +1,171 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import com.evolveum.midpoint.client.api.Service;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorConfigurationType;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
+import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
+import com.evolveum.midpoint.xml.ns._public.connector.icf_1.connector_schema_3.ConfigurationPropertiesType;
+import com.evolveum.midpoint.xml.ns._public.connector.icf_1.connector_schema_3.ResultsHandlerConfigurationType;
+import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;
+import org.w3c.dom.Element;
+import org.w3c.dom.Text;
+
+import javax.xml.bind.JAXBElement;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public class TemplateUtils {
+
+ public static String getOrig(PolyStringType poly) {
+ if (poly == null) {
+ return null;
+ }
+ for (Object content : poly.getContent()) {
+ if (content instanceof String) {
+ return (String) content;
+ }
+ // TODO: DOM elements and JAXB elements
+ }
+ return null;
+ }
+
+ public static List getResultsHandlerConfiguration(ResourceType resource) {
+ ResultsHandlerConfigurationType config = getConnectorConfiguration(resource, ResultsHandlerConfigurationType.class);
+ if (config == null) {
+ return new ArrayList<>();
+ }
+
+ List attributes = new ArrayList<>();
+ addAttribute("enableAttributesToGetSearchResultsHandler", config.isEnableAttributesToGetSearchResultsHandler(), attributes);
+ addAttribute("enableCaseInsensitiveFilter", config.isEnableCaseInsensitiveFilter(), attributes);
+ addAttribute("enableFilteredResultsHandler", config.isEnableFilteredResultsHandler(), attributes);
+ addAttribute("enableNormalizingResultsHandler", config.isEnableNormalizingResultsHandler(), attributes);
+ addAttribute("filteredResultsHandlerInValidationMode", config.isFilteredResultsHandlerInValidationMode(), attributes);
+
+ return attributes;
+ }
+
+ private static void addAttribute(String name, Object value, List attributes) {
+ if (value == null) {
+ return;
+ }
+
+ attributes.add(new Attribute(name, value));
+ }
+
+ public static List getConnectorConfiguration(ResourceType resource) {
+ ConfigurationPropertiesType config = getConnectorConfiguration(resource, ConfigurationPropertiesType.class);
+ if (config == null) {
+ return new ArrayList<>();
+ }
+
+ List attributes = new ArrayList<>();
+
+ for (Object obj : config.getAny()) {
+ if (!(obj instanceof Element)) {
+ continue;
+ }
+
+ Element element = (Element) obj;
+ String value;
+ if (element.getFirstChild() instanceof Text) {
+ value = element.getTextContent();
+ } else {
+ value = "XML"; // todo improve, passwords, etc
+ }
+
+ attributes.add(new Attribute(element.getLocalName(), null, value));
+ }
+
+ return attributes;
+ }
+
+ private static T getConnectorConfiguration(ResourceType resource, Class type) {
+ ConnectorConfigurationType config = resource.getConnectorConfiguration();
+ List configs = config.getAny();
+ if (configs.isEmpty()) {
+ return null;
+ }
+
+// Map configDescription = getConnectorConfigurationDescription(resource);
+
+ for (Object obj : configs) {
+ if (!(obj instanceof JAXBElement)) {
+ continue;
+ }
+
+ JAXBElement jaxb = (JAXBElement) obj;
+ if (jaxb.getValue() == null || !type.isAssignableFrom(jaxb.getValue().getClass())) {
+ continue;
+ }
+
+ return jaxb.getValue();
+ }
+
+ return null;
+ }
+
+ private static Map getConnectorConfigurationDescription(Service client, ResourceType resource) {
+ ObjectReferenceType connectorRef = resource.getConnectorRef();
+ if (connectorRef == null || connectorRef.getOid() == null) {
+ return new HashMap<>();
+ }
+
+ Map result = new HashMap<>();
+// ConnectorType connector = loadObject(client, connectorRef);
+ // todo implement
+
+ return result;
+ }
+
+ public static ObjectType loadObject(Service client, ObjectReferenceType ref) throws Exception {
+ if (client == null || ref == null) {
+ return null;
+ }
+
+
+// ObjectTypes type = ObjectTypes.getObjectTypeFromTypeQName(ref.getType());
+// if (type == null) {
+// type = ObjectTypes.OBJECT;
+// }
+//
+// return client.oid(type.getClassDefinition(), ref.getOid()).get();
+ return null;
+ }
+
+ public static class Attribute {
+
+ private String name;
+ private String description;
+ private Object value;
+
+ public Attribute(String name, Object value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public Attribute(String name, String description, Object value) {
+ this.name = name;
+ this.description = description;
+ this.value = value;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+ }
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/generator/VelocityGeneratorProcessor.java b/src/main/java/com/evolveum/midpoint/philosopher/generator/VelocityGeneratorProcessor.java
new file mode 100644
index 0000000..1cb9e41
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/generator/VelocityGeneratorProcessor.java
@@ -0,0 +1,49 @@
+package com.evolveum.midpoint.philosopher.generator;
+
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public class VelocityGeneratorProcessor {
+
+ public VelocityGeneratorProcessor() {
+ init();
+ }
+
+ private void init() {
+ Properties props = new Properties();
+ props.put(RuntimeConstants.RESOURCE_LOADER, "classpath");
+ props.put("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
+
+ Velocity.init(props);
+ }
+
+ private Template getTemplate(String name) {
+ return Velocity.getTemplate(name, StandardCharsets.UTF_8.name());
+ }
+
+ public void process(Writer output, GeneratorContext ctx) throws IOException {
+ Template template = getTemplate("/template/documentation.vm");
+ if (template == null) {
+ return;
+ }
+
+ VelocityContext context = new VelocityContext();
+ context.put("configuration", ctx.getConfiguration());
+ context.put("client", ctx.getClient());
+ context.put("utils", TemplateUtils.class);
+ context.put("processor", new ProcessorUtils(ctx));
+
+ template.merge(context, output);
+ }
+}
diff --git a/src/main/java/com/evolveum/midpoint/philosopher/util/URIConverter.java b/src/main/java/com/evolveum/midpoint/philosopher/util/URIConverter.java
new file mode 100644
index 0000000..572a7f7
--- /dev/null
+++ b/src/main/java/com/evolveum/midpoint/philosopher/util/URIConverter.java
@@ -0,0 +1,51 @@
+package com.evolveum.midpoint.philosopher.util;
+
+import com.beust.jcommander.IParameterValidator;
+import com.beust.jcommander.IStringConverter;
+import com.beust.jcommander.ParameterException;
+
+import java.net.URI;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public class URIConverter implements IStringConverter, IParameterValidator {
+
+ private String optionName;
+
+ public URIConverter() {
+ this(null);
+ }
+
+ public URIConverter(String optionName) {
+ this.optionName = optionName;
+ }
+
+ @Override
+ public URI convert(String value) {
+ if (value == null) {
+ return null;
+ }
+
+ try {
+ return URI.create(value);
+ } catch (IllegalArgumentException ex) {
+ throw new IllegalArgumentException("Option " + optionName
+ + " doesn't contain valid URL ('" + value + "')", ex);
+ }
+ }
+
+ @Override
+ public void validate(String name, String value) throws ParameterException {
+ if (value == null) {
+ return;
+ }
+
+ try {
+ URI.create(value);
+ } catch (IllegalArgumentException ex) {
+ throw new ParameterException("Option " + name
+ + " doesn't contain valid URL ('" + value + "'), reason: " + ex.getMessage());
+ }
+ }
+}
diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties
index 9a2f00e..1a6531e 100644
--- a/src/main/resources/messages.properties
+++ b/src/main/resources/messages.properties
@@ -2,5 +2,13 @@ base.help=Print this help
base.version=Version and build description
base.silent=No output at all
base.verbose=Verbose output
+connection.url=Url to MidPoint model webservice endpoint or JDBC url to database. If '-m' option is used url \
+ will be used to connect to JDBC database. If '-m' is not specified then this parameter is used as MidPoint \
+ REST url endpoint.
+connection.username=Username for rest/jdbc connection
+connection.password=Password for rest/jdbc connection
+connection.askPassword=Please write rest/jdbc connection password
generate=Generate documentation
-generate.template=Template
\ No newline at end of file
+generate.template=Template file
+generate.output=Output file
+generate.exportFormat=Export format. Allowed values [pdf, html].
\ No newline at end of file
diff --git a/src/main/resources/template/documentation.vm b/src/main/resources/template/documentation.vm
new file mode 100644
index 0000000..0a4fe87
--- /dev/null
+++ b/src/main/resources/template/documentation.vm
@@ -0,0 +1,7 @@
+:toc:
+
+#parse("/template/templates.vm")
+
+#parse("/template/resources.vm")
+
+#parse("/template/libraries.vm")
diff --git a/src/main/resources/template/libraries.vm b/src/main/resources/template/libraries.vm
new file mode 100644
index 0000000..3356bdf
--- /dev/null
+++ b/src/main/resources/template/libraries.vm
@@ -0,0 +1,13 @@
+## FUNCTION LIBRARIES
+
+#set($libraries=$processor.loadFunctionLibraries())
+
+#if(!$libraries.isEmpty())
+
+= Function Libraries
+
+ #foreach($object in $libraries)
+ #parse("/template/library.vm")
+ #end
+
+#end
\ No newline at end of file
diff --git a/src/main/resources/template/library.vm b/src/main/resources/template/library.vm
new file mode 100644
index 0000000..d0a24a1
--- /dev/null
+++ b/src/main/resources/template/library.vm
@@ -0,0 +1,7 @@
+#[[##]]# $!utils.getOrig($object.getName())
+
+$!object.getDescription()
+
+#[[###]]# Functions
+
+## todo describe functions
diff --git a/src/main/resources/template/resource.vm b/src/main/resources/template/resource.vm
new file mode 100644
index 0000000..bc92c06
--- /dev/null
+++ b/src/main/resources/template/resource.vm
@@ -0,0 +1,61 @@
+#[[##]]# $!utils.getOrig($object.getName())
+
+#[[###]]# Connector
+
+#set($connector=$utils.loadObject($client, $object.getConnectorRef()))
+
+Resource uses $!utils.getOrig($connector.getDisplayName()) connector. Artifact details:
+* **Connector type:** $!connector.getConnectorType()
+* **Connector version:** $!connector.getConnectorVersion()
+* **Connector bundle:** $!connector.getConnectorBundle()
+* **Namespace:** $!connector.getNamespace()
+
+#[[####]]# Connector Configuration
+
+Parameter|Value|Description
+:---|:---|--:
+#foreach($attribute in $utils.getConnectorConfiguration($object))
+|$!attribute.getName() | $!attribute.getValue() |$!attribute.getDescription() |
+#end
+
+#set($handlersConfig=$utils.getResultsHandlerConfiguration($object))
+
+#if(!$handlersConfig.isEmpty())
+
+#[[#####]]# Results Handlers Configuration
+
+Parameter|Value
+:---|:---|--:
+#foreach($attribute in $handlersConfig)
+|$!attribute.getName() | $!attribute.getValue() |
+#end
+
+#end
+
+#[[###]]# Available Object Types
+
+* table OC / Kind / Intent / Description from somewhere
+
+#foreach($type in $object.getSchemaHandling().getObjectType())
+#[[####]]# $!type.getDisplayName() $!type.getKind()/$!type.getIntent()
+#end
+
+#[[###]]# Attributes Description
+
+#foreach($type in $object.getSchemaHandling().getObjectType())
+#[[####]]# $!type.getDisplayName() $!type.getKind()/$!type.getIntent()
+
+Attribute|Type|Description
+:---|:---|--:
+#foreach($attribute in $type.getAttribute())
+|$!attribute.getRef().getValue() | |$!attribute.getDescription() |
+#end
+#end
+
+#[[###]]# Synchronization Configuration
+
+* Table
+
+#[[###]]# Capabilities
+
+* Table
diff --git a/src/main/resources/template/resources.vm b/src/main/resources/template/resources.vm
new file mode 100644
index 0000000..6a2616f
--- /dev/null
+++ b/src/main/resources/template/resources.vm
@@ -0,0 +1,13 @@
+## RESOURCES
+
+#set($resources=$processor.loadResources())
+
+#if(!$resources.isEmpty())
+
+= Resources
+
+ #foreach($object in $resources)
+ #parse("/template/resource.vm")
+ #end
+
+#end
\ No newline at end of file
diff --git a/src/main/resources/template/template.vm b/src/main/resources/template/template.vm
new file mode 100644
index 0000000..39ddd5d
--- /dev/null
+++ b/src/main/resources/template/template.vm
@@ -0,0 +1,3 @@
+#[[##]]# $!utils.getOrig($object.getName())
+
+$!object.getDescription()
diff --git a/src/main/resources/template/templates.vm b/src/main/resources/template/templates.vm
new file mode 100644
index 0000000..d8840c9
--- /dev/null
+++ b/src/main/resources/template/templates.vm
@@ -0,0 +1,13 @@
+## OBJECT TEMPLATES
+
+#set($templates=$processor.loadTemplates())
+
+#if(!$templates.isEmpty())
+
+= Object Templates
+
+ #foreach($object in $templates)
+ #parse("/template/template.vm")
+ #end
+
+#end
\ No newline at end of file
diff --git a/src/test/java/com/evolveum/midpoint/philosopher/GeneratorTest.java b/src/test/java/com/evolveum/midpoint/philosopher/GeneratorTest.java
new file mode 100644
index 0000000..5d3262a
--- /dev/null
+++ b/src/test/java/com/evolveum/midpoint/philosopher/GeneratorTest.java
@@ -0,0 +1,42 @@
+package com.evolveum.midpoint.philosopher;
+
+import com.evolveum.midpoint.philosopher.generator.ConnectionOptions;
+import com.evolveum.midpoint.philosopher.generator.GenerateAction;
+import com.evolveum.midpoint.philosopher.generator.GenerateOptions;
+import com.evolveum.midpoint.philosopher.generator.HtmlExporter;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Created by Viliam Repan (lazyman).
+ */
+public class GeneratorTest {
+
+ @Test
+ public void generateSampleAdoc() throws Exception {
+ ConnectionOptions con = new ConnectionOptions();
+ con.setUrl("https://demo.evolveum.com/midpoint/ws/rest");
+ con.setUsername("administrator");
+ con.setPassword("5ecr3t");
+
+ GenerateOptions opts = new GenerateOptions();
+ opts.setConnection(con);
+ opts.setOutput(new File("./target/demo.adoc"));
+
+ GenerateAction action = new GenerateAction();
+ action.init(opts);
+
+ action.execute();
+ }
+
+ @Test
+ public void generateAdocHtml() throws IOException {
+ HtmlExporter exporter = new HtmlExporter();
+
+ File adoc = new File("./src/test/resources/test.adoc");
+ File html = new File("./target/test.html");
+ exporter.export(adoc, html);
+ }
+}
diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..e540cfc
--- /dev/null
+++ b/src/test/resources/logback-test.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+ %date [%thread] %-5level \(%logger{46}\): %message%n
+
+
+
+
+ ./target/test.log
+
+ %date [%thread] %-5level \(%logger{46}\): %message%n
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/test/resources/test.adoc b/src/test/resources/test.adoc
new file mode 100644
index 0000000..98cdcd5
--- /dev/null
+++ b/src/test/resources/test.adoc
@@ -0,0 +1,13 @@
+:toc: left
+
+= First example
+
+Whoa.
+
+== second level
+
+I'm fine
+
+=== third level
+
+asdf
\ No newline at end of file