syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmarte...@apache.org
Subject [2/3] syncope git commit: refactoring of the report stack , SYNCOPE-158
Date Fri, 23 Oct 2015 10:36:56 GMT
refactoring of the report stack , SYNCOPE-158


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/7a11bf3b
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/7a11bf3b
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/7a11bf3b

Branch: refs/heads/SYNCOPE-156
Commit: 7a11bf3b911a9ca96dcd4a9b15158dc1d47fd814
Parents: 73f73f2
Author: massi <massimiliano.perrone@tirasa.net>
Authored: Fri Oct 23 12:11:56 2015 +0200
Committer: massi <massimiliano.perrone@tirasa.net>
Committed: Fri Oct 23 12:11:56 2015 +0200

----------------------------------------------------------------------
 .../cli/commands/CommonsResultManager.java      |   6 +-
 .../client/cli/commands/ReportCommand.java      | 352 -------------------
 .../ConfigurationResultManager.java             |   2 +-
 .../commands/logger/LoggerResultManager.java    |   2 +-
 .../notification/NotificationDelete.java        |   2 +-
 .../commands/policy/PolicyResultManager.java    |   6 +-
 .../commands/report/AbstractReportCommand.java  |  30 ++
 .../cli/commands/report/ReportCommand.java      | 137 ++++++++
 .../cli/commands/report/ReportDelete.java       |  58 +++
 .../commands/report/ReportDeleteExecution.java  |  61 ++++
 .../cli/commands/report/ReportExecute.java      |  64 ++++
 .../commands/report/ReportExportExecution.java  | 100 ++++++
 .../client/cli/commands/report/ReportList.java  |  33 ++
 .../cli/commands/report/ReportListJobs.java     |  35 ++
 .../client/cli/commands/report/ReportRead.java  |  59 ++++
 .../commands/report/ReportReadExecution.java    |  62 ++++
 .../commands/report/ReportResultManager.java    |  75 ++++
 .../commands/schema/SchemaResultManager.java    |   2 +-
 .../syncope/client/cli/messages/Messages.java   |  94 -----
 .../syncope/client/cli/messages/Table.java      | 194 ----------
 .../client/cli/messages/TwoColumnTable.java     | 262 --------------
 .../syncope/client/cli/view/Messages.java       |  94 +++++
 .../apache/syncope/client/cli/view/Table.java   | 194 ++++++++++
 23 files changed, 1014 insertions(+), 910 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/CommonsResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/CommonsResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/CommonsResultManager.java
index c316e13..7c17550 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/CommonsResultManager.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/CommonsResultManager.java
@@ -18,10 +18,14 @@
  */
 package org.apache.syncope.client.cli.commands;
 
