You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by sk...@apache.org on 2018/03/05 16:03:31 UTC

syncope git commit: [SYNCOPE-1225] Now providing search engine for Schemas

Repository: syncope
Updated Branches:
  refs/heads/2_0_X 6401942e3 -> a42311f58


[SYNCOPE-1225] Now providing search engine for Schemas


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

Branch: refs/heads/2_0_X
Commit: a42311f589b7987efc93d431c58667381259948c
Parents: 6401942
Author: skylark17 <ma...@tirasa.net>
Authored: Mon Mar 5 17:02:45 2018 +0100
Committer: skylark17 <ma...@tirasa.net>
Committed: Mon Mar 5 17:02:45 2018 +0100

----------------------------------------------------------------------
 .../client/console/panels/SchemaTypePanel.java  |  39 +++++--
 .../panels/SchemaTypePanelWithSearch.java       | 105 +++++++++++++++++++
 .../client/console/panels/SchemasPanel.java     |   2 +-
 .../client/console/rest/SchemaRestClient.java   |  21 +++-
 .../panels/SchemaTypePanelWithSearch.html       |  33 ++++++
 .../common/rest/api/beans/SchemaQuery.java      |  17 +++
 .../common/rest/api/service/SchemaService.java  |   3 +-
 .../apache/syncope/core/logic/SchemaLogic.java  |  26 ++++-
 .../core/persistence/api/dao/SchemaDAO.java     |   4 +-
 .../persistence/jpa/dao/JPADerSchemaDAO.java    |   9 ++
 .../persistence/jpa/dao/JPAPlainSchemaDAO.java  |   9 ++
 .../persistence/jpa/dao/JPAVirSchemaDAO.java    |   9 ++
 .../persistence/jpa/inner/DerSchemaTest.java    |   6 ++
 .../persistence/jpa/inner/PlainSchemaTest.java  |   6 ++
 .../persistence/jpa/inner/VirSchemaTest.java    |   6 ++
 .../rest/cxf/service/SchemaServiceImpl.java     |   2 +-
 .../fit/console/AbstractTypesITCase.java        |  14 +--
 .../syncope/fit/console/SchemasITCase.java      |  84 +++++++--------
 .../syncope/fit/core/DerSchemaITCase.java       |  10 ++
 .../syncope/fit/core/PlainSchemaITCase.java     |  10 ++
 .../syncope/fit/core/VirSchemaITCase.java       |  10 ++
 21 files changed, 360 insertions(+), 65 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
index 30c5050..ded6973 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanel.java
@@ -51,6 +51,7 @@ import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.event.IEvent;
 import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
@@ -80,6 +81,8 @@ public class SchemaTypePanel extends TypesDirectoryPanel<SchemaTO, SchemaProvide
 
     private final SchemaType schemaType;
 
+    private String keyword;
+
     public SchemaTypePanel(final String id, final SchemaType schemaType, final PageReference pageRef) {
         super(id, pageRef);
         this.restClient = new SchemaRestClient();
@@ -250,8 +253,10 @@ public class SchemaTypePanel extends TypesDirectoryPanel<SchemaTO, SchemaProvide
 
         @Override
         public Iterator<SchemaTO> iterator(final long first, final long count) {
-            final List<SchemaTO> list = restClient.getSchemas(this.schemaType);
-            Collections.sort(list, comparator);
+            List<SchemaTO> schemaList = StringUtils.isBlank(keyword)
+                    ? restClient.getSchemas(this.schemaType)
+                    : restClient.getSchemas(this.schemaType, keyword, new String[0]);
+            Collections.sort(schemaList, comparator);
 
             if (SchemaType.PLAIN == this.schemaType) {
                 final List<String> configurations = new ArrayList<>();
@@ -265,22 +270,26 @@ public class SchemaTypePanel extends TypesDirectoryPanel<SchemaTO, SchemaProvide
                 }, configurations);
 
                 final List<SchemaTO> res = new ArrayList<>();
-                for (SchemaTO item : list) {
+                for (SchemaTO item : schemaList) {
                     if (!configurations.contains(item.getKey())) {
                         res.add(item);
                     }
                 }
                 return res.subList((int) first, (int) first + (int) count).iterator();
             } else {
-                return list.subList((int) first, (int) first + (int) count).iterator();
+                return schemaList.subList((int) first, (int) first + (int) count).iterator();
             }
         }
 
         @Override
         public long size() {
-            int size = restClient.getSchemas(this.schemaType).size();
-            return SchemaType.PLAIN == this.schemaType
-                    ? size - confRestClient.list().size()
+            int size = StringUtils.isBlank(keyword)
+                    ? restClient.getSchemas(this.schemaType).size()
+                    : restClient.getSchemas(this.schemaType, keyword, new String[0]).size();
+            return size > confRestClient.list().size()
+                    ? (SchemaType.PLAIN == this.schemaType
+                            ? size - confRestClient.list().size()
+                            : size)
                     : size;
         }
 
