You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by fm...@apache.org on 2015/10/30 12:34:51 UTC

[12/50] [abbrv] syncope git commit: Fixed SYNCOPE-580, refactoring and added realm stack, SYNCOPE-158

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/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
index 1d3e5de..7fca5c0 100644
--- 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
@@ -24,7 +24,7 @@ public class ReportList extends AbstractReportCommand {
 
     public void list() {
         try {
-            reportResultManager.fromValueToView(reportService.list());
+            reportResultManager.fromValueToView(reportSyncopeOperations.list());
         } catch (final SyncopeClientException ex) {
             reportResultManager.generic(ex.getMessage());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/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
index 9bc688e..5b13cbf 100644
--- 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
@@ -26,7 +26,7 @@ public class ReportListJobs extends AbstractReportCommand {
     public void list() {
         try {
             for (final JobStatusType jobStatusType : JobStatusType.values()) {
-                reportResultManager.printReportExecution(reportService.listJobs(jobStatusType));
+                reportResultManager.printReportExecution(reportSyncopeOperations.listJobs(jobStatusType));
             }
         } catch (final SyncopeClientException ex) {
             reportResultManager.generic(ex.getMessage());

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/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
index d1ab975..9a1ebc8 100644
--- 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
@@ -40,9 +40,9 @@ public class ReportRead extends AbstractReportCommand {
             final List<ReportTO> reportTOs = new ArrayList<>();
             for (final String parameter : input.getParameters()) {
                 try {
-                    reportTOs.add(reportService.read(Long.valueOf(parameter)));
+                    reportTOs.add(reportSyncopeOperations.read(parameter));
                 } catch (final NumberFormatException ex) {
-                    reportResultManager.managerNumberFormatException("report", parameter);
+                    reportResultManager.numberFormatException("report", parameter);
                 } catch (final WebServiceException | SyncopeClientException ex) {
                     if (ex.getMessage().startsWith("NotFound")) {
                         reportResultManager.notFoundError("Report", parameter);

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/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
index 95c61cd..45d1c54 100644
--- 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
@@ -41,7 +41,7 @@ public class ReportReadExecution extends AbstractReportCommand {
             final List<ReportExecTO> reportExecTOs = new ArrayList<>();
             for (final String parameter : input.getParameters()) {
                 try {
-                    reportExecTOs.add(reportService.readExecution(Long.valueOf(parameter)));
+                    reportExecTOs.add(reportSyncopeOperations.readExecution(parameter));
                 } catch (final WebServiceException | SyncopeClientException ex) {
                     System.out.println("Error:");
                     if (ex.getMessage().startsWith("NotFound")) {
@@ -50,7 +50,7 @@ public class ReportReadExecution extends AbstractReportCommand {
                         reportResultManager.generic(ex.getMessage());
                     }
                 } catch (final NumberFormatException ex) {
-                    reportResultManager.managerNumberFormatException("report", parameter);
+                    reportResultManager.numberFormatException("report", parameter);
                 }
             }
             reportResultManager.printReportExecution(reportExecTOs);

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportSyncopeOperations.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportSyncopeOperations.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportSyncopeOperations.java
new file mode 100644
index 0000000..1cf4514
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/report/ReportSyncopeOperations.java
@@ -0,0 +1,65 @@
+/*
+ * 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 javax.ws.rs.core.Response;
+import org.apache.syncope.client.cli.SyncopeServices;
+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;
+
+public class ReportSyncopeOperations {
+
+    private final ReportService reportService = SyncopeServices.get(ReportService.class);
+
+    public ReportExecTO readExecution(final String executionid) {
+        return reportService.readExecution(Long.valueOf(executionid));
+    }
+
+    public ReportTO read(final String reportId) {
+        return reportService.read(Long.valueOf(reportId));
+    }
+
+    public List<ReportExecTO> listJobs(final JobStatusType jobStatusType) {
+        return reportService.listJobs(jobStatusType);
+    }
+
+    public List<ReportTO> list() {
+        return reportService.list();
+    }
+
+    public Response exportExecutionResult(final String executionKey, final ReportExecExportFormat fmt) {
+        return reportService.exportExecutionResult(Long.valueOf(executionKey), fmt);
+    }
+
+    public void execute(final String reportId) {
+        reportService.execute(Long.valueOf(reportId));
+    }
+
+    public void deleteExecution(final String executionId) {
+        reportService.deleteExecution(Long.valueOf(executionId));
+    }
+
+    public void delete(final String reportId) {
+        reportService.delete(Long.valueOf(reportId));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/AbstractResourceCommand.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/AbstractResourceCommand.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/AbstractResourceCommand.java
index 85d4a2d..943f405 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/AbstractResourceCommand.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/AbstractResourceCommand.java
@@ -18,13 +18,10 @@
  */
 package org.apache.syncope.client.cli.commands.resource;
 
-import org.apache.syncope.client.cli.SyncopeServices;
-import org.apache.syncope.common.rest.api.service.ResourceService;
-
 public abstract class AbstractResourceCommand {
 
-    protected final ResourceService resourceService = SyncopeServices.get(ResourceService.class);
-
+    protected final ResourceSyncopeOperations resourceSyncopeOperations = new ResourceSyncopeOperations();
+    
     protected final ResourceResultManager resourceResultManager = new ResourceResultManager();
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceDelete.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceDelete.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceDelete.java
index c3ecd84..9068b7d 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceDelete.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceDelete.java
@@ -35,10 +35,10 @@ public class ResourceDelete extends AbstractResourceCommand {
         if (input.getParameters().length >= 1) {
             for (final String parameter : input.getParameters()) {
                 try {
-                    resourceService.delete(parameter);
+                    resourceSyncopeOperations.delete(parameter);
                     resourceResultManager.deletedMessage("resource", parameter);
                 } catch (final NumberFormatException ex) {
-                    resourceResultManager.managerNumberFormatException("resource", parameter);
+                    resourceResultManager.numberFormatException("resource", parameter);
                 } catch (final SyncopeClientException | WebServiceException ex) {
                     if (ex.getMessage().startsWith("NotFound")) {
                         resourceResultManager.notFoundError("Resource", parameter);

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceList.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceList.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceList.java
index 85f05f5..27f0d74 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceList.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceList.java
@@ -24,7 +24,7 @@ public class ResourceList extends AbstractResourceCommand {
 
     public void list() {
         try {
-            resourceResultManager.toView(resourceService.list());
+            resourceResultManager.toView(resourceSyncopeOperations.list());
         } catch (final SyncopeClientException ex) {
             resourceResultManager.generic(ex.getMessage());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceRead.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceRead.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceRead.java
index 3790c02..85cd669 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceRead.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceRead.java
@@ -39,9 +39,9 @@ public class ResourceRead extends AbstractResourceCommand {
             final List<ResourceTO> resourceTOs = new ArrayList<>();
             for (final String parameter : input.getParameters()) {
                 try {
-                    resourceTOs.add(resourceService.read(parameter));
+                    resourceTOs.add(resourceSyncopeOperations.read(parameter));
                 } catch (final NumberFormatException ex) {
-                    resourceResultManager.managerNumberFormatException("resource", parameter);
+                    resourceResultManager.numberFormatException("resource", parameter);
                 } catch (final SyncopeClientException | WebServiceException ex) {
                     if (ex.getMessage().startsWith("NotFound")) {
                         resourceResultManager.notFoundError("Resource", parameter);

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceResultManager.java
index 91847f4..d598910 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceResultManager.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceResultManager.java
@@ -54,6 +54,7 @@ public class ResourceResultManager extends CommonsResultManager {
         System.out.println("    delete trace level: " + resourceTO.getDeleteTraceLevel());
         System.out.println("    update trace level: " + resourceTO.getUpdateTraceLevel());
         System.out.println("    sync trace level: " + resourceTO.getSyncTraceLevel());
+        System.out.println("");
     }
 
     private void printProvision(final List<ProvisionTO> provisionTOs) {
@@ -66,14 +67,12 @@ public class ResourceResultManager extends CommonsResultManager {
             System.out.println("       MAPPING: ");
             printMapping(provisionTO.getMapping());
         }
-        System.out.println("");
     }
 
     private void printMapping(final MappingTO mappingTO) {
         System.out.println("          ConnObjectLink: " + mappingTO.getConnObjectLink());
         System.out.println("          MAPPING ITEM: ");
         printMappingItem(mappingTO.getItems());
-        System.out.println("");
     }
 
     private void printMappingItem(final List<MappingItemTO> mappingItemTOs) {
@@ -88,8 +87,8 @@ public class ResourceResultManager extends CommonsResultManager {
             System.out.println("             purpose: " + mappingItemTO.getPurpose());
             System.out.println("             connector object key: " + mappingItemTO.isConnObjectKey());
             System.out.println("             password: " + mappingItemTO.isPassword());
+            System.out.println("");
         }
-        System.out.println("");
     }
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceSyncopeOperations.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceSyncopeOperations.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceSyncopeOperations.java
new file mode 100644
index 0000000..9ddedf8
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/resource/ResourceSyncopeOperations.java
@@ -0,0 +1,51 @@
+/*
+ * 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.resource;
+
+import java.util.List;
+import org.apache.syncope.client.cli.SyncopeServices;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ResourceTO;
+import org.apache.syncope.common.rest.api.service.ResourceService;
+
+public class ResourceSyncopeOperations {
+
+    private final ResourceService resourceService = SyncopeServices.get(ResourceService.class);
+
+    public void delete(final String name) {
+        resourceService.delete(name);
+    }
+
+    public List<ResourceTO> list() {
+        return resourceService.list();
+    }
+
+    public ResourceTO read(final String name) {
+        return resourceService.read(name);
+    }
+
+    public boolean exists(final String name) {
+        try {
+            read(name);
+            return true;
+        } catch (final SyncopeClientException ex) {
+            return false;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/AbstractSchemaCommand.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/AbstractSchemaCommand.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/AbstractSchemaCommand.java
index 3074135..96dae04 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/AbstractSchemaCommand.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/AbstractSchemaCommand.java
@@ -18,13 +18,10 @@
  */
 package org.apache.syncope.client.cli.commands.schema;
 
-import org.apache.syncope.client.cli.SyncopeServices;
-import org.apache.syncope.common.rest.api.service.SchemaService;
-
 public abstract class AbstractSchemaCommand {
 
-    protected final SchemaService schemaService = SyncopeServices.get(SchemaService.class);
-    
+    protected final SchemaSyncopeOperations schemaSyncopeOperations = new SchemaSyncopeOperations();
+
     protected final SchemaResultManager schemaResultManager = new SchemaResultManager();
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaDelete.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaDelete.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaDelete.java
index 9cf6fe2..0850e2f 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaDelete.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaDelete.java
@@ -41,7 +41,7 @@ public class SchemaDelete extends AbstractSchemaCommand {
             final String[] parameters = Arrays.copyOfRange(input.getParameters(), 1, input.parameterNumber());
             try {
                 for (final String parameter : parameters) {
-                    schemaService.delete(SchemaType.valueOf(input.firstParameter()), parameter);
+                    schemaSyncopeOperations.delete(SchemaType.valueOf(input.firstParameter()), parameter);
                     schemaResultManager.deletedMessage("Schema", parameter);
                 }
             } catch (final SyncopeClientException | WebServiceException ex) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaList.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaList.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaList.java
index 5f51604..404a487 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaList.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaList.java
@@ -41,7 +41,7 @@ public class SchemaList extends AbstractSchemaCommand {
             try {
                 final SchemaType schemaType = SchemaType.valueOf(input.firstParameter());
                 final LinkedList<AbstractSchemaTO> schemaTOs = new LinkedList<>();
-                for (final AbstractSchemaTO schemaTO : schemaService.list(schemaType)) {
+                for (final AbstractSchemaTO schemaTO : schemaSyncopeOperations.list(schemaType)) {
                     schemaTOs.add(schemaTO);
                 }
                 switch (schemaType) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListAll.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListAll.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListAll.java
index 5d00adb..57d95a1 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListAll.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListAll.java
@@ -30,7 +30,7 @@ public class SchemaListAll extends AbstractSchemaCommand {
         try {
             for (final SchemaType schemaType : SchemaType.values()) {
                 final LinkedList<AbstractSchemaTO> schemaTOs = new LinkedList<>();
-                for (final AbstractSchemaTO schemaTO : schemaService.list(schemaType)) {
+                for (final AbstractSchemaTO schemaTO : schemaSyncopeOperations.list(schemaType)) {
                     schemaTOs.add(schemaTO);
                 }
                 switch (schemaType) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListDerived.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListDerived.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListDerived.java
index 8cdb501..ee90327 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListDerived.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListDerived.java
@@ -22,14 +22,13 @@ import java.util.LinkedList;
 import javax.xml.ws.WebServiceException;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AbstractSchemaTO;
-import org.apache.syncope.common.lib.types.SchemaType;
 
 public class SchemaListDerived extends AbstractSchemaCommand {
 
     public void listDerived() {
         try {
             final LinkedList<AbstractSchemaTO> schemaTOs = new LinkedList<>();
-            for (final AbstractSchemaTO schemaTO : schemaService.list(SchemaType.DERIVED)) {
+            for (final AbstractSchemaTO schemaTO : schemaSyncopeOperations.listDerived()) {
                 schemaTOs.add(schemaTO);
             }
             schemaResultManager.fromListDerived(schemaTOs);

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListPlain.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListPlain.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListPlain.java
index e4160a7..6fa9ad6 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListPlain.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListPlain.java
@@ -22,14 +22,13 @@ import java.util.LinkedList;
 import javax.xml.ws.WebServiceException;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AbstractSchemaTO;
-import org.apache.syncope.common.lib.types.SchemaType;
 
 public class SchemaListPlain extends AbstractSchemaCommand {
 
     public void listPlain() {
         try {
             final LinkedList<AbstractSchemaTO> schemaTOs = new LinkedList<>();
-            for (final AbstractSchemaTO schemaTO : schemaService.list(SchemaType.PLAIN)) {
+            for (final AbstractSchemaTO schemaTO : schemaSyncopeOperations.listPlain()) {
                 schemaTOs.add(schemaTO);
             }
             schemaResultManager.fromListPlain(schemaTOs);

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListVirtual.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListVirtual.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListVirtual.java
index 7b1bf24..74b5b6c 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListVirtual.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaListVirtual.java
@@ -22,14 +22,13 @@ import java.util.LinkedList;
 import javax.xml.ws.WebServiceException;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AbstractSchemaTO;
-import org.apache.syncope.common.lib.types.SchemaType;
 
 public class SchemaListVirtual extends AbstractSchemaCommand {
 
     public void listVirtual() {
         try {
             final LinkedList<AbstractSchemaTO> schemaTOs = new LinkedList<>();
-            for (final AbstractSchemaTO schemaTO : schemaService.list(SchemaType.VIRTUAL)) {
+            for (final AbstractSchemaTO schemaTO : schemaSyncopeOperations.listVirtual()) {
                 schemaTOs.add(schemaTO);
             }
             schemaResultManager.fromListVirtual(schemaTOs);

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaRead.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaRead.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaRead.java
index 97f1029..d84444d 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaRead.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaRead.java
@@ -45,7 +45,7 @@ public class SchemaRead extends AbstractSchemaCommand {
                 final SchemaType schemaType = SchemaType.valueOf(input.firstParameter());
                 final LinkedList<AbstractSchemaTO> schemaTOs = new LinkedList<>();
                 for (final String parameter : parameters) {
-                    schemaTOs.add(schemaService.read(schemaType, parameter));
+                    schemaTOs.add(schemaSyncopeOperations.read(schemaType, parameter));
                 }
                 switch (schemaType) {
                     case PLAIN:

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaSyncopeOperations.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaSyncopeOperations.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaSyncopeOperations.java
new file mode 100644
index 0000000..c8f0a6d
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/schema/SchemaSyncopeOperations.java
@@ -0,0 +1,54 @@
+/*
+ * 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.schema;
+
+import java.util.List;
+import org.apache.syncope.client.cli.SyncopeServices;
+import org.apache.syncope.common.lib.to.AbstractSchemaTO;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.syncope.common.rest.api.service.SchemaService;
+
+public class SchemaSyncopeOperations {
+
+    private final SchemaService schemaService = SyncopeServices.get(SchemaService.class);
+
+    public <T extends AbstractSchemaTO> T read(final SchemaType schemaType, final String schemaName) {
+        return schemaService.read(schemaType, schemaName);
+    }
+
+    public <T extends AbstractSchemaTO> List<T> list(final SchemaType schemaType) {
+        return schemaService.list(schemaType);
+    }
+
+    public <T extends AbstractSchemaTO> List<T> listVirtual() {
+        return schemaService.list(SchemaType.VIRTUAL);
+    }
+
+    public <T extends AbstractSchemaTO> List<T> listPlain() {
+        return schemaService.list(SchemaType.PLAIN);
+    }
+
+    public <T extends AbstractSchemaTO> List<T> listDerived() {
+        return schemaService.list(SchemaType.DERIVED);
+    }
+
+    public void delete(final SchemaType schemaType, final String schemaName) {
+        schemaService.delete(schemaType, schemaName);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/AbstractTaskCommand.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/AbstractTaskCommand.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/AbstractTaskCommand.java
index 18e877a..bdc4c22 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/AbstractTaskCommand.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/AbstractTaskCommand.java
@@ -18,12 +18,9 @@
  */
 package org.apache.syncope.client.cli.commands.task;
 
-import org.apache.syncope.client.cli.SyncopeServices;
-import org.apache.syncope.common.rest.api.service.TaskService;
-
 public abstract class AbstractTaskCommand {
 
-    protected final TaskService taskService = SyncopeServices.get(TaskService.class);
+    protected final TaskSyncopeOperations taskSyncopeOperations = new TaskSyncopeOperations();
 
     protected final TaskResultManager taskResultManager = new TaskResultManager();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskDelete.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskDelete.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskDelete.java
index 655e112..e0d4753 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskDelete.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskDelete.java
@@ -37,7 +37,7 @@ public class TaskDelete extends AbstractTaskCommand {
         if (input.parameterNumber() >= 1) {
             for (final String parameter : input.getParameters()) {
                 try {
-                    taskService.delete(Long.valueOf(parameter));
+                    taskSyncopeOperations.delete(parameter);
                     taskResultManager.deletedMessage("Task", parameter);
                 } catch (final WebServiceException | SyncopeClientException ex) {
                     if (ex.getMessage().startsWith("NotFound")) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecute.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecute.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecute.java
index 9f53ece..dfefae3 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecute.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecute.java
@@ -37,7 +37,6 @@ public class TaskExecute extends AbstractTaskCommand {
     public void execute() {
         if (input.parameterNumber() == 2) {
             try {
-                final Long taskIdToExecute = Long.valueOf(input.firstParameter());
                 boolean dryRun = true;
                 if ("false".equalsIgnoreCase(input.secondParameter())) {
                     dryRun = false;
@@ -46,7 +45,8 @@ public class TaskExecute extends AbstractTaskCommand {
                 } else {
                     taskResultManager.notBooleanDeletedError("dry run", input.secondParameter());
                 }
-                taskResultManager.printTaskExecTO(Arrays.asList(taskService.execute(taskIdToExecute, dryRun)));
+                taskResultManager.printTaskExecTO(Arrays.asList(
+                        taskSyncopeOperations.execute(input.firstParameter(), dryRun)));
             } catch (final WebServiceException | SyncopeClientException ex) {
                 if (ex.getMessage().startsWith("NotFound")) {
                     taskResultManager.notFoundError("Task", input.firstParameter());

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecutionDelete.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecutionDelete.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecutionDelete.java
index a107716..bb6d694 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecutionDelete.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecutionDelete.java
@@ -37,7 +37,7 @@ public class TaskExecutionDelete extends AbstractTaskCommand {
         if (input.parameterNumber() >= 1) {
             for (final String parameter : input.getParameters()) {
                 try {
-                    taskService.deleteExecution(Long.valueOf(parameter));
+                    taskSyncopeOperations.deleteExecution(parameter);
                     taskResultManager.deletedMessage("Task execution", parameter);
                 } catch (final WebServiceException | SyncopeClientException ex) {
                     if (ex.getMessage().startsWith("NotFound")) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecutionRead.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecutionRead.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecutionRead.java
index d24641d..d83e2ef 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecutionRead.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskExecutionRead.java
@@ -38,7 +38,7 @@ public class TaskExecutionRead extends AbstractTaskCommand {
             for (final String parameter : input.getParameters()) {
                 try {
                     taskResultManager.printTaskExecTO(
-                            Arrays.asList(taskService.readExecution(Long.valueOf(parameter))));
+                            Arrays.asList(taskSyncopeOperations.readExecution(parameter)));
                 } catch (final NumberFormatException ex) {
                     taskResultManager.notBooleanDeletedError("task execution", parameter);
                 } catch (final SyncopeClientException | WebServiceException ex) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskList.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskList.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskList.java
index 203dbcb..b8c08e5 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskList.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskList.java
@@ -42,7 +42,7 @@ public class TaskList extends AbstractTaskCommand {
             try {
                 final TaskType taskType = TaskType.valueOf(input.firstParameter());
                 final LinkedList<AbstractTaskTO> taskTOs = new LinkedList<>();
-                for (final AbstractTaskTO taskTO : taskService.list(taskType, new TaskQuery()).getResult()) {
+                for (final AbstractTaskTO taskTO : taskSyncopeOperations.list(taskType, new TaskQuery()).getResult()) {
                     taskTOs.add(taskTO);
                 }
                 taskResultManager.fromList(taskType, taskTOs);

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskRead.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskRead.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskRead.java
index 2538254..9e93d9e 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskRead.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskRead.java
@@ -39,7 +39,7 @@ public class TaskRead extends AbstractTaskCommand {
             final LinkedList<AbstractTaskTO> taskTOs = new LinkedList<>();
             for (final String parameter : input.getParameters()) {
                 try {
-                    taskTOs.add(taskService.read(Long.valueOf(parameter)));
+                    taskTOs.add(taskSyncopeOperations.read(parameter));
                 } catch (final NumberFormatException ex) {
                     taskResultManager.notBooleanDeletedError("task", parameter);
                 } catch (final SyncopeClientException | WebServiceException ex) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskRunningJobs.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskRunningJobs.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskRunningJobs.java
index fdb886f..d3a7e93 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskRunningJobs.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskRunningJobs.java
@@ -19,13 +19,12 @@
 package org.apache.syncope.client.cli.commands.task;
 
 import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.types.JobStatusType;
 
 public class TaskRunningJobs extends AbstractTaskCommand {
 
     public void list() {
         try {
-            taskResultManager.printTaskExecTO(taskService.listJobs(JobStatusType.RUNNING));
+            taskResultManager.printTaskExecTO(taskSyncopeOperations.listRunningJobs());
         } catch (final SyncopeClientException ex) {
             taskResultManager.generic(ex.getMessage());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskScheduledJobs.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskScheduledJobs.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskScheduledJobs.java
index d95f122..c4798d5 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskScheduledJobs.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskScheduledJobs.java
@@ -19,13 +19,12 @@
 package org.apache.syncope.client.cli.commands.task;
 
 import org.apache.syncope.common.lib.SyncopeClientException;
-import org.apache.syncope.common.lib.types.JobStatusType;
 
 public class TaskScheduledJobs extends AbstractTaskCommand {
 
     public void list() {
         try {
-            taskResultManager.printTaskExecTO(taskService.listJobs(JobStatusType.SCHEDULED));
+            taskResultManager.printTaskExecTO(taskSyncopeOperations.listScheduledJobs());
         } catch (final SyncopeClientException ex) {
             taskResultManager.generic(ex.getMessage());
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskSyncopeOperations.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskSyncopeOperations.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskSyncopeOperations.java
new file mode 100644
index 0000000..6b819e9
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/task/TaskSyncopeOperations.java
@@ -0,0 +1,66 @@
+/*
+ * 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.task;
+
+import java.util.List;
+import org.apache.syncope.client.cli.SyncopeServices;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.syncope.common.lib.types.JobStatusType;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.rest.api.beans.TaskQuery;
+import org.apache.syncope.common.rest.api.service.TaskService;
+
+public class TaskSyncopeOperations {
+
+    private final TaskService taskService = SyncopeServices.get(TaskService.class);
+
+    public List<TaskExecTO> listScheduledJobs() {
+        return taskService.listJobs(JobStatusType.SCHEDULED);
+    }
+
+    public List<TaskExecTO> listRunningJobs() {
+        return taskService.listJobs(JobStatusType.RUNNING);
+    }
+
+    public <T extends AbstractTaskTO> T read(final String taskId) {
+        return taskService.read(Long.valueOf(taskId));
+    }
+
+    public void delete(final String taskId) {
+        taskService.read(Long.valueOf(taskId));
+    }
+
+    public <T extends AbstractTaskTO> PagedResult<T> list(final TaskType type, final TaskQuery query) {
+        return taskService.list(type, query);
+    }
+
+    public TaskExecTO readExecution(final String executionId) {
+        return taskService.readExecution(Long.valueOf(executionId));
+    }
+
+    public void deleteExecution(final String executionId) {
+        taskService.deleteExecution(Long.valueOf(executionId));
+    }
+
+    public TaskExecTO execute(final String executionId, final boolean dryRun) {
+        return taskService.execute(Long.valueOf(executionId), dryRun);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/AbstractUserCommand.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/AbstractUserCommand.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/AbstractUserCommand.java
new file mode 100644
index 0000000..5a28a04
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/AbstractUserCommand.java
@@ -0,0 +1,27 @@
+/*
+ * 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.user;
+
+public abstract class AbstractUserCommand {
+
+    protected final UserSyncopeOperations userSyncopeOperations = new UserSyncopeOperations();
+
+    protected final UserResultManager userResultManager = new UserResultManager();
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserCommand.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserCommand.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserCommand.java
new file mode 100644
index 0000000..35c3941
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserCommand.java
@@ -0,0 +1,144 @@
+/*
+ * 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.user;
+
+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 = "user")
+public class UserCommand extends AbstractCommand {
+
+    private static final String HELP_MESSAGE = "Usage: user [options]\n"
+            + "  Options:\n"
+            + "    --help \n"
+            + "    --list \n"
+            + "    --count \n"
+            + "    --get-user-key\n"
+            + "       Syntax: --get-user-key {USER-ID} {USER-ID} [...]\n"
+            + "    --get-username\n"
+            + "       Syntax: --get-username {USERNAME} {USERNAME} [...]\n"
+            + "    --read \n"
+            + "       Syntax: --read {USER-ID} {USER-ID} [...]\n"
+            + "    --search-by-attribute \n"
+            + "       Syntax: --search-by-attribute {REALM} {ATTR-NAME}={ATTR-VALUE}\n"
+            + "    --search-by-role \n"
+            + "       Syntax: --search-by-role {REALM} {ROLE-ID}\n"
+            + "    --search-by-resource \n"
+            + "       Syntax: --search-by-resource {REALM} {RESOURCE-NAME}\n"
+            + "    --delete \n"
+            + "       Syntax: --delete {USER-ID} {USER-ID} [...]";
+
+    @Override
+    public void execute(final Input input) {
+        if (StringUtils.isBlank(input.getOption())) {
+            input.setOption(UserOptions.HELP.getOptionName());
+        }
+
+        switch (UserOptions.fromName(input.getOption())) {
+            case COUNT:
+                new UserCount(input).count();
+                break;
+            case LIST:
+                new UserList().list();
+                break;
+            case GET_BY_KEY:
+                new UserGetKey(input).get();
+                break;
+            case GET_BY_USERNAME:
+                new UserGetUsername(input).get();
+                break;
+            case READ:
+                new UserRead(input).read();
+                break;
+            case SEARCH_BY_ATTRIBUTE:
+                new UserSearchByAttribute(input).search();
+                break;
+            case SEARCH_BY_ROLE:
+                new UserSearchByRole(input).search();
+                break;
+            case SEARCH_BY_RESOURCE:
+                new UserSearchByResource(input).search();
+                break;
+            case DELETE:
+                new UserDelete(input).delete();
+                break;
+            case HELP:
+                System.out.println(HELP_MESSAGE);
+                break;
+            default:
+                new UserResultManager().defaultError(input.getOption(), HELP_MESSAGE);
+        }
+    }
+
+    @Override
+    public String getHelpMessage() {
+        return HELP_MESSAGE;
+    }
+
+    private enum UserOptions {
+
+        HELP("--help"),
+        COUNT("--count"),
+        LIST("--list"),
+        GET_BY_KEY("--get-user-key"),
+        GET_BY_USERNAME("--get-username"),
+        READ("--read"),
+        SEARCH_BY_ATTRIBUTE("--search-by-attribute"),
+        SEARCH_BY_ROLE("--search-by-role"),
+        SEARCH_BY_RESOURCE("--search-by-resource"),
+        DELETE("--delete");
+
+        private final String optionName;
+
+        UserOptions(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 UserOptions fromName(final String name) {
+            UserOptions optionToReturn = HELP;
+            for (final UserOptions option : UserOptions.values()) {
+                if (option.equalsOptionName(name)) {
+                    optionToReturn = option;
+                }
+            }
+            return optionToReturn;
+        }
+
+        public static List<String> toList() {
+            final List<String> options = new ArrayList<>();
+            for (final UserOptions value : values()) {
+                options.add(value.getOptionName());
+            }
+            return options;
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserCount.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserCount.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserCount.java
new file mode 100644
index 0000000..a9cff9e
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserCount.java
@@ -0,0 +1,43 @@
+/*
+ * 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.user;
+
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.common.lib.SyncopeClientException;
+
+public class UserCount extends AbstractUserCommand {
+
+    private final Input input;
+
+    public UserCount(final Input input) {
+        this.input = input;
+    }
+
+    public void count() {
+        if (input.parameterNumber() == 0) {
+            try {
+                userResultManager.generic("Total users: " + userSyncopeOperations.count());
+            } catch (final SyncopeClientException ex) {
+                userResultManager.generic("Error: " + ex.getMessage());
+            }
+        } else {
+            userResultManager.generic("Error: unnecessary parameters " + input.listParameters());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserDelete.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserDelete.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserDelete.java
new file mode 100644
index 0000000..817db6c
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserDelete.java
@@ -0,0 +1,55 @@
+/*
+ * 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.user;
+
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.common.lib.SyncopeClientException;
+
+public class UserDelete extends AbstractUserCommand {
+
+    private static final String DELETE_HELP_MESSAGE = "user --delete {USER-ID} {USER-ID} [...]";
+
+    private final Input input;
+
+    public UserDelete(final Input input) {
+        this.input = input;
+    }
+
+    public void delete() {
+        if (input.parameterNumber() >= 1) {
+            for (final String parameter : input.getParameters()) {
+                try {
+                    userSyncopeOperations.delete(parameter);
+                    userResultManager.deletedMessage("User", parameter);
+                } catch (final WebServiceException | SyncopeClientException ex) {
+                    if (ex.getMessage().startsWith("NotFound")) {
+                        userResultManager.notFoundError("User", parameter);
+                    } else {
+                        userResultManager.generic(ex.getMessage());
+                    }
+                } catch (final NumberFormatException ex) {
+                    userResultManager.numberFormatException("user", parameter);
+                }
+            }
+        } else {
+            userResultManager.commandOptionError(DELETE_HELP_MESSAGE);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserGetKey.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserGetKey.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserGetKey.java
new file mode 100644
index 0000000..d64a327
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserGetKey.java
@@ -0,0 +1,45 @@
+/*
+ * 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.user;
+
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.common.lib.SyncopeClientException;
+
+public class UserGetKey extends AbstractUserCommand {
+
+    private static final String GET_HELP_MESSAGE = "user --get-user-key {USERNAME}";
+
+    private final Input input;
+
+    public UserGetKey(final Input input) {
+        this.input = input;
+    }
+
+    public void get() {
+        if (input.getParameters().length == 1) {
+            try {
+                userResultManager.generic(userSyncopeOperations.getIdFromUsername(input.firstParameter()));
+            } catch (final SyncopeClientException ex) {
+                userResultManager.generic("Error: " + ex.getMessage());
+            }
+        } else {
+            userResultManager.commandOptionError(GET_HELP_MESSAGE);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserGetUsername.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserGetUsername.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserGetUsername.java
new file mode 100644
index 0000000..a94b1df
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserGetUsername.java
@@ -0,0 +1,45 @@
+/*
+ * 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.user;
+
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.common.lib.SyncopeClientException;
+
+public class UserGetUsername extends AbstractUserCommand {
+
+    private static final String GET_HELP_MESSAGE = "user --get-username {USER-ID}";
+
+    private final Input input;
+
+    public UserGetUsername(final Input input) {
+        this.input = input;
+    }
+
+    public void get() {
+        if (input.getParameters().length == 1) {
+            try {
+                userResultManager.generic(userSyncopeOperations.getUsernameFromId(input.firstParameter()));
+            } catch (final SyncopeClientException ex) {
+                userResultManager.generic("Error: " + ex.getMessage());
+            }
+        } else {
+            userResultManager.commandOptionError(GET_HELP_MESSAGE);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserList.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserList.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserList.java
new file mode 100644
index 0000000..4778cd2
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserList.java
@@ -0,0 +1,48 @@
+/*
+ * 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.user;
+
+import java.util.LinkedList;
+import java.util.Scanner;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.UserTO;
+
+public class UserList extends AbstractUserCommand {
+
+    public void list() {
+        try {
+            final Scanner scanIn = new Scanner(System.in);
+            System.out.println(
+                    "This operation could be print a lot of information "
+                    + "on your screen. Do you want to continue? [yes/no]");
+            final String answer = scanIn.nextLine();
+            if ("yes".equalsIgnoreCase(answer)) {
+                final PagedResult<UserTO> uResult = userSyncopeOperations.list();
+                userResultManager.toView(new LinkedList<>(uResult.getResult()));
+            } else if ("no".equalsIgnoreCase(answer)) {
+                userResultManager.generic("List operation skipped");
+            } else {
+                userResultManager.generic("Invalid parameter, please use [yes/no]");
+            }
+        } catch (final SyncopeClientException ex) {
+            userResultManager.generic(ex.getMessage());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserRead.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserRead.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserRead.java
new file mode 100644
index 0000000..ae94409
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserRead.java
@@ -0,0 +1,60 @@
+/*
+ * 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.user;
+
+import java.util.LinkedList;
+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.UserTO;
+
+public class UserRead extends AbstractUserCommand {
+
+    private static final String READ_HELP_MESSAGE = "user --read {USER-ID} {USER-ID} [...]";
+
+    private final Input input;
+
+    public UserRead(final Input input) {
+        this.input = input;
+    }
+
+    public void read() {
+        if (input.getParameters().length >= 1) {
+            final LinkedList<UserTO> userTOs = new LinkedList<>();
+            for (final String parameter : input.getParameters()) {
+                try {
+                    userTOs.add(userSyncopeOperations.read(parameter));
+                } catch (final SyncopeClientException | WebServiceException ex) {
+                    if (ex.getMessage().startsWith("NotFound")) {
+                        userResultManager.notFoundError("Logger", parameter);
+                    } else {
+                        userResultManager.generic("Error: " + ex.getMessage());
+                    }
+                    break;
+                } catch (final NumberFormatException ex) {
+                    userResultManager.numberFormatException("user", parameter);
+                }
+            }
+            userResultManager.toView(userTOs);
+        } else {
+            userResultManager.commandOptionError(READ_HELP_MESSAGE);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserResultManager.java
new file mode 100644
index 0000000..2ea0578
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserResultManager.java
@@ -0,0 +1,110 @@
+/*
+ * 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.user;
+
+import java.util.List;
+import java.util.Set;
+import org.apache.syncope.client.cli.commands.CommonsResultManager;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.PropagationStatus;
+import org.apache.syncope.common.lib.to.RelationshipTO;
+import org.apache.syncope.common.lib.to.UserTO;
+
+public class UserResultManager extends CommonsResultManager {
+
+    public void toView(final List<UserTO> userTOs) {
+        for (final UserTO userTO : userTOs) {
+            printUser(userTO);
+        }
+        System.out.println("");
+    }
+
+    private void printUser(final UserTO userTO) {
+        System.out.println(" > USER ID: " + userTO.getKey());
+        System.out.println("    username: " + userTO.getUsername());
+        System.out.println("    realm: " + userTO.getRealm());
+        System.out.println("    status: " + userTO.getStatus());
+        System.out.println("    RESOURCES: ");
+        printResource(userTO.getResources());
+        System.out.println("    ROLES: ");
+        printRole(userTO.getRoles());
+        System.out.println("    creation date: " + userTO.getCreationDate());
+        System.out.println("    change password date: " + userTO.getChangePwdDate());
+        System.out.println("    PLAIN ATTRIBUTES: ");
+        printAttributes(userTO.getPlainAttrs());
+        System.out.println("    DERIVED ATTRIBUTES: ");
+        printAttributes(userTO.getDerAttrs());
+        System.out.println("    VIRTUAL ATTRIBUTES: ");
+        printAttributes(userTO.getVirAttrs());
+        System.out.println("    creator: " + userTO.getCreator());
+        System.out.println("    last modifier: " + userTO.getLastModifier());
+        System.out.println("    token: " + userTO.getToken());
+        System.out.println("    token expiration time: " + userTO.getTokenExpireTime());
+        System.out.println("    last change: " + userTO.getLastChangeDate());
+        System.out.println("    last login: " + userTO.getLastLoginDate());
+        System.out.println("    failed logins: " + userTO.getFailedLogins());
+        System.out.println("PROPAGATIONS:");
+        printPropagationStatus(userTO.getPropagationStatusTOs());
+        System.out.println("RELATIONSHIPS:");
+        printRelationships(userTO.getRelationships());
+        System.out.println("    security question id: " + userTO.getSecurityQuestion());
+        System.out.println("    security question answer id: " + userTO.getSecurityAnswer());
+        System.out.println("");
+    }
+
+    private void printResource(final Set<String> resources) {
+        for (final String resource : resources) {
+            System.out.println("       - " + resource);
+        }
+    }
+
+    private void printRole(final List<Long> roles) {
+        for (final Long role : roles) {
+            System.out.println("       - " + role);
+        }
+    }
+
+    private void printAttributes(final Set<AttrTO> derAttrTOs) {
+        for (final AttrTO attrTO : derAttrTOs) {
+            final StringBuilder attributeSentence = new StringBuilder();
+            attributeSentence.append("       ")
+                    .append(attrTO.getSchema())
+                    .append(": ")
+                    .append(attrTO.getValues());
+            if (attrTO.isReadonly()) {
+                attributeSentence.append(" - is readonly.");
+            }
+            System.out.println(attributeSentence);
+        }
+    }
+
+    private void printPropagationStatus(final List<PropagationStatus> propagationStatuses) {
+        for (final PropagationStatus propagationStatus : propagationStatuses) {
+            System.out.println("       status: " + propagationStatus.getStatus());
+            System.out.println("       resource: " + propagationStatus.getResource());
+            System.out.println("       failure reason: " + propagationStatus.getFailureReason());
+        }
+    }
+
+    private void printRelationships(final List<RelationshipTO> relationshipTOs) {
+        for (final RelationshipTO relationshipTO : relationshipTOs) {
+            System.out.println("       type: " + relationshipTO.getType());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByAttribute.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByAttribute.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByAttribute.java
new file mode 100644
index 0000000..18ac77e
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByAttribute.java
@@ -0,0 +1,69 @@
+/*
+ * 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.user;
+
+import java.util.List;
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.client.cli.commands.realm.RealmSyncopeOperations;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.UserTO;
+
+public class UserSearchByAttribute extends AbstractUserCommand {
+
+    private static final String SEARCH_HELP_MESSAGE = "user --search-by-attribute {REALM} {ATTR-NAME}={ATTR-VALUE}";
+
+    private final Input input;
+
+    public UserSearchByAttribute(final Input input) {
+        this.input = input;
+    }
+
+    public void search() {
+        if (input.parameterNumber() >= 2) {
+            final String realm = input.firstParameter();
+            final Input.PairParameter pairParameter = input.toPairParameter(input.secondParameter());
+            final RealmSyncopeOperations realmSyncopeOperations = new RealmSyncopeOperations();
+            try {
+                List<UserTO> userTOs;
+                if (!realmSyncopeOperations.exists(realm)) {
+                    userResultManager.generic("Operation performed on root realm because " + realm + "does not exists");
+                }
+                userTOs = userSyncopeOperations.searchByAttribute(
+                        realm, pairParameter.getKey(), pairParameter.getValue());
+                if (userTOs == null || userTOs.isEmpty()) {
+                    userResultManager.generic("No users found with attribute "
+                            + pairParameter.getKey() + " and value " + pairParameter.getValue());
+                } else {
+                    userResultManager.toView(userTOs);
+                }
+            } catch (final WebServiceException | SyncopeClientException ex) {
+                if (ex.getMessage().startsWith("NotFound")) {
+                    userResultManager.notFoundError("User with " + pairParameter.getKey(), pairParameter.getValue());
+                } else {
+                    userResultManager.generic(ex.getMessage(), SEARCH_HELP_MESSAGE);
+                }
+            } catch (final IllegalArgumentException ex) {
+                userResultManager.generic(ex.getMessage(), SEARCH_HELP_MESSAGE);
+            }
+            userResultManager.commandOptionError(SEARCH_HELP_MESSAGE);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByResource.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByResource.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByResource.java
new file mode 100644
index 0000000..6a22150
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByResource.java
@@ -0,0 +1,68 @@
+/*
+ * 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.user;
+
+import java.util.List;
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.client.cli.commands.realm.RealmSyncopeOperations;
+import org.apache.syncope.client.cli.commands.resource.ResourceSyncopeOperations;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.UserTO;
+
+public class UserSearchByResource extends AbstractUserCommand {
+
+    private static final String SEARCH_HELP_MESSAGE = "user --search {REALM} {RESOURCE-NAME}";
+
+    private final Input input;
+
+    public UserSearchByResource(final Input input) {
+        this.input = input;
+    }
+
+    public void search() {
+        if (input.parameterNumber() == 2) {
+            final String realm = input.firstParameter();
+            final String resource = input.secondParameter();
+            final RealmSyncopeOperations realmSyncopeOperations = new RealmSyncopeOperations();
+            final ResourceSyncopeOperations resourceSyncopeOperations = new ResourceSyncopeOperations();
+            try {
+                List<UserTO> userTOs = null;
+                if (!realmSyncopeOperations.exists(realm)) {
+                    userResultManager.generic("Operation performed on root realm because " + realm + "does not exists");
+                }
+                if (!resourceSyncopeOperations.exists(resource)) {
+                    userResultManager.notFoundError("Resource", resource);
+                } else {
+                    userTOs = userSyncopeOperations.searchByResource(realm, resource);
+                }
+                if (userTOs == null || userTOs.isEmpty()) {
+                    userResultManager.generic("No users has " + resource + " assigned");
+                } else {
+                    userResultManager.toView(userTOs);
+                }
+            } catch (final WebServiceException | SyncopeClientException ex) {
+                userResultManager.generic(ex.getMessage(), SEARCH_HELP_MESSAGE);
+            }
+        } else {
+            userResultManager.commandOptionError(SEARCH_HELP_MESSAGE);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByRole.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByRole.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByRole.java
new file mode 100644
index 0000000..789bacb
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSearchByRole.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.user;
+
+import java.util.List;
+import javax.xml.ws.WebServiceException;
+import org.apache.syncope.client.cli.Input;
+import org.apache.syncope.client.cli.commands.realm.RealmSyncopeOperations;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.UserTO;
+
+public class UserSearchByRole extends AbstractUserCommand {
+
+    private static final String SEARCH_HELP_MESSAGE = "user --search {REALM} {ROLE-ID}";
+
+    private final Input input;
+
+    public UserSearchByRole(final Input input) {
+        this.input = input;
+    }
+
+    public void search() {
+        if (input.parameterNumber() == 2) {
+            final String realm = input.firstParameter();
+            final String role = input.secondParameter();
+            final RealmSyncopeOperations realmSyncopeOperations = new RealmSyncopeOperations();
+            try {
+                List<UserTO> userTOs;
+                if (!realmSyncopeOperations.exists(realm)) {
+                    userResultManager.generic("Operation performed on root realm because " + realm + "does not exists");
+                }
+                userTOs = userSyncopeOperations.searchByRole(realm, input.secondParameter());
+                if (userTOs == null || userTOs.isEmpty()) {
+                    userResultManager.generic("No users has " + role + " assigned");
+                } else {
+                    userResultManager.toView(userTOs);
+                }
+            } catch (final WebServiceException | SyncopeClientException ex) {
+                userResultManager.generic(ex.getMessage(), SEARCH_HELP_MESSAGE);
+            }
+        } else {
+            userResultManager.commandOptionError(SEARCH_HELP_MESSAGE);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/47b9f64b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSyncopeOperations.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSyncopeOperations.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSyncopeOperations.java
new file mode 100644
index 0000000..0496d97
--- /dev/null
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/user/UserSyncopeOperations.java
@@ -0,0 +1,78 @@
+/*
+ * 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.user;
+
+import java.util.List;
+import org.apache.syncope.client.cli.SyncopeServices;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.common.lib.to.PagedResult;
+import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.beans.AnyListQuery;
+import org.apache.syncope.common.rest.api.service.UserService;
+
+public class UserSyncopeOperations {
+
+    private final UserService userService = SyncopeServices.get(UserService.class);
+
+    public List<UserTO> searchByRole(final String realm, final String role) {
+        return userService.search(
+                SyncopeClient.getAnySearchQueryBuilder().realm(realm).
+                fiql(SyncopeClient.getUserSearchConditionBuilder().inRoles(Long.valueOf(role))
+                        .query()).build()).getResult();
+    }
+
+    public List<UserTO> searchByResource(final String realm, final String resource) {
+        return userService.search(
+                SyncopeClient.getAnySearchQueryBuilder().realm(realm).
+                fiql(SyncopeClient.getUserSearchConditionBuilder().hasResources(resource)
+                        .query()).build()).getResult();
+    }
+
+    public List<UserTO> searchByAttribute(final String realm, final String attributeName, final String attributeValue) {
+        return userService.search(
+                SyncopeClient.getAnySearchQueryBuilder().realm(realm).
+                fiql(SyncopeClient.getUserSearchConditionBuilder().is(attributeName).equalTo(attributeValue)
+                        .query()).build()).getResult();
+    }
+
+    public PagedResult<UserTO> list() {
+        return userService.list(new AnyListQuery());
+    }
+
+    public UserTO read(final String userId) {
+        return userService.read(Long.valueOf(userId));
+    }
+
+    public void delete(final String userId) {
+        userService.delete(Long.valueOf(userId));
+    }
+
+    public int count() {
+        return list().getResult().size();
+    }
+
+    public String getUsernameFromId(final String userId) {
+        return userService.getUsername(Long.valueOf(userId)).getHeaderString(RESTHeaders.USERNAME);
+    }
+
+    public String getIdFromUsername(final String username) {
+        return userService.getUserKey(username).getHeaderString(RESTHeaders.USER_KEY);
+    }
+}