-import org.apache.syncope.client.cli.messages.Messages;
+import org.apache.syncope.client.cli.view.Messages;
 
 public abstract class CommonsResultManager {
 
+    public void managerNumberFormatException(final String what, final String key) {
+        Messages.printIdNotNumberDeletedMessage(what, key);
+    }
+
     public void deletedMessage(final String what, final String key) {
         Messages.printDeletedMessage(what, key);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
deleted file mode 100644
index 30be7fb..0000000
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/ReportCommand.java
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * 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.syncope.client.cli.commands;
-
-import java.io.IOException;
-import java.io.SequenceInputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.ws.WebServiceException;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.client.cli.Command;
-import org.apache.syncope.client.cli.Input;
-import org.apache.syncope.client.cli.SyncopeServices;
-import org.apache.syncope.client.cli.messages.Messages;
-import org.apache.syncope.client.cli.util.CommandUtils;
-import org.apache.syncope.client.cli.util.XMLUtils;
-import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.to.ReportExecTO;
-import org.apache.syncope.common.lib.to.ReportTO;
-import org.apache.syncope.common.lib.types.JobStatusType;
-import org.apache.syncope.common.lib.types.ReportExecExportFormat;
-import org.apache.syncope.common.rest.api.service.ReportService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.xml.sax.SAXException;
-
-@Command(name = "report")
-public class ReportCommand extends AbstractCommand {
-
-    private static final Logger LOG = LoggerFactory.getLogger(ReportCommand.class);
-
-    private static final String HELP_MESSAGE = "Usage: report [options]\n"
-            + "  Options:\n"
-            + "    --help \n"
-            + "    --list \n"
-            + "    --read \n"
-            + "       Syntax: --read {REPORT-ID} {REPORT-ID} [...] \n"
-            + "    --delete \n"
-            + "       Syntax: --delete {REPORT-ID} {REPORT-ID} [...]\n"
-            + "    --execute \n"
-            + "       Syntax: --execute {REPORT-ID} \n"
-            + "    --read-execution \n"
-            + "       Syntax: --read-execution {EXECUTION-ID} {EXECUTION-ID} [...]\n"
-            + "    --delete-execution \n"
-            + "       Syntax: --delete-execution {EXECUTION-ID} {EXECUTION-ID} [...]\n"
-            + "    --export-execution-result \n"
-            + "       Syntax: --export-execution-result {EXECUTION-ID} {EXECUTION-ID} [...] {FORMAT}\n"
-            + "          Format: CSV / HTML / PDF / XML / RTF"
-            + "    --reportlet-class";
-    
-    @Override
-    public void execute(final Input input) {
-        LOG.debug("Option: {}", input.getOption());
-        LOG.debug("Parameters:");
-        for (final String parameter : input.getParameters()) {
-            LOG.debug("   > " + parameter);
-        }
-
-        String[] parameters = input.getParameters();
-
-        if (StringUtils.isBlank(input.getOption())) {
-            input.setOption(Options.HELP.getOptionName());
-        }
-
-        final ReportService reportService = SyncopeServices.get(ReportService.class);
-        switch (Options.fromName(input.getOption())) {
-            case LIST:
-                try {
-                    for (final ReportTO reportTO : reportService.list()) {
-                        System.out.println(reportTO);
-                    }
-                } catch (final SyncopeClientException ex) {
-                    Messages.printMessage(ex.getMessage());
-                }
-                break;
-            case LIST_JOBS:
-                try {
-                    for (final JobStatusType jobStatusType : JobStatusType.values()) {
-                        System.out.println("Report execution for " + jobStatusType);
-                        final List<ReportExecTO> reportExecTOs = reportService.listJobs(jobStatusType);
-                        for (final ReportExecTO reportExecTO : reportExecTOs) {
-                            System.out.println(" - Report execution id: " + reportExecTO.getKey());
-                            System.out.println(" - Report execution status: " + reportExecTO.getStatus());
-                            System.out.println(" - Report execution start date: " + reportExecTO.getStartDate());
-                            System.out.println(" - Report execution end date: " + reportExecTO.getEndDate());
-                            System.out.println();
-                        }
-                    }
-                } catch (final SyncopeClientException ex) {
-                    Messages.printMessage(ex.getMessage());
-                }
-                break;
-            case READ:
-                final String readErrorMessage = "report --read {REPORT-ID} {REPORT-ID} [...]";
-                if (parameters.length >= 1) {
-                    for (final String parameter : parameters) {
-                        try {
-                            System.out.println(reportService.read(Long.valueOf(parameter)));
-                        } catch (final NumberFormatException ex) {
-                            Messages.printIdNotNumberDeletedMessage("report", parameter);
-                        } catch (final WebServiceException | SyncopeClientException ex) {
-                            if (ex.getMessage().startsWith("NotFound")) {
-                                Messages.printNofFoundMessage("Report", parameter);
-                            } else {
-                                Messages.printMessage(ex.getMessage());
-                            }
-                        }
-                    }
-                } else {
-                    Messages.printCommandOptionMessage(readErrorMessage);
-                }
-                break;
-            case DELETE:
-                final String deleteErrorMessage = "report --delete {REPORT-ID} {REPORT-ID} [...]";
-
-                if (parameters.length >= 1) {
-                    for (final String parameter : parameters) {
-                        try {
-                            reportService.delete(Long.valueOf(parameter));
-                            Messages.printDeletedMessage("Report", parameter);
-                        } catch (final WebServiceException | SyncopeClientException ex) {
-                            if (ex.getMessage().startsWith("NotFound")) {
-                                Messages.printNofFoundMessage("Report", parameter);
-                            } else if (ex.getMessage().startsWith("DataIntegrityViolation")) {
-                                Messages.printMessage("You cannot delete report " + parameter);
-                            } else {
-                                Messages.printMessage(ex.getMessage());
-                            }
-                        } catch (final NumberFormatException ex) {
-                            Messages.printIdNotNumberDeletedMessage("report", parameter);
-                        }
-                    }
-                } else {
-                    Messages.printCommandOptionMessage(deleteErrorMessage);
-                }
-                break;
-            case EXECUTE:
-                final String executeErrorMessage = "report --execute {REPORT-ID}";
-
-                if (parameters.length == 1) {
-
-                    try {
-                        final Long reportIdToExecute = Long.valueOf(parameters[0]);
-                        reportService.execute(reportIdToExecute);
-                        final List<ReportExecTO> executionList
-                                = reportService.read(reportIdToExecute).getExecutions();
-                        final ReportExecTO lastExecution = executionList.get(executionList.size() - 1);
-                        System.out.println(" - Report execution id: " + lastExecution.getKey());
-                        System.out.println(" - Report execution status: " + lastExecution.getStatus());
-                        System.out.println(" - Report execution start date: " + lastExecution.getStartDate());
-                    } catch (final WebServiceException | SyncopeClientException ex) {
-                        System.out.println("Error:");
-                        if (ex.getMessage().startsWith("NotFound")) {
-                            Messages.printNofFoundMessage("Report", parameters[0]);
-                        } else if (ex.getMessage().startsWith("DataIntegrityViolation")) {
-                            Messages.printMessage("You cannot delete report " + parameters[0]);
-                        } else {
-                            Messages.printMessage(ex.getMessage());
-                        }
-                    } catch (final NumberFormatException ex) {
-                        Messages.printIdNotNumberDeletedMessage("report", parameters[0]);
-                    }
-                } else {
-                    Messages.printCommandOptionMessage(executeErrorMessage);
-                }
-                break;
-            case READ_EXECUTION:
-                final String readExecutionErrorMessage = "report --read-execution {EXECUTION-ID} {EXECUTION-ID} [...]";
-
-                if (parameters.length >= 1) {
-                    for (final String parameter : parameters) {
-
-                        try {
-                            ReportExecTO reportExecTO = reportService.readExecution(Long.valueOf(parameter));
-                            System.out.println(" - Report execution id: " + reportExecTO.getKey());
-                            System.out.println(" - Report execution status: " + reportExecTO.getStatus());
-                            System.out.println(" - Report execution start date: " + reportExecTO.getStartDate());
-                            System.out.println(" - Report execution end date: " + reportExecTO.getEndDate());
-                        } catch (final WebServiceException | SyncopeClientException ex) {
-                            System.out.println("Error:");
-                            if (ex.getMessage().startsWith("NotFound")) {
-                                Messages.printNofFoundMessage("Report", parameter);
-                            } else {
-                                Messages.printMessage(ex.getMessage());
-                            }
-                        } catch (final NumberFormatException ex) {
-                            Messages.printIdNotNumberDeletedMessage("report", parameter);
-                        }
-                    }
-                } else {
-                    Messages.printCommandOptionMessage(readExecutionErrorMessage);
-                }
-                break;
-            case DELETE_EXECUTION:
-                final String deleteExecutionErrorMessage
-                        = "report --delete-execution {EXECUTION-ID} {EXECUTION-ID} [...]";
-
-                if (parameters.length >= 1) {
-                    for (final String parameter : parameters) {
-
-                        try {
-                            reportService.deleteExecution(Long.valueOf(parameter));
-                            Messages.printDeletedMessage("Report execution", parameter);
-                        } catch (final WebServiceException | SyncopeClientException ex) {
-                            if (ex.getMessage().startsWith("NotFound")) {
-                                Messages.printNofFoundMessage("Report", parameter);
-                            } else if (ex.getMessage().startsWith("DataIntegrityViolation")) {
-                                System.out.println(" - You cannot delete report " + parameter);
-                            } else {
-                                System.out.println(ex.getMessage());
-                            }
-                        } catch (final NumberFormatException ex) {
-                            Messages.printIdNotNumberDeletedMessage("report", parameter);
-                        }
-                    }
-                } else {
-                    Messages.printCommandOptionMessage(deleteExecutionErrorMessage);
-                }
-                break;
-            case EXPORT_EXECUTION_RESULT:
-                final String exportExecutionErrorMessage
-                        = "report --export-execution-result {EXECUTION-ID} {EXECUTION-ID} [...] {FORMAT}\n"
-                        + "          Format: CSV / HTML / PDF / XML / RTF";
-
-                if (parameters.length >= 2) {
-                    parameters = Arrays.copyOf(parameters, parameters.length - 1);
-                    for (final String parameter : parameters) {
-                        try {
-                            final ReportExecExportFormat format = ReportExecExportFormat.valueOf(input.lastParameter());
-                            final Long exportId = Long.valueOf(parameter);
-                            final SequenceInputStream report = (SequenceInputStream) reportService.
-                                    exportExecutionResult(exportId, format).getEntity();
-                            switch (format) {
-                                case XML:
-                                    final String xmlFinalName = "export_" + exportId + ".xml";
-                                    XMLUtils.createXMLFile(report, xmlFinalName);
-                                    Messages.printMessage(xmlFinalName + " successfully created");
-                                    break;
-                                case CSV:
-                                    Messages.printMessage(format + " doesn't supported");
-                                    break;
-                                case PDF:
-                                    Messages.printMessage(format + " doesn't supported");
-                                    break;
-                                case HTML:
-                                    Messages.printMessage(format + " doesn't supported");
-                                    break;
-                                case RTF:
-                                    Messages.printMessage(format + " doesn't supported");
-                                    break;
-                                default:
-                                    Messages.printMessage(format + " doesn't supported");
-                                    break;
-                            }
-                        } catch (final WebServiceException | SyncopeClientException ex) {
-                            if (ex.getMessage().startsWith("NotFound")) {
-                                Messages.printNofFoundMessage("Report", parameter);
-                            } else {
-                                System.out.println(ex.getMessage());
-                            }
-                        } catch (final NumberFormatException ex) {
-                            Messages.printIdNotNumberDeletedMessage("report", parameter);
-                        } catch (IOException | ParserConfigurationException | SAXException | TransformerException e) {
-                            System.out.println(" - Error creating " + "export_" + parameter + " " + e.getMessage());
-                        } catch (final IllegalArgumentException ex) {
-                            Messages.printTypeNotValidMessage(
-                                    "format", input.firstParameter(),
-                                    CommandUtils.fromEnumToArray(ReportExecExportFormat.class));
-                        }
-                        break;
-                    }
-                } else {
-                    Messages.printCommandOptionMessage(exportExecutionErrorMessage);
-                }
-                break;
-            case HELP:
-                System.out.println(HELP_MESSAGE);
-                break;
-            default:
-                Messages.printDefaultMessage(input.getOption(), HELP_MESSAGE);
-        }
-    }
-
-    @Override
-    public String getHelpMessage() {
-        return HELP_MESSAGE;
-    }
-
-    private enum Options {
-
-        HELP("--help"),
-        LIST("--list"),
-        LIST_JOBS("--list-jobs"),
-        READ("--read"),
-        DELETE("--delete"),
-        EXECUTE("--execute"),
-        READ_EXECUTION("--read-execution"),
-        DELETE_EXECUTION("--delete-execution"),
-        EXPORT_EXECUTION_RESULT("--export-execution-result");
-
-        private final String optionName;
-
-        Options(final String optionName) {
-            this.optionName = optionName;
-        }
-
-        public String getOptionName() {
-            return optionName;
-        }
-
-        public boolean equalsOptionName(final String otherName) {
-            return (otherName == null) ? false : optionName.equals(otherName);
-        }
-
-        public static Options fromName(final String name) {
-            Options optionToReturn = HELP;
-            for (final Options option : Options.values()) {
-                if (option.equalsOptionName(name)) {
-                    optionToReturn = option;
-                }
-            }
-            return optionToReturn;
-        }
-
-        public static List<String> toList() {
-            final List<String> options = new ArrayList<>();
-            for (final Options value : values()) {
-                options.add(value.getOptionName());
-            }
-            return options;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/configuration/ConfigurationResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/configuration/ConfigurationResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/configuration/ConfigurationResultManager.java
index 446d08a..e4073c0 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/configuration/ConfigurationResultManager.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/configuration/ConfigurationResultManager.java
@@ -21,7 +21,7 @@ package org.apache.syncope.client.cli.commands.configuration;
 import java.util.Arrays;
 import java.util.LinkedList;
 import org.apache.syncope.client.cli.commands.CommonsResultManager;
-import org.apache.syncope.client.cli.messages.Table;
+import org.apache.syncope.client.cli.view.Table;
 import org.apache.syncope.common.lib.to.AttrTO;
 
 public class ConfigurationResultManager extends CommonsResultManager {

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/logger/LoggerResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/logger/LoggerResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/logger/LoggerResultManager.java
index 1a686cd..a693aff 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/logger/LoggerResultManager.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/logger/LoggerResultManager.java
@@ -21,7 +21,7 @@ package org.apache.syncope.client.cli.commands.logger;
 import java.util.Arrays;
 import java.util.LinkedList;
 import org.apache.syncope.client.cli.commands.CommonsResultManager;
-import org.apache.syncope.client.cli.messages.Table;
+import org.apache.syncope.client.cli.view.Table;
 import org.apache.syncope.common.lib.to.LoggerTO;
 
 public class LoggerResultManager extends CommonsResultManager {

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/notification/NotificationDelete.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/notification/NotificationDelete.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/notification/NotificationDelete.java
index 1e4b96d..2e0e5cd 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/notification/NotificationDelete.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/notification/NotificationDelete.java
@@ -20,7 +20,7 @@ package org.apache.syncope.client.cli.commands.notification;
 
 import javax.xml.ws.WebServiceException;
 import org.apache.syncope.client.cli.Input;
-import org.apache.syncope.client.cli.messages.Messages;
+import org.apache.syncope.client.cli.view.Messages;
 import org.apache.syncope.common.lib.SyncopeClientException;
 
 public class NotificationDelete extends AbstractNotificationCommand {

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/policy/PolicyResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/policy/PolicyResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/policy/PolicyResultManager.java
index 88e40a0..7d140a3 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/policy/PolicyResultManager.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/policy/PolicyResultManager.java
@@ -81,7 +81,7 @@ public class PolicyResultManager extends CommonsResultManager {
     }
 
     public void printAccountPolicy(final AccountPolicyTO policyTO) {
-        System.out.println(" > KEY: " + String.valueOf(policyTO.getKey()));
+        System.out.println(" > KEY: " + policyTO.getKey());
         System.out.println("    type: " + policyTO.getType().name());
         System.out.println("    description: " + policyTO.getDescription());
         System.out.println("    resources : " + policyTO.getUsedByResources().toString());
@@ -93,7 +93,7 @@ public class PolicyResultManager extends CommonsResultManager {
     }
 
     public void printPasswordPolicy(final PasswordPolicyTO policyTO) {
-        System.out.println(" > KEY: " + String.valueOf(policyTO.getKey()));
+        System.out.println(" > KEY: " + policyTO.getKey());
         System.out.println("    type: " + policyTO.getType().name());
         System.out.println("    description: " + policyTO.getDescription());
         System.out.println("    resources : " + policyTO.getUsedByResources().toString());
@@ -105,7 +105,7 @@ public class PolicyResultManager extends CommonsResultManager {
     }
 
     public void printSyncPolicy(final SyncPolicyTO policyTO) {
-        System.out.println(" > KEY: " + String.valueOf(policyTO.getKey()));
+        System.out.println(" > KEY: " + policyTO.getKey());
         System.out.println("    type: " + policyTO.getType().name());
         System.out.println("    description: " + policyTO.getDescription());
         System.out.println("    resources : " + policyTO.getUsedByResources().toString());

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/AbstractReportCommand.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/AbstractReportCommand.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/AbstractReportCommand.java
new file mode 100644
index 0000000..e4c2394
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/AbstractReportCommand.java
@@ -0,0 +1,30 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import org.apache.syncope.client.cli.SyncopeServices;
+import org.apache.syncope.common.rest.api.service.ReportService;
+
+public abstract class AbstractReportCommand {
+
+    protected final ReportService reportService = SyncopeServices.get(ReportService.class);
+
+    protected final ReportResultManager reportResultManager = new ReportResultManager();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportCommand.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportCommand.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportCommand.java
new file mode 100644
index 0000000..1d64bf1
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportCommand.java
@@ -0,0 +1,137 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.cli.Command;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.client.cli.commands.AbstractCommand;
+
+@Command(name = "report")
+public class ReportCommand extends AbstractCommand {
+
+    private static final String HELP_MESSAGE = "Usage: report [options]\n"
+            + "  Options:\n"
+            + "    --help \n"
+            + "    --list \n"
+            + "    --read \n"
+            + "       Syntax: --read {REPORT-ID} {REPORT-ID} [...] \n"
+            + "    --delete \n"
+            + "       Syntax: --delete {REPORT-ID} {REPORT-ID} [...]\n"
+            + "    --execute \n"
+            + "       Syntax: --execute {REPORT-ID} \n"
+            + "    --read-execution \n"
+            + "       Syntax: --read-execution {EXECUTION-ID} {EXECUTION-ID} [...]\n"
+            + "    --delete-execution \n"
+            + "       Syntax: --delete-execution {EXECUTION-ID} {EXECUTION-ID} [...]\n"
+            + "    --export-execution-result \n"
+            + "       Syntax: --export-execution-result {EXECUTION-ID} {EXECUTION-ID} [...] {FORMAT}\n"
+            + "          Format: CSV / HTML / PDF / XML / RTF";
+
+    @Override
+    public void execute(final Input input) {
+        if (StringUtils.isBlank(input.getOption())) {
+            input.setOption(Options.HELP.getOptionName());
+        }
+
+        switch (Options.fromName(input.getOption())) {
+            case LIST:
+                new ReportList().list();
+                break;
+            case LIST_JOBS:
+                new ReportListJobs().list();
+                break;
+            case READ:
+                new ReportRead(input).read();
+                break;
+            case DELETE:
+                new ReportDelete(input).delete();
+                break;
+            case EXECUTE:
+                new ReportExecute(input).execute();
+                break;
+            case READ_EXECUTION:
+                new ReportReadExecution(input).read();
+                break;
+            case DELETE_EXECUTION:
+                new ReportDeleteExecution(input).delete();
+                break;
+            case EXPORT_EXECUTION_RESULT:
+                new ReportExportExecution(input).export();
+                break;
+            case HELP:
+                System.out.println(HELP_MESSAGE);
+                break;
+            default:
+                new ReportResultManager().defaultError(input.getOption(), HELP_MESSAGE);
+        }
+    }
+
+    @Override
+    public String getHelpMessage() {
+        return HELP_MESSAGE;
+    }
+
+    private enum Options {
+
+        HELP("--help"),
+        LIST("--list"),
+        LIST_JOBS("--list-jobs"),
+        READ("--read"),
+        DELETE("--delete"),
+        EXECUTE("--execute"),
+        READ_EXECUTION("--read-execution"),
+        DELETE_EXECUTION("--delete-execution"),
+        EXPORT_EXECUTION_RESULT("--export-execution-result");
+
+        private final String optionName;
+
+        Options(final String optionName) {
+            this.optionName = optionName;
+        }
+
+        public String getOptionName() {
+            return optionName;
+        }
+
+        public boolean equalsOptionName(final String otherName) {
+            return (otherName == null) ? false : optionName.equals(otherName);
+        }
+
+        public static Options fromName(final String name) {
+            Options optionToReturn = HELP;
+            for (final Options option : Options.values()) {
+                if (option.equalsOptionName(name)) {
+                    optionToReturn = option;
+                }
+            }
+            return optionToReturn;
+        }
+
+        public static List<String> toList() {
+            final List<String> options = new ArrayList<>();
+            for (final Options value : values()) {
+                options.add(value.getOptionName());
+            }
+            return options;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportDelete.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportDelete.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportDelete.java
new file mode 100644
index 0000000..012d04f
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportDelete.java
@@ -0,0 +1,58 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.common.lib.SyncopeClientException;
+
+public class ReportDelete extends AbstractReportCommand {
+
+    private static final String DELETE_HELP_MESSAGE = "report --delete {REPORT-ID} {REPORT-ID} [...]";
+
+    private final Input input;
+
+    public ReportDelete(final Input input) {
+        this.input = input;
+    }
+
+    public void delete() {
+        if (input.parameterNumber() >= 1) {
+            for (final String parameter : input.getParameters()) {
+                try {
+                    reportService.delete(Long.valueOf(parameter));
+                    reportResultManager.deletedMessage("Report", parameter);
+                } catch (final WebServiceException | SyncopeClientException ex) {
+                    if (ex.getMessage().startsWith("NotFound")) {
+                        reportResultManager.notFoundError("Report", parameter);
+                    } else if (ex.getMessage().startsWith("DataIntegrityViolation")) {
+                        reportResultManager.generic("You cannot delete report " + parameter);
+                    } else {
+                        reportResultManager.generic(ex.getMessage());
+                    }
+                } catch (final NumberFormatException ex) {
+                    reportResultManager.managerNumberFormatException("report", parameter);
+                }
+            }
+        } else {
+            reportResultManager.commandOptionError(DELETE_HELP_MESSAGE);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportDeleteExecution.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportDeleteExecution.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportDeleteExecution.java
new file mode 100644
index 0000000..4ab53fa
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportDeleteExecution.java
@@ -0,0 +1,61 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.common.lib.SyncopeClientException;
+
+public class ReportDeleteExecution extends AbstractReportCommand {
+
+    private static final String DELETE_EXECUTION_HELP_MESSAGE
+            = "report --delete-execution {EXECUTION-ID} {EXECUTION-ID} [...]";
+
+    private final Input input;
+
+    public ReportDeleteExecution(final Input input) {
+        this.input = input;
+    }
+
+    public void delete() {
+
+        if (input.parameterNumber() >= 1) {
+            for (final String parameter : input.getParameters()) {
+
+                try {
+                    reportService.deleteExecution(Long.valueOf(parameter));
+                    reportResultManager.deletedMessage("Report execution", parameter);
+                } catch (final WebServiceException | SyncopeClientException ex) {
+                    if (ex.getMessage().startsWith("NotFound")) {
+                        reportResultManager.notFoundError("Report", parameter);
+                    } else if (ex.getMessage().startsWith("DataIntegrityViolation")) {
+                        reportResultManager.generic("You cannot delete report " + parameter);
+                    } else {
+                        reportResultManager.generic(ex.getMessage());
+                    }
+                } catch (final NumberFormatException ex) {
+                    reportResultManager.managerNumberFormatException("report", parameter);
+                }
+            }
+        } else {
+            reportResultManager.commandOptionError(DELETE_EXECUTION_HELP_MESSAGE);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportExecute.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportExecute.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportExecute.java
new file mode 100644
index 0000000..311544d
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportExecute.java
@@ -0,0 +1,64 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import java.util.Arrays;
+import java.util.List;
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ReportExecTO;
+
+public class ReportExecute extends AbstractReportCommand {
+
+    private static final String EXECUTE_HELP_MESSAGE = "report --execute {REPORT-ID}";
+
+    private final Input input;
+
+    public ReportExecute(final Input input) {
+        this.input = input;
+    }
+
+    public void execute() {
+        if (input.parameterNumber() == 1) {
+
+            try {
+                final Long reportIdToExecute = Long.valueOf(input.firstParameter());
+                reportService.execute(reportIdToExecute);
+                final List<ReportExecTO> executionList
+                        = reportService.read(reportIdToExecute).getExecutions();
+                final ReportExecTO lastExecution = executionList.get(executionList.size() - 1);
+                reportResultManager.printReportExecution(Arrays.asList(lastExecution));
+            } catch (final WebServiceException | SyncopeClientException ex) {
+                if (ex.getMessage().startsWith("NotFound")) {
+                    reportResultManager.notFoundError("Report", input.firstParameter());
+                } else if (ex.getMessage().startsWith("DataIntegrityViolation")) {
+                    reportResultManager.generic("You cannot delete report " + input.firstParameter());
+                } else {
+                    reportResultManager.generic(ex.getMessage());
+                }
+            } catch (final NumberFormatException ex) {
+                reportResultManager.managerNumberFormatException("report", input.firstParameter());
+            }
+        } else {
+            reportResultManager.commandOptionError(EXECUTE_HELP_MESSAGE);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportExportExecution.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportExportExecution.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportExportExecution.java
new file mode 100644
index 0000000..c55d339
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportExportExecution.java
@@ -0,0 +1,100 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import java.io.IOException;
+import java.io.SequenceInputStream;
+import java.util.Arrays;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.client.cli.util.CommandUtils;
+import org.apache.syncope.client.cli.util.XMLUtils;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.types.ReportExecExportFormat;
+import org.xml.sax.SAXException;
+
+public class ReportExportExecution extends AbstractReportCommand {
+
+    private static final String EXPORT_EXECUTION_HELP_MESSAGE
+            = "report --export-execution-result {EXECUTION-ID} {EXECUTION-ID} [...] {FORMAT}\n"
+            + "          Format: CSV / HTML / PDF / XML / RTF";
+
+    private final Input input;
+
+    public ReportExportExecution(final Input input) {
+        this.input = input;
+    }
+
+    public void export() {
+        if (input.parameterNumber() >= 2) {
+            final String[] parameters = Arrays.copyOf(input.getParameters(), input.parameterNumber() - 1);
+            for (final String parameter : parameters) {
+                try {
+                    final ReportExecExportFormat format = ReportExecExportFormat.valueOf(input.lastParameter());
+                    final Long exportId = Long.valueOf(parameter);
+                    final SequenceInputStream report = (SequenceInputStream) reportService.
+                            exportExecutionResult(exportId, format).getEntity();
+                    switch (format) {
+                        case XML:
+                            final String xmlFinalName = "export_" + exportId + ".xml";
+                            XMLUtils.createXMLFile(report, xmlFinalName);
+                            reportResultManager.generic(xmlFinalName + " successfully created");
+                            break;
+                        case CSV:
+                            reportResultManager.generic(format + " doesn't supported");
+                            break;
+                        case PDF:
+                            reportResultManager.generic(format + " doesn't supported");
+                            break;
+                        case HTML:
+                            reportResultManager.generic(format + " doesn't supported");
+                            break;
+                        case RTF:
+                            reportResultManager.generic(format + " doesn't supported");
+                            break;
+                        default:
+                            reportResultManager.generic(format + " doesn't supported");
+                            break;
+                    }
+                } catch (final WebServiceException | SyncopeClientException ex) {
+                    ex.printStackTrace();
+                    if (ex.getMessage().startsWith("NotFound")) {
+                        reportResultManager.notFoundError("Report", parameter);
+                    } else {
+                        reportResultManager.generic(ex.getMessage());
+                    }
+                } catch (final NumberFormatException ex) {
+                    reportResultManager.managerNumberFormatException("report", parameter);
+                } catch (IOException | ParserConfigurationException | SAXException | TransformerException e) {
+                    reportResultManager.generic(" - Error creating " + "export_" + parameter + " " + e.getMessage());
+                } catch (final IllegalArgumentException ex) {
+                    reportResultManager.typeNotValidError(
+                            "format", input.firstParameter(),
+                            CommandUtils.fromEnumToArray(ReportExecExportFormat.class));
+                }
+                break;
+            }
+        } else {
+            reportResultManager.commandOptionError(EXPORT_EXECUTION_HELP_MESSAGE);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportList.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportList.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportList.java
new file mode 100644
index 0000000..d43f21f
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportList.java
@@ -0,0 +1,33 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import org.apache.syncope.common.lib.SyncopeClientException;
+
+public class ReportList extends AbstractReportCommand {
+
+    public void list() {
+        try {
+            reportResultManager.fromList(reportService.list());
+        } catch (final SyncopeClientException ex) {
+            reportResultManager.generic(ex.getMessage());
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportListJobs.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportListJobs.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportListJobs.java
new file mode 100644
index 0000000..9bc688e
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportListJobs.java
@@ -0,0 +1,35 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.types.JobStatusType;
+
+public class ReportListJobs extends AbstractReportCommand {
+
+    public void list() {
+        try {
+            for (final JobStatusType jobStatusType : JobStatusType.values()) {
+                reportResultManager.printReportExecution(reportService.listJobs(jobStatusType));
+            }
+        } catch (final SyncopeClientException ex) {
+            reportResultManager.generic(ex.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportRead.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportRead.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportRead.java
new file mode 100644
index 0000000..dd9760e
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportRead.java
@@ -0,0 +1,59 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ReportTO;
+
+public class ReportRead extends AbstractReportCommand {
+
+    private static final String READ_HELP_MESSAGE = "report --read {REPORT-ID} {REPORT-ID} [...]";
+
+    private final Input input;
+
+    public ReportRead(final Input input) {
+        this.input = input;
+    }
+
+    public void read() {
+        if (input.parameterNumber() >= 1) {
+            final List<ReportTO> reportTOs = new ArrayList<>();
+            for (final String parameter : input.getParameters()) {
+                try {
+                    reportTOs.add(reportService.read(Long.valueOf(parameter)));
+                } catch (final NumberFormatException ex) {
+                    reportResultManager.managerNumberFormatException("report", parameter);
+                } catch (final WebServiceException | SyncopeClientException ex) {
+                    if (ex.getMessage().startsWith("NotFound")) {
+                        reportResultManager.notFoundError("Report", parameter);
+                    } else {
+                        reportResultManager.generic(ex.getMessage());
+                    }
+                }
+            }
+            reportResultManager.fromList(reportTOs);
+        } else {
+            reportResultManager.commandOptionError(READ_HELP_MESSAGE);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportReadExecution.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportReadExecution.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportReadExecution.java
new file mode 100644
index 0000000..95c61cd
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportReadExecution.java
@@ -0,0 +1,62 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ReportExecTO;
+
+public class ReportReadExecution extends AbstractReportCommand {
+
+    private static final String READ_EXECUTION_HELP_MESSAGE
+            = "report --read-execution {EXECUTION-ID} {EXECUTION-ID} [...]";
+
+    private final Input input;
+
+    public ReportReadExecution(final Input input) {
+        this.input = input;
+    }
+
+    public void read() {
+        if (input.parameterNumber() >= 1) {
+            final List<ReportExecTO> reportExecTOs = new ArrayList<>();
+            for (final String parameter : input.getParameters()) {
+                try {
+                    reportExecTOs.add(reportService.readExecution(Long.valueOf(parameter)));
+                } catch (final WebServiceException | SyncopeClientException ex) {
+                    System.out.println("Error:");
+                    if (ex.getMessage().startsWith("NotFound")) {
+                        reportResultManager.notFoundError("Report", parameter);
+                    } else {
+                        reportResultManager.generic(ex.getMessage());
+                    }
+                } catch (final NumberFormatException ex) {
+                    reportResultManager.managerNumberFormatException("report", parameter);
+                }
+            }
+            reportResultManager.printReportExecution(reportExecTOs);
+        } else {
+            reportResultManager.commandOptionError(READ_EXECUTION_HELP_MESSAGE);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportResultManager.java
new file mode 100644
index 0000000..cc1b41a
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportResultManager.java
@@ -0,0 +1,75 @@
+/*
+ * 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.syncope.client.cli.commands.report;
+
+import java.util.List;
+import org.apache.syncope.client.cli.commands.CommonsResultManager;
+import org.apache.syncope.common.lib.report.AbstractReportletConf;
+import org.apache.syncope.common.lib.report.UserReportletConf;
+import org.apache.syncope.common.lib.to.ReportExecTO;
+import org.apache.syncope.common.lib.to.ReportTO;
+
+public class ReportResultManager extends CommonsResultManager {
+
+    public void fromList(final List<ReportTO> reportTOs) {
+        for (final ReportTO reportTO : reportTOs) {
+            printReport(reportTO);
+        }
+    }
+
+    private void printReport(final ReportTO reportTO) {
+        System.out.println(" > REPORT ID: " + reportTO.getKey());
+        System.out.println("    type: " + reportTO.getName());
+        System.out.println("    type: " + reportTO.getCronExpression());
+        System.out.println("    type: " + reportTO.getLatestExecStatus());
+        System.out.println("    type: " + reportTO.getLastExec());
+        System.out.println("    type: " + reportTO.getNextExec());
+        System.out.println("    type: " + reportTO.getStartDate());
+        System.out.println("    type: " + reportTO.getEndDate());
+        System.out.println("    CONF:");
+        for (final AbstractReportletConf reportletConf : reportTO.getReportletConfs()) {
+            printReportletConf(reportletConf);
+        }
+        System.out.println("    EXECUTION:");
+        printReportExecution(reportTO.getExecutions());
+    }
+
+    private void printReportletConf(final AbstractReportletConf reportletConf) {
+        if (reportletConf instanceof UserReportletConf) {
+            final UserReportletConf userReportletConf = (UserReportletConf) reportletConf;
+            System.out.println("       name: " + userReportletConf.getName());
+            System.out.println("       features: " + userReportletConf.getFeatures());
+            System.out.println("       plain attributes: " + userReportletConf.getPlainAttrs());
+            System.out.println("       derived attributes: " + userReportletConf.getDerAttrs());
+            System.out.println("       virtual attributes: " + userReportletConf.getVirAttrs());
+            System.out.println("       matching condition: " + userReportletConf.getMatchingCond());
+        }
+    }
+
+    public void printReportExecution(final List<ReportExecTO> reportExecTOs) {
+        for (final ReportExecTO reportExecTO : reportExecTOs) {
+            System.out.println("       REPORT EXEC ID: " + reportExecTO.getKey());
+            System.out.println("       status: " + reportExecTO.getStatus());
+            System.out.println("       message: " + reportExecTO.getMessage());
+            System.out.println("       start date: " + reportExecTO.getStartDate());
+            System.out.println("       end date: " + reportExecTO.getEndDate());
+            System.out.println("       report id: " + reportExecTO.getReport());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java
index 8880dd3..5963eb8 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaResultManager.java
@@ -21,7 +21,7 @@ package org.apache.syncope.client.cli.commands.schema;
 import java.util.Arrays;
 import java.util.LinkedList;
 import org.apache.syncope.client.cli.commands.CommonsResultManager;
-import org.apache.syncope.client.cli.messages.Table;
+import org.apache.syncope.client.cli.view.Table;
 import org.apache.syncope.common.lib.to.AbstractSchemaTO;
 import org.apache.syncope.common.lib.to.DerSchemaTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/messages/Messages.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/messages/Messages.java b/client/cli/src/main/java/org/apache/syncope/client/cli/messages/Messages.java
deleted file mode 100644
index 35550fd..0000000
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/messages/Messages.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * 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.syncope.client.cli.messages;
-
-public final class Messages {
-
-    private static final String OPTION_COMMAND_MESSAGE_TEMPLATE = "\n - Usage: %s\n";
-
-    private static final String CREATED_MESSAGE_TEMPLATE = "%s %s successfully created";
-
-    private static final String UPDATED_MESSAGE_TEMPLATE = "%s %s successfully updated";
-
-    private static final String DELETED_MESSAGE_TEMPLATE = "%s %s successfully deleted";
-
-    private static final String DOESNT_EXIST_MESSAGE_TEMPLATE = "%s %s doesn't exist";
-
-    private static final String TYPE_NOT_VALID_MESSAGE_TEMPLATE = "%s isn't a valid %s type, try with: %s";
-
-    private static final String ID_NOT_NUMBER_MESSAGE_TEMPLATE = "Error reading %s. It isn't a valid %s "
-            + "id because it isn't a long value";
-
-    private static final String NOT_BOOLEAN_MESSAGE_TEMPLATE = "Error reading %s. It isn't a valid %s "
-            + "value because it isn't a boolean value";
-
-    private static final String DEFAULT_MESSAGE_TEMPLATE = "%s is not a valid option. \n\b %s";
-
-    public static void printCommandOptionMessage(final String message) {
-        System.out.println(String.format(OPTION_COMMAND_MESSAGE_TEMPLATE, message));
-    }
-
-    public static void printMessage(final String... messages) {
-        final StringBuilder messageBuilder = new StringBuilder("\n");
-        for (final String message : messages) {
-            messageBuilder.append(" - ").append(message).append("\n");
-        }
-        System.out.println(messageBuilder.toString());
-    }
-
-    public static void printNofFoundMessage(final String what, final String key) {
-        printMessage(String.format(DOESNT_EXIST_MESSAGE_TEMPLATE, what, key));
-    }
-
-    public static void printCreatedMessage(final String what, final String key) {
-        printMessage(String.format(CREATED_MESSAGE_TEMPLATE, what, key));
-    }
-
-    public static void printUpdatedMessage(final String what, final String key) {
-        printMessage(String.format(UPDATED_MESSAGE_TEMPLATE, what, key));
-    }
-
-    public static void printDeletedMessage(final String what, final String key) {
-        printMessage(String.format(DELETED_MESSAGE_TEMPLATE, what, key));
-    }
-
-    public static void printIdNotNumberDeletedMessage(final String what, final String key) {
-        printMessage(String.format(ID_NOT_NUMBER_MESSAGE_TEMPLATE, key, what));
-    }
-
-    public static void printNotBooleanDeletedMessage(final String what, final String key) {
-        printMessage(String.format(NOT_BOOLEAN_MESSAGE_TEMPLATE, key, what));
-    }
-
-    public static void printTypeNotValidMessage(final String what, final String key, final String[] types) {
-        final StringBuilder typesBuilder = new StringBuilder();
-        for (final String type : types) {
-            typesBuilder.append("\n     *** ").append(type);
-        }
-        printMessage(String.format(TYPE_NOT_VALID_MESSAGE_TEMPLATE, key, what, typesBuilder.toString()));
-    }
-
-    public static void printDefaultMessage(final String option, final String helpMessage) {
-        printMessage(String.format(DEFAULT_MESSAGE_TEMPLATE, option, helpMessage));
-    }
-
-    private Messages() {
-
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/messages/Table.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/messages/Table.java b/client/cli/src/main/java/org/apache/syncope/client/cli/messages/Table.java
deleted file mode 100644
index 311682c..0000000
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/messages/Table.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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.syncope.client.cli.messages;
-
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.Set;
-import org.apache.commons.lang3.StringUtils;
-
-public final class Table {
-
-    private static final String TABLE_TITLE_FORMAT = "#  %s  #\n";
-
-    private final String title;
-
-    private final LinkedList<String> headers;
-
-    private final Set<LinkedList<String>> values;
-
-    private int columnsNumber;
-
-    private String[] tmpValuesArray;
-
-    private String tableContentFormat;
-
-    private int[] columnsSize;
-
-    private int tableWidth;
-
-    private String border = "";
-
-    private Table(
-            final String title,
-            final LinkedList<String> headers,
-            final Set<LinkedList<String>> values) {
-        this.title = title;
-        this.headers = headers;
-        this.values = values;
-    }
-
-    public void print() {
-        columnsNumber = headers.size();
-        tmpValuesArray = new String[columnsNumber];
-
-        buildTableContentFormat();
-        initializeColumnSize();
-        countTableWidth();
-
-        printBorder();
-        printTitle();
-        printBorder();
-        printHeaders();
-        printBorder();
-        printeContent();
-        printBorder();
-    }
-
-    private void buildTableContentFormat() {
-        final StringBuilder tableContentFormatBuilder = new StringBuilder("#");
-        for (int s = 0; s < columnsNumber; s++) {
-            tableContentFormatBuilder.append("  %s  #");
-        }
-        tableContentFormatBuilder.append("\n");
-        tableContentFormat = tableContentFormatBuilder.toString();
-    }
-
-    private void initializeColumnSize() {
-        columnsSize = new int[columnsNumber];
-        for (int j = 0; j < columnsSize.length; j++) {
-            columnsSize[j] = 0;
-        }
-
-        for (int i = 0; i < columnsSize.length; i++) {
-            if (headers.get(i).length() > columnsSize[i]) {
-                columnsSize[i] = headers.get(i).length();
-            }
-        }
-
-        for (final LinkedList<String> value : values) {
-            for (int j = 0; j < columnsSize.length; j++) {
-                if (value.get(j) != null && value.get(j).length() > columnsSize[j]) {
-                    columnsSize[j] = value.get(j).length();
-                }
-            }
-        }
-    }
-
-    private void countTableWidth() {
-        int maxColumnValueSum = 0;
-        for (int j = 0; j < columnsSize.length; j++) {
-            maxColumnValueSum = maxColumnValueSum + columnsSize[j];
-        }
-
-        tableWidth = maxColumnValueSum + (columnsNumber * (2 + 2)) + columnsNumber + 1;
-    }
-
-    private void printBorder() {
-        if (border.isEmpty()) {
-            final StringBuilder borderBuilder = new StringBuilder();
-            for (int j = 0; j < tableWidth; j++) {
-                borderBuilder.append("#");
-            }
-            border = borderBuilder.toString();
-        }
-
-        System.out.println(border);
-    }
-
-    private void printTitle() {
-        System.out.format(TABLE_TITLE_FORMAT, StringUtils.center(" ", tableWidth - 6));
-        System.out.format(TABLE_TITLE_FORMAT, StringUtils.center(title.toUpperCase(), tableWidth - 6));
-        System.out.format(TABLE_TITLE_FORMAT, StringUtils.center(" ", tableWidth - 6));
-    }
-
-    private void printHeaders() {
-        printColumnSpace();
-
-        for (int h = 0; h < columnsNumber; h++) {
-            tmpValuesArray[h] = StringUtils.center(headers.get(h).toUpperCase(), columnsSize[h]);
-        }
-
-        System.out.format(tableContentFormat, tmpValuesArray);
-
-        printColumnSpace();
-    }
-
-    private void printeContent() {
-        printColumnSpace();
-
-        for (final LinkedList<String> value : values) {
-            for (int j = 0; j < columnsNumber; j++) {
-                if (value.get(j) == null) {
-                    tmpValuesArray[j] = StringUtils.center("null", columnsSize[j]);
-                } else {
-                    tmpValuesArray[j] = StringUtils.center(value.get(j), columnsSize[j]);
-                }
-            }
-            System.out.format(tableContentFormat, tmpValuesArray);
-        }
-
-        printColumnSpace();
-    }
-
-    private void printColumnSpace() {
-        for (int h = 0; h < columnsNumber; h++) {
-            tmpValuesArray[h] = StringUtils.center(" ", columnsSize[h]);
-        }
-
-        System.out.format(tableContentFormat, tmpValuesArray);
-    }
-
-    public static class TableBuilder {
-
-        private final LinkedList<String> headers = new LinkedList<>();
-
-        private final Set<LinkedList<String>> values = new LinkedHashSet<>();
-
-        private final String title;
-
-        public TableBuilder(final String title) {
-            this.title = title;
-        }
-
-        public TableBuilder header(final String header) {
-            headers.add(header);
-            return this;
-        }
-
-        public TableBuilder rowValues(final LinkedList<String> row) {
-            values.add(row);
-            return this;
-        }
-
-        public Table build() {
-            return new Table(title, headers, values);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/7a11bf3b/client/cli/src/main/java/org/apache/syncope/client/cli/messages/TwoColumnTable.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/messages/TwoColumnTable.java b/client/cli/src/main/java/org/apache/syncope/client/cli/messages/TwoColumnTable.java
deleted file mode 100644
index df5bbea..0000000
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/messages/TwoColumnTable.java
+++ /dev/null
@@ -1,262 +0,0 @@
-
-/*
- * 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.syncope.client.cli.messages;
-
-import java.util.Map;
-
-public class TwoColumnTable {
-
-    private static final int TABLE_BORDER = 1;
-
-    private static final int MIN_COLUMN_SPACE = 2;
-
-    private static final int MIN_COLUMN_SIZE = 5;
-
-    private int tableWidth;
-
-    private int firstColumntContentWidth;
-
-    private int secondColumntContentWidth;
-
-    private final String title;
-
-    private final String firstColumnHeader;
-
-    private int firstColumnMaxWidth;
-
-    private final String secondColumnHeader;
-
-    private int secondColumnMaxWidth;
-
-    public TwoColumnTable(final String title,
-            final String firstColumnHeader,
-            final int firstColumnMaxWidth,
-            final String secondColumnHeader,
-            final int secondColumnMaxWidth) {
-
-        this.firstColumnHeader = firstColumnHeader.toUpperCase();
-
-        if (firstColumnMaxWidth < MIN_COLUMN_SIZE) {
-            this.firstColumnMaxWidth = MIN_COLUMN_SIZE;
-        } else {
-            this.firstColumnMaxWidth = firstColumnMaxWidth;
-        }
-
-        this.secondColumnHeader = secondColumnHeader.toUpperCase();
-
-        if (secondColumnMaxWidth < MIN_COLUMN_SIZE) {
-            this.secondColumnMaxWidth = MIN_COLUMN_SIZE;
-        } else {
-            this.secondColumnMaxWidth = secondColumnMaxWidth;
-        }
-
-        tableWidth = (TABLE_BORDER * 3) + (MIN_COLUMN_SPACE * 4) + firstColumnMaxWidth + secondColumnMaxWidth;
-
-        if (title.length() > firstColumnMaxWidth + secondColumnMaxWidth) {
-            tableWidth = (TABLE_BORDER * 3) + (MIN_COLUMN_SPACE * 4) + title.length();
-        }
-
-        firstColumntContentWidth = (MIN_COLUMN_SPACE * 2) + firstColumnMaxWidth;
-        secondColumntContentWidth = (MIN_COLUMN_SPACE * 2) + secondColumnMaxWidth;
-
-        this.title = title.toUpperCase();
-    }
-
-    public void printTable(final Map<String, String> value) {
-
-        if (value.isEmpty()) {
-            firstColumnMaxWidth = firstColumnHeader.length();
-            secondColumnMaxWidth = secondColumnHeader.length();
-            firstColumntContentWidth = (MIN_COLUMN_SPACE * 2) + firstColumnMaxWidth;
-            secondColumntContentWidth = (MIN_COLUMN_SPACE * 2) + secondColumnMaxWidth;
-            tableWidth = (TABLE_BORDER * 3) + (MIN_COLUMN_SPACE * 4) + firstColumnMaxWidth + secondColumnMaxWidth;
-            if (title.length() > firstColumnMaxWidth + secondColumnMaxWidth) {
-                tableWidth = (TABLE_BORDER * 3) + (MIN_COLUMN_SPACE * 4) + title.length();
-            }
-        }
-
-        final StringBuilder table = new StringBuilder();
-
-// ################ BORDER-TOP ################
-        for (int i = 0; i < tableWidth; i++) {
-            table.append("#");
-        }
-        table.append("\n");
-// ################ BORDER-TOP ################
-
-// ################ TABLE-TITLE ################
-        table.append("#");
-        for (int i = 0; i < titleFirstSpace(title); i++) {
-            table.append(" ");
-        }
-        table.append(title);
-        for (int i = 0; i < titleSecondSpace(title); i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        table.append("\n");
-// ################ TABLE-TITLE ################
-
-// ################ BORDER-TOP ################
-        for (int i = 0; i < tableWidth; i++) {
-            table.append("#");
-        }
-        table.append("\n");
-// ################ BORDER-TOP ################
-
-// ################ LIST-SPACE ################
-        table.append("#");
-        for (int i = 0; i < firstColumntContentWidth; i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        for (int i = 0; i < secondColumntContentWidth; i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        table.append("\n");
-// ################ LIST-SPACE ################
-
-// ################ HEADER-TITLE ################
-        table.append("#");
-        for (int i = 0; i < firstColumnFirstSpace(firstColumnHeader); i++) {
-            table.append(" ");
-        }
-        table.append(firstColumnHeader);
-        for (int i = 0; i < firstColumnSecondSpace(firstColumnHeader); i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        for (int i = 0; i < secondColumnFirstSpace(secondColumnHeader); i++) {
-            table.append(" ");
-        }
-        table.append(secondColumnHeader);
-        for (int i = 0; i < secondColumnSecondSpace(secondColumnHeader); i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        table.append("\n");
-// ################ HEADER-TITLE ################
-
-// ################ LIST-SPACE ################
-        table.append("#");
-        for (int i = 0; i < firstColumntContentWidth; i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        for (int i = 0; i < secondColumntContentWidth; i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        table.append("\n");
-// ################ LIST-SPACE ################
-
-// ################ BORDER-TOP ################
-        for (int i = 0; i < tableWidth; i++) {
-            table.append("#");
-        }
-        table.append("\n");
-// ################ BORDER-TOP ################
-
-// ################ LIST-SPACE ################
-        table.append("#");
-        for (int i = 0; i < firstColumntContentWidth; i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        for (int i = 0; i < secondColumntContentWidth; i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        table.append("\n");
-// ################ LIST-SPACE ################
-
-// ################ CONTENT ################
-        for (final Map.Entry<String, String> entrySet : value.entrySet()) {
-            final String firstColumnValue = entrySet.getKey();
-            final String secondColumnValue = entrySet.getValue();
-            table.append("#");
-            for (int i = 0; i < firstColumnFirstSpace(firstColumnValue); i++) {
-                table.append(" ");
-            }
-            table.append(firstColumnValue);
-            for (int i = 0; i < firstColumnSecondSpace(firstColumnValue); i++) {
-                table.append(" ");
-            }
-            table.append("#");
-            for (int i = 0; i < secondColumnFirstSpace(secondColumnValue); i++) {
-                table.append(" ");
-            }
-            table.append(secondColumnValue);
-            for (int i = 0; i < secondColumnSecondSpace(secondColumnValue); i++) {
-                table.append(" ");
-            }
-            table.append("#");
-            table.append("\n");
-        }
-// ################ CONTENT ################
-
-// ################ LIST-SPACE ################
-        table.append("#");
-        for (int i = 0; i < firstColumntContentWidth; i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        for (int i = 0; i < secondColumntContentWidth; i++) {
-            table.append(" ");
-        }
-        table.append("#");
-        table.append("\n");
-// ################ LIST-SPACE ################
-
-// ################ BORDER-BOTTOM ################
-        for (int i = 0; i < tableWidth; i++) {
-            table.append("#");
-        }
-// ################ BORDER-BOTTOM ################
-
-        System.out.println(table.toString() + "\n");
-    }
-
-    private int titleFirstSpace(final String wordToPrint) {
-        return ((tableWidth - 2) - (wordToPrint.length())) / 2;
-    }
-
-    private int titleSecondSpace(final String wordToPrint) {
-        return tableWidth - 2 - (titleFirstSpace(wordToPrint) + wordToPrint.length());
-    }
-
-    private int firstColumnFirstSpace(final String wordToPrint) {
-        return (MIN_COLUMN_SPACE * 2 + (firstColumnMaxWidth - wordToPrint.length())) / 2;
-    }
-
-    private int firstColumnSecondSpace(final String wordToPrint) {
-        return firstColumntContentWidth - (firstColumnFirstSpace(wordToPrint) + wordToPrint.length());
-    }
-
-    private int secondColumnFirstSpace(final String wordToPrint) {
-        return (MIN_COLUMN_SPACE * 2 + (secondColumnMaxWidth - wordToPrint.length())) / 2;
-    }
-
-    private int secondColumnSecondSpace(final String wordToPrint) {
-        return secondColumntContentWidth - (secondColumnFirstSpace(wordToPrint) + wordToPrint.length());
-    }
-
-}


Mime
View raw message