@@ -289,4 +298,20 @@ public class SchemaTypePanel extends TypesDirectoryPanel<SchemaTO, SchemaProvide
             return new CompoundPropertyModel<>(object);
         }
     }
+
+    @Override
+    public void onEvent(IEvent<?> event) {
+        if (event.getPayload() instanceof SchemaTypePanelWithSearch.SchemaSearchEvent) {
+            SchemaTypePanelWithSearch.SchemaSearchEvent payload =
+                    SchemaTypePanelWithSearch.SchemaSearchEvent.class.cast(event.getPayload());
+            final AjaxRequestTarget target = payload.getTarget();
+            keyword = payload.getKeyword();
+
+            updateResultTable(target);
+            ((BasePage) pageRef.getPage()).getNotificationPanel().refresh(target);
+        } else {
+            super.onEvent(event);
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanelWithSearch.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanelWithSearch.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanelWithSearch.java
new file mode 100644
index 0000000..c822630
--- /dev/null
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemaTypePanelWithSearch.java
@@ -0,0 +1,105 @@
+/*
+ * 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.console.panels;
+
+import java.io.Serializable;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.client.console.wicket.markup.html.form.AjaxTextFieldPanel;
+import org.apache.syncope.common.lib.types.SchemaType;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
+import org.apache.wicket.event.Broadcast;
+import org.apache.wicket.markup.html.WebMarkupContainer;
+import org.apache.wicket.markup.html.form.Form;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.Model;
+
+public class SchemaTypePanelWithSearch extends Panel {
+
+    private static final long serialVersionUID = 433565065115855671L;
+
+    private final SchemaTypePanel schemaTypePanel;
+
+    public SchemaTypePanelWithSearch(final String id,
+            final SchemaType schemaType,
+            final PageReference pageReference) {
+        super(id);
+
+        schemaTypePanel = new SchemaTypePanel(id, schemaType, pageReference);
+
+        addSearchBox();
+        add(schemaTypePanel);
+    }
+
+    private void addSearchBox() {
+        final Model<String> queryFilter = new Model<>(StringUtils.EMPTY);
+
+        final WebMarkupContainer searchBoxContainer = new WebMarkupContainer("searchBox");
+        final Form<?> form = new Form<>("form");
+        final AjaxTextFieldPanel filter = new AjaxTextFieldPanel(
+                "filter",
+                "filter",
+                queryFilter,
+                false);
+        filter.hideLabel().setOutputMarkupId(true);
+        form.add(filter);
+
+        form.add(new AjaxSubmitLink("search") {
+
+            private static final long serialVersionUID = -1765773642975892072L;
+
+            @Override
+            protected void onAfterSubmit(final AjaxRequestTarget target, final Form<?> form) {
+                super.onAfterSubmit(target, form);
+
+                send(SchemaTypePanelWithSearch.this,
+                        Broadcast.DEPTH,
+                        new SchemaSearchEvent(target, queryFilter.getObject()));
+            }
+        });
+        searchBoxContainer.add(form);
+
+        add(searchBoxContainer);
+    }
+
+    public static class SchemaSearchEvent implements Serializable {
+
+        private static final long serialVersionUID = -282052400565266028L;
+
+        private final AjaxRequestTarget target;
+
+        private final String keyword;
+
+        public SchemaSearchEvent(final AjaxRequestTarget target, final String keyword) {
+            this.target = target;
+            this.keyword = keyword;
+        }
+
+        public AjaxRequestTarget getTarget() {
+            return target;
+        }
+
+        public String getKeyword() {
+            return keyword;
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemasPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemasPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemasPanel.java
index 78fb28c..7ad295b 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemasPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/SchemasPanel.java
@@ -55,7 +55,7 @@ public class SchemasPanel extends Panel {
 
                 @Override
                 public Panel getPanel(final String panelId) {
-                    return new SchemaTypePanel(panelId, schemaType, pageReference);
+                    return new SchemaTypePanelWithSearch(panelId, schemaType, pageReference);
                 }
             });
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/client/console/src/main/java/org/apache/syncope/client/console/rest/SchemaRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/SchemaRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/SchemaRestClient.java
index b902715..ea119df 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/SchemaRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/SchemaRestClient.java
@@ -82,19 +82,36 @@ public class SchemaRestClient extends BaseRestClient {
     }
 
     public <T extends SchemaTO> List<T> getSchemas(final SchemaType schemaType, final String... kind) {
+        return doGetSchemas(schemaType, null, kind);
+    }
+
+    public <T extends SchemaTO> List<T> getSchemas(
+            final SchemaType schemaType, final String keyword, final String... kind) {
+        return doGetSchemas(schemaType, keyword, kind);
+    }
+
+    private <T extends SchemaTO> List<T> doGetSchemas(
+            final SchemaType schemaType, final String keyword, final String... kind) {
         List<T> schemas = new ArrayList<>();
 
         try {
+            SchemaQuery.Builder schemaQuery =
+                    new SchemaQuery.Builder().type(schemaType);
+            if (keyword != null) {
+                schemaQuery.keyword(keyword);
+            }
+
             if (kind == null || kind.length == 0) {
                 schemas.addAll(getService(SchemaService.class).
-                        <T>list(new SchemaQuery.Builder().type(schemaType).build()));
+                        <T>list(schemaQuery.build()));
             } else {
                 schemas.addAll(getService(SchemaService.class).
-                        <T>list(new SchemaQuery.Builder().type(schemaType).anyTypeClasses(kind).build()));
+                        <T>list(schemaQuery.anyTypeClasses(kind).build()));
             }
         } catch (SyncopeClientException e) {
             LOG.error("While getting all {} schemas for {}", schemaType, kind, e);
         }
+
         return schemas;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/client/console/src/main/resources/org/apache/syncope/client/console/panels/SchemaTypePanelWithSearch.html
----------------------------------------------------------------------
diff --git a/client/console/src/main/resources/org/apache/syncope/client/console/panels/SchemaTypePanelWithSearch.html b/client/console/src/main/resources/org/apache/syncope/client/console/panels/SchemaTypePanelWithSearch.html
new file mode 100644
index 0000000..6caa8b6
--- /dev/null
+++ b/client/console/src/main/resources/org/apache/syncope/client/console/panels/SchemaTypePanelWithSearch.html
@@ -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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:panel>
+    <div wicket:id="searchBox">
+      <form wicket:id="form">
+        <div class="form-group input-group">
+          <span wicket:id="filter">[FILTER]</span>
+          <span class="input-group-addon">
+            <a href="#" wicket:id="search"><i class="glyphicon glyphicon-search"></i></a>
+          </span>
+        </div>
+      </form>
+    </div>
+    <div wicket:id="content"></div>
+  </wicket:panel>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SchemaQuery.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SchemaQuery.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SchemaQuery.java
index 811b664..a35b85c 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SchemaQuery.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/SchemaQuery.java
@@ -61,6 +61,12 @@ public class SchemaQuery extends AbstractBaseBean {
             return anyTypeClasses(Arrays.asList(anyTypeClasses));
         }
 
+        public Builder keyword(final String keyword) {
+            instance.setKeyword(keyword);
+
+            return this;
+        }
+
         public SchemaQuery build() {
             if (instance.type == null) {
                 throw new IllegalArgumentException("type is required");
@@ -73,6 +79,8 @@ public class SchemaQuery extends AbstractBaseBean {
 
     private List<String> anyTypeClasses;
 
+    private String keyword;
+
     public SchemaType getType() {
         return type;
     }
@@ -92,4 +100,13 @@ public class SchemaQuery extends AbstractBaseBean {
         this.anyTypeClasses = anyTypeClasses;
     }
 
+    public String getKeyword() {
+        return keyword;
+    }
+
+    @QueryParam("keyword")
+    public void setKeyword(final String keyword) {
+        this.keyword = keyword;
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SchemaService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SchemaService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SchemaService.java
index f0cd4a6..e19cce7 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SchemaService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SchemaService.java
@@ -56,7 +56,8 @@ public interface SchemaService extends JAXRSService {
      *
      * @param <T> actual SchemaTO
      * @param query query conditions
-     * @return list of schemas with matching type, for the given anyTypeClass if provided
+     * @return list of schemas with matching type, for the given anyTypeClass if provided,
+     * with names containing keyword if provided
      */
     @GET
     @Path("{type}")

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/core/logic/src/main/java/org/apache/syncope/core/logic/SchemaLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/SchemaLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/SchemaLogic.java
index b06c918..4f16de9 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/SchemaLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/SchemaLogic.java
@@ -148,7 +148,21 @@ public class SchemaLogic extends AbstractTransactionalLogic<SchemaTO> {
     @SuppressWarnings("unchecked")
     public <T extends SchemaTO> List<T> list(
             final SchemaType schemaType, final List<String> anyTypeClasses) {
+        return doSearch(schemaType, anyTypeClasses, null);
+    }
+
+    @PreAuthorize("isAuthenticated()")
+    @SuppressWarnings("unchecked")
+    public <T extends SchemaTO> List<T> search(
+            final SchemaType schemaType, final List<String> anyTypeClasses, final String keyword) {
+        return doSearch(schemaType, anyTypeClasses,
+                keyword != null
+                        ? StringUtils.replaceChars(keyword, "*", "%")
+                        : null);
+    }
 
+    private <T extends SchemaTO> List<T> doSearch(
+            final SchemaType schemaType, final List<String> anyTypeClasses, final String keyword) {
         List<AnyTypeClass> classes = new ArrayList<>(anyTypeClasses == null ? 0 : anyTypeClasses.size());
         if (anyTypeClasses != null) {
             anyTypeClasses.remove(AnyTypeKind.USER.name());
@@ -167,7 +181,9 @@ public class SchemaLogic extends AbstractTransactionalLogic<SchemaTO> {
         switch (schemaType) {
             case VIRTUAL:
                 result = CollectionUtils.collect(
-                        classes.isEmpty() ? virSchemaDAO.findAll() : virSchemaDAO.findByAnyTypeClasses(classes),
+                        classes.isEmpty()
+                        ? (keyword == null ? virSchemaDAO.findAll() : virSchemaDAO.search(keyword))
+                        : virSchemaDAO.findByAnyTypeClasses(classes),
                         new Transformer<VirSchema, T>() {
 
                     @Override
@@ -179,7 +195,9 @@ public class SchemaLogic extends AbstractTransactionalLogic<SchemaTO> {
 
             case DERIVED:
                 result = CollectionUtils.collect(
-                        classes.isEmpty() ? derSchemaDAO.findAll() : derSchemaDAO.findByAnyTypeClasses(classes),
+                        classes.isEmpty()
+                        ? (keyword == null ? derSchemaDAO.findAll() : derSchemaDAO.search(keyword))
+                        : derSchemaDAO.findByAnyTypeClasses(classes),
                         new Transformer<DerSchema, T>() {
 
                     @Override
@@ -192,7 +210,9 @@ public class SchemaLogic extends AbstractTransactionalLogic<SchemaTO> {
             case PLAIN:
             default:
                 result = CollectionUtils.collect(
-                        classes.isEmpty() ? plainSchemaDAO.findAll() : plainSchemaDAO.findByAnyTypeClasses(classes),
+                        classes.isEmpty()
+                        ? (keyword == null ? plainSchemaDAO.findAll() : plainSchemaDAO.search(keyword))
+                        : plainSchemaDAO.findByAnyTypeClasses(classes),
                         new Transformer<PlainSchema, T>() {
 
                     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SchemaDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SchemaDAO.java
index 76ce8ed..de2df90 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SchemaDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/SchemaDAO.java
@@ -30,7 +30,9 @@ public interface SchemaDAO<S extends Schema> extends DAO<S> {
     List<S> findByAnyTypeClasses(Collection<AnyTypeClass> anyTypeClasses);
 
     List<S> findAll();
-
+    
+    List<S> search(String keyword);
+    
     S save(S derSchema);
 
     void delete(String key);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
index 3894adb..98e1bea 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
@@ -63,6 +63,15 @@ public class JPADerSchemaDAO extends AbstractDAO<DerSchema> implements DerSchema
     }
 
     @Override
+    public List<DerSchema> search(final String keyword) {
+        TypedQuery<DerSchema> query = entityManager().createQuery(
+                "SELECT e FROM " + JPADerSchema.class.getSimpleName() + " e"
+                + " WHERE e.id LIKE :keyword", DerSchema.class);
+        query.setParameter("keyword", keyword);
+        return query.getResultList();
+    }
+
+    @Override
     public DerSchema save(final DerSchema derSchema) {
         return entityManager().merge(derSchema);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
index dfc3840..b9b333c 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
@@ -81,6 +81,15 @@ public class JPAPlainSchemaDAO extends AbstractDAO<PlainSchema> implements Plain
     }
 
     @Override
+    public List<PlainSchema> search(final String keyword) {
+        TypedQuery<PlainSchema> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAPlainSchema.class.getSimpleName() + " e"
+                + " WHERE e.id LIKE :keyword", PlainSchema.class);
+        query.setParameter("keyword", keyword);
+        return query.getResultList();
+    }
+
+    @Override
     public <T extends PlainAttr<?>> List<T> findAttrs(final PlainSchema schema, final Class<T> reference) {
         TypedQuery<T> query = entityManager().createQuery(
                 "SELECT e FROM " + ((JPAPlainAttrDAO) plainAttrDAO).getEntityReference(reference).getSimpleName()

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
index 4dfc8db..b42b40a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
@@ -115,6 +115,15 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema> implements VirSchema
     }
 
     @Override
+    public List<VirSchema> search(final String keyword) {
+        TypedQuery<VirSchema> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAVirSchema.class.getSimpleName() + " e"
+                + " WHERE e.id LIKE :keyword", VirSchema.class);
+        query.setParameter("keyword", keyword);
+        return query.getResultList();
+    }
+
+    @Override
     public VirSchema save(final VirSchema virSchema) {
         return entityManager().merge(virSchema);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DerSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DerSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DerSchemaTest.java
index 97764b8..f1a4fcd 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DerSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/DerSchemaTest.java
@@ -47,6 +47,12 @@ public class DerSchemaTest extends AbstractTest {
     }
 
     @Test
+    public void search() {
+        List<DerSchema> schemas = derSchemaDAO.search("mderivedd*");
+        assertEquals(1, schemas.size());
+    }
+
+    @Test
     public void findByName() {
         DerSchema attributeSchema = derSchemaDAO.find("cn");
         assertNotNull("did not find expected derived attribute schema", attributeSchema);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
index ffe1edc..416998a 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PlainSchemaTest.java
@@ -51,6 +51,12 @@ public class PlainSchemaTest extends AbstractTest {
     }
 
     @Test
+    public void search() {
+        List<PlainSchema> schemas = plainSchemaDAO.search("fullna*");
+        assertEquals(1, schemas.size());
+    }
+
+    @Test
     public void findByName() {
         PlainSchema schema = plainSchemaDAO.find("fullname");
         assertNotNull("did not find expected attribute schema", schema);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
index 192ef0f..83693e4 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/VirSchemaTest.java
@@ -54,6 +54,12 @@ public class VirSchemaTest extends AbstractTest {
     }
 
     @Test
+    public void search() {
+        List<VirSchema> schemas = virSchemaDAO.search("rvirtuald*");
+        assertEquals(1, schemas.size());
+    }
+
+    @Test
     public void findByName() {
         VirSchema attributeSchema = virSchemaDAO.find("virtualdata");
         assertNotNull("did not find expected virtual attribute schema", attributeSchema);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SchemaServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SchemaServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SchemaServiceImpl.java
index 5c74e41..10db5b5 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SchemaServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SchemaServiceImpl.java
@@ -53,7 +53,7 @@ public class SchemaServiceImpl extends AbstractServiceImpl implements SchemaServ
 
     @Override
     public <T extends SchemaTO> List<T> list(final SchemaQuery query) {
-        return logic.list(query.getType(), query.getAnyTypeClasses());
+        return logic.search(query.getType(), query.getAnyTypeClasses(), query.getKeyword());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractTypesITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractTypesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractTypesITCase.java
index 6a395ad..4c9362e 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractTypesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/AbstractTypesITCase.java
@@ -27,10 +27,10 @@ import org.junit.Before;
 public abstract class AbstractTypesITCase extends AbstractConsoleITCase {
 
     protected static final String PLAIN_DATATABLE_PATH = "body:content:tabbedPanel:panel:"
-            + "accordionPanel:tabs:0:body:content:container:content:searchContainer:resultTable";
+            + "accordionPanel:tabs:0:body:content:content:container:content:searchContainer:resultTable";
 
     protected static final String VIRTUAL_DATATABLE_PATH = "body:content:tabbedPanel:panel:"
-            + "accordionPanel:tabs:2:body:content:container:content:searchContainer:resultTable";
+            + "accordionPanel:tabs:2:body:content:content:container:content:searchContainer:resultTable";
 
     protected static final String DATATABLE_PATH =
             "body:content:tabbedPanel:panel:container:content:searchContainer:resultTable";
@@ -88,19 +88,19 @@ public abstract class AbstractTypesITCase extends AbstractConsoleITCase {
     protected void createPlainSchema(final String key) {
         browsingToPlainSchemas();
         TESTER.clickLink(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:container:content:add");
+                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:content:container:content:add");
 
         TESTER.assertComponent(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer",
+                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:content:outerObjectsRepeater:0:outer",
                 Modal.class);
 
         final FormTester formTester = TESTER.newFormTester("body:content:tabbedPanel:panel:"
-                + "accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer:form");
+                + "accordionPanel:tabs:0:body:content:content:outerObjectsRepeater:0:outer:form");
         formTester.setValue("content:details:form:key:textField", key);
         formTester.setValue("content:details:form:type:dropDownChoiceField", "3");
 
-        TESTER.clickLink("body:content:tabbedPanel:panel:"
-                + "accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
+        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
 
         TESTER.assertInfoMessages("Operation executed successfully");
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/fit/core-reference/src/test/java/org/apache/syncope/fit/console/SchemasITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/SchemasITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/SchemasITCase.java
index 45303fb..74c9c26 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/console/SchemasITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/console/SchemasITCase.java
@@ -45,32 +45,32 @@ public class SchemasITCase extends AbstractTypesITCase {
                 Constants.ON_CLICK);
 
         TESTER.clickLink(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:1:outer:"
+                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:content:outerObjectsRepeater:1:outer:"
                 + "container:content:togglePanelContainer:container:actions:actions:actionRepeater:0:action:action");
 
         TESTER.assertComponent(
                 "body:content:tabbedPanel:"
-                + "panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer:"
+                + "panel:accordionPanel:tabs:0:body:content:content:outerObjectsRepeater:0:outer:"
                 + "form:content:kindForm:kind:dropDownChoiceField", DropDownChoice.class);
     }
 
     @Test
     public void createPlainSchema() {
         browsingToPlainSchemas();
-        TESTER.clickLink(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:container:content:add");
+        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:container:content:add");
 
-        TESTER.assertComponent(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer",
+        TESTER.assertComponent("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:0:outer",
                 Modal.class);
 
         final FormTester formTester = TESTER.newFormTester("body:content:tabbedPanel:panel:"
-                + "accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer:form");
+                + "accordionPanel:tabs:0:body:content:content:outerObjectsRepeater:0:outer:form");
         formTester.setValue("content:details:form:key:textField", "zBoolean");
         formTester.setValue("content:details:form:type:dropDownChoiceField", "3");
 
-        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:"
-                + "outer:dialog:footer:inputs:0:submit");
+        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
 
         TESTER.assertInfoMessages("Operation executed successfully");
 
@@ -88,21 +88,20 @@ public class SchemasITCase extends AbstractTypesITCase {
         assertNotNull(result);
 
         TESTER.executeAjaxEvent(result.getPageRelativePath(), Constants.ON_CLICK);
-        TESTER.clickLink(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:1:outer:"
+        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:1:outer:"
                 + "container:content:togglePanelContainer:container:actions:actions:actionRepeater:0:action:action");
 
-        TESTER.assertComponent(
-                "body:content:tabbedPanel:"
-                + "panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer:"
+        TESTER.assertComponent("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:0:outer:"
                 + "form:content:kindForm:kind:dropDownChoiceField", DropDownChoice.class);
 
-        FormTester formTester = TESTER.newFormTester(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer:form");
+        FormTester formTester = TESTER.newFormTester("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:0:outer:form");
         formTester.setValue("content:details:form:multivalue:checkboxField", "true");
 
-        TESTER.clickLink("body:content:tabbedPanel:panel:"
-                + "accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit",
+        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit",
                 true);
 
         TESTER.assertInfoMessages("Operation executed successfully");
@@ -113,20 +112,20 @@ public class SchemasITCase extends AbstractTypesITCase {
         browsingToPlainSchemas();
         //create new Plain Schema
         final String schemaName = "zStringDelete";
-        TESTER.clickLink(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:container:content:add");
+        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:container:content:add");
 
-        TESTER.assertComponent(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer",
+        TESTER.assertComponent("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:0:outer",
                 Modal.class);
 
         final FormTester formTester = TESTER.newFormTester("body:content:tabbedPanel:panel:"
-                + "accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer:form");
+                + "accordionPanel:tabs:0:body:content:content:outerObjectsRepeater:0:outer:form");
         formTester.setValue("content:details:form:key:textField", schemaName);
         formTester.setValue("content:details:form:type:dropDownChoiceField", "0");
 
-        TESTER.clickLink("body:content:tabbedPanel:panel:"
-                + "accordionPanel:tabs:0:body:content:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
+        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit");
 
         TESTER.assertInfoMessages("Operation executed successfully");;
 
@@ -145,12 +144,12 @@ public class SchemasITCase extends AbstractTypesITCase {
         TESTER.executeAjaxEvent(result.getPageRelativePath(), Constants.ON_CLICK);
 
         TESTER.getRequest().addParameter("confirm", "true");
-        TESTER.clickLink(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:1:outer:"
+        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:1:outer:"
                 + "container:content:togglePanelContainer:container:actions:actions:actionRepeater:1:action:action");
 
-        TESTER.executeAjaxEvent(TESTER.getComponentFromLastRenderedPage(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:0:body:content:outerObjectsRepeater:1:outer:"
+        TESTER.executeAjaxEvent(TESTER.getComponentFromLastRenderedPage("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:0:body:content:content:outerObjectsRepeater:1:outer:"
                 + "container:content:togglePanelContainer:container:actions:actions:actionRepeater:1:action:action"),
                 Constants.ON_CLICK);
 
@@ -163,19 +162,19 @@ public class SchemasITCase extends AbstractTypesITCase {
     @Test
     public void createVirtualSchema() {
         browsingToVirtualSchemas();
-        TESTER.clickLink(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:2:body:content:container:content:add");
+        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:2:body:content:content:container:content:add");
 
-        TESTER.assertComponent(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:2:body:content:outerObjectsRepeater:0:outer",
+        TESTER.assertComponent("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:2:body:content:content:outerObjectsRepeater:0:outer",
                 Modal.class);
 
-        final FormTester formTester = TESTER.newFormTester("body:content:tabbedPanel:panel:"
-                + "accordionPanel:tabs:2:body:content:outerObjectsRepeater:0:outer:form");
+        final FormTester formTester = TESTER.newFormTester("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:2:body:content:content:outerObjectsRepeater:0:outer:form");
 
         formTester.setValue("content:details:form:resource:dropDownChoiceField", "0");
         TESTER.executeAjaxEvent("body:content:tabbedPanel:panel:"
-                + "accordionPanel:tabs:2:body:content:outerObjectsRepeater:0:outer:form:"
+                + "accordionPanel:tabs:2:body:content:content:outerObjectsRepeater:0:outer:form:"
                 + "content:details:form:resource:dropDownChoiceField", Constants.ON_CHANGE);
 
         formTester.setValue("content:details:form:key:textField", "mynewvir");
@@ -183,8 +182,9 @@ public class SchemasITCase extends AbstractTypesITCase {
         formTester.setValue("content:details:form:anyType:dropDownChoiceField", "0");
         formTester.setValue("content:details:form:extAttrName:textField", "virattr");
 
-        TESTER.executeAjaxEvent("body:content:tabbedPanel:panel:accordionPanel:tabs:2:body:content:"
-                + "outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit", Constants.ON_CLICK);
+        TESTER.executeAjaxEvent("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:2:body:content:content:outerObjectsRepeater:0:outer:dialog:footer:inputs:0:submit",
+                Constants.ON_CLICK);
 
         TESTER.assertInfoMessages("Operation executed successfully");
         TESTER.cleanupFeedbackMessages();
@@ -194,12 +194,12 @@ public class SchemasITCase extends AbstractTypesITCase {
         TESTER.executeAjaxEvent(result.getPageRelativePath(), Constants.ON_CLICK);
 
         TESTER.getRequest().addParameter("confirm", "true");
-        TESTER.clickLink(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:2:body:content:outerObjectsRepeater:1:outer:"
+        TESTER.clickLink("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:2:body:content:content:outerObjectsRepeater:1:outer:"
                 + "container:content:togglePanelContainer:container:actions:actions:actionRepeater:1:action:action");
 
-        TESTER.executeAjaxEvent(TESTER.getComponentFromLastRenderedPage(
-                "body:content:tabbedPanel:panel:accordionPanel:tabs:2:body:content:outerObjectsRepeater:1:outer:"
+        TESTER.executeAjaxEvent(TESTER.getComponentFromLastRenderedPage("body:content:tabbedPanel:panel:accordionPanel:"
+                + "tabs:2:body:content:content:outerObjectsRepeater:1:outer:"
                 + "container:content:togglePanelContainer:container:actions:actions:actionRepeater:1:action:action"),
                 Constants.ON_CLICK);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DerSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DerSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DerSchemaITCase.java
index db8bdaa..ab877dc 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DerSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/DerSchemaITCase.java
@@ -47,6 +47,16 @@ public class DerSchemaITCase extends AbstractITCase {
     }
 
     @Test
+    public void search() {
+        List<DerSchemaTO> derSchemas =
+                schemaService.list(new SchemaQuery.Builder().type(SchemaType.DERIVED).keyword("mderivedd*").build());
+        assertFalse(derSchemas.isEmpty());
+        for (DerSchemaTO derivedSchemaTO : derSchemas) {
+            assertNotNull(derivedSchemaTO);
+        }
+    }
+
+    @Test
     public void read() {
         DerSchemaTO derivedSchemaTO = schemaService.read(SchemaType.DERIVED, "cn");
         assertNotNull(derivedSchemaTO);

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
index e36c8e5..83ad9f5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PlainSchemaITCase.java
@@ -264,6 +264,16 @@ public class PlainSchemaITCase extends AbstractITCase {
     }
 
     @Test
+    public void search() {
+        List<PlainSchemaTO> schemas =
+                schemaService.list(new SchemaQuery.Builder().type(SchemaType.PLAIN).keyword("fullna*").build());
+        assertFalse(schemas.isEmpty());
+        for (PlainSchemaTO schemaTO : schemas) {
+            assertNotNull(schemaTO);
+        }
+    }
+
+    @Test
     public void listByAnyTypeClass() {
         List<PlainSchemaTO> userSchemas = schemaService.list(
                 new SchemaQuery.Builder().type(SchemaType.PLAIN).anyTypeClass("minimal user").build());

http://git-wip-us.apache.org/repos/asf/syncope/blob/a42311f5/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirSchemaITCase.java
index faf1a0d..71aed10 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/VirSchemaITCase.java
@@ -51,6 +51,16 @@ public class VirSchemaITCase extends AbstractITCase {
     }
 
     @Test
+    public void search() {
+        List<VirSchemaTO> vSchemas =
+                schemaService.list(new SchemaQuery.Builder().type(SchemaType.VIRTUAL).keyword("rvirtuald*").build());
+        assertFalse(vSchemas.isEmpty());
+        for (VirSchemaTO vSchemaTO : vSchemas) {
+            assertNotNull(vSchemaTO);
+        }
+    }
+
+    @Test
     public void crud() {
         ResourceTO csv = resourceService.read(RESOURCE_NAME_CSV);
         assertNotNull(csv);