syncope-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ilgro...@apache.org
Subject [syncope] 02/02: [SYNCOPE-1395] persistence-jpa-pgjsonb module, passing all persistence-jpa's unit tests
Date Fri, 09 Nov 2018 14:04:40 GMT
This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git

commit c04c374b5b060c2b867467abe02ed874c63035c5
Author: Francesco Chicchiricc├▓ <ilgrosso@apache.org>
AuthorDate: Fri Nov 9 14:33:18 2018 +0100

    [SYNCOPE-1395] persistence-jpa-pgjsonb module, passing all persistence-jpa's unit tests
---
 core/persistence-jpa-pgjsonb/pom.xml               |  302 +++
 .../syncope/core/persistence/api/dao/PGAnyDAO.java |   38 +
 .../core/persistence/jpa/dao/PGJPAAnyDAO.java      |  355 +++
 .../persistence/jpa/dao/PGJPAAnyObjectDAO.java     |   81 +
 .../persistence/jpa/dao/PGJPAAnySearchDAO.java     |  231 ++
 .../core/persistence/jpa/dao/PGJPAGroupDAO.java    |   81 +
 .../persistence/jpa/dao/PGJPAPlainAttrDAO.java     |   34 +
 .../jpa/dao/PGJPAPlainAttrValueDAO.java            |   46 +
 .../persistence/jpa/dao/PGJPAPlainSchemaDAO.java   |   38 +
 .../core/persistence/jpa/dao/PGJPAUserDAO.java     |   89 +
 .../core/persistence/jpa/entity/PGJPAAny.java      |   33 +
 .../persistence/jpa/entity/PGJPAEntityFactory.java |  132 ++
 .../jpa/entity/PGJPAEntityListener.java            |   49 +
 .../core/persistence/jpa/entity/PGPlainAttr.java   |   30 +
 .../jpa/entity/anyobject/PGAPlainAttr.java         |  196 ++
 .../entity/anyobject/PGAPlainAttrUniqueValue.java  |   60 +
 .../jpa/entity/anyobject/PGAPlainAttrValue.java    |   48 +
 .../jpa/entity/anyobject/PGJPAAnyObject.java       |   97 +
 .../entity/anyobject/PGJPAAnyObjectListener.java   |   49 +
 .../persistence/jpa/entity/conf/PGCPlainAttr.java  |  163 ++
 .../jpa/entity/conf/PGCPlainAttrUniqueValue.java   |   60 +
 .../jpa/entity/conf/PGCPlainAttrValue.java         |   48 +
 .../persistence/jpa/entity/conf/PGJPAConf.java     |   85 +
 .../jpa/entity/conf/PGJPAConfListener.java         |   49 +
 .../persistence/jpa/entity/group/PGGPlainAttr.java |  163 ++
 .../jpa/entity/group/PGGPlainAttrUniqueValue.java  |   60 +
 .../jpa/entity/group/PGGPlainAttrValue.java        |   48 +
 .../persistence/jpa/entity/group/PGJPAGroup.java   |   87 +
 .../jpa/entity/group/PGJPAGroupListener.java       |   49 +
 .../persistence/jpa/entity/user/PGJPAUser.java     |   90 +
 .../jpa/entity/user/PGJPAUserListener.java         |   49 +
 .../persistence/jpa/entity/user/PGUPlainAttr.java  |  196 ++
 .../jpa/entity/user/PGUPlainAttrUniqueValue.java   |   60 +
 .../jpa/entity/user/PGUPlainAttrValue.java         |   48 +
 .../jpa/validation/entity/PGJPAAnyCheck.java       |   41 +
 .../jpa/validation/entity/PGJPAAnyValidator.java   |   45 +
 .../main/resources/META-INF/spring-orm-pgjsonb.xml |   37 +
 .../src/main/resources/domains/Master.properties   |   28 +
 .../src/main/resources/indexes.xml                 |   63 +
 .../src/main/resources/persistence.properties      |   26 +
 .../src/main/resources/views.xml                   |  154 ++
 .../src/test/resources/domains/MasterContent.xml   | 2410 ++++++++++++++++++++
 .../src/test/resources/persistenceTest.xml         |   55 +
 .../src/test/resources/simplelogger.properties     |   22 +
 core/pom.xml                                       |    1 +
 45 files changed, 6126 insertions(+)

diff --git a/core/persistence-jpa-pgjsonb/pom.xml b/core/persistence-jpa-pgjsonb/pom.xml
new file mode 100644
index 0000000..de08084
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/pom.xml
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.syncope</groupId>
+    <artifactId>syncope-core</artifactId>
+    <version>2.1.3-SNAPSHOT</version>
+  </parent>
+
+  <name>Apache Syncope Core Persistence JPA PostgreSQL jsonb</name>
+  <description>Apache Syncope Core Persistence JPA PostgreSQL jsonb</description>
+  <groupId>org.apache.syncope.core</groupId>
+  <artifactId>syncope-core-persistence-jpa-pgjsonb</artifactId>
+  <packaging>jar</packaging>
+  
+  <properties>
+    <rootpom.basedir>${basedir}/../..</rootpom.basedir>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.syncope.core</groupId>
+      <artifactId>syncope-core-persistence-jpa</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <!-- TEST -->
+    <dependency> 
+      <groupId>javax.servlet</groupId> 
+      <artifactId>javax.servlet-api</artifactId> 
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-simple</artifactId>
+      <version>${slf4j.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>jcl-over-slf4j</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>com.h2database</groupId>
+      <artifactId>h2</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter-engine</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.openjpa</groupId>
+        <artifactId>openjpa-maven-plugin</artifactId>
+        <inherited>true</inherited>
+        <dependencies>
+          <dependency>
+            <groupId>com.h2database</groupId>
+            <artifactId>h2</artifactId>
+            <version>${h2.version}</version>
+          </dependency>
+        </dependencies>
+        <configuration>
+          <persistenceXmlFile>${project.basedir}/../persistence-jpa/src/main/resources/persistence-enhance.xml</persistenceXmlFile> 
+          <includes>org/apache/syncope/core/persistence/jpa/entity/**/*.class</includes>
+          <connectionDriverName>org.springframework.jdbc.datasource.DriverManagerDataSource</connectionDriverName>
+          <connectionProperties>
+            driverClassName=org.h2.Driver,
+            url=jdbc:h2:mem:syncopedb
+            username=sa,
+            password=
+          </connectionProperties>
+        </configuration>
+        <executions>
+          <execution>
+            <id>enhancer</id>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>enhance</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+      </plugin>
+    </plugins>
+
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+      </resource>
+    </resources>
+  </build>
+
+  <profiles>
+    <profile>
+      <id>ut</id>
+      
+      <dependencies>
+        <dependency>
+          <groupId>org.postgresql</groupId>
+          <artifactId>postgresql</artifactId>
+          <version>${jdbc.postgresql.version}</version>
+          <scope>test</scope>
+        </dependency>
+      </dependencies>
+
+      <build>
+        <defaultGoal>clean verify</defaultGoal>
+        
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>build-helper-maven-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>add-test-source</id>
+                <phase>generate-test-sources</phase>
+                <goals>
+                  <goal>add-test-source</goal>
+                </goals>
+                <configuration>
+                  <sources>
+                    <source>${basedir}/../persistence-jpa/src/test/java</source>
+                  </sources>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+      
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <skip>true</skip>
+            </configuration>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-failsafe-plugin</artifactId>
+            <configuration>
+              <includes>
+                <include>**/*Test.java</include>
+              </includes>
+              <excludedGroups>multitenancy,plainAttrTable</excludedGroups>
+            </configuration>
+          </plugin>
+
+          <plugin>
+            <groupId>io.fabric8</groupId>
+            <artifactId>docker-maven-plugin</artifactId>
+            <configuration>
+              <images>
+                <image>
+                  <name>crunchydata/crunchy-postgres:centos7-10.5-2.1.0</name>
+                  <run>
+                    <env>
+                      <PG_ROOT_PASSWORD>postgres</PG_ROOT_PASSWORD>
+                      <PG_MODE>primary</PG_MODE>
+                      <PG_PRIMARY_USER>postgres</PG_PRIMARY_USER>
+                      <PG_PRIMARY_PASSWORD>postgres</PG_PRIMARY_PASSWORD>
+                      <PG_PRIMARY_HOST>localhost</PG_PRIMARY_HOST>
+                      <PG_PRIMARY_PORT>5432</PG_PRIMARY_PORT>
+                      <PG_DATABASE>syncope</PG_DATABASE>
+                      <PG_USER>syncope</PG_USER>
+                      <PG_PASSWORD>syncope</PG_PASSWORD>
+                    </env>
+                    <ports>
+                      <port>5432:5432</port>
+                    </ports>
+                  </run>
+                </image>
+              </images>
+            </configuration>
+            <executions>
+              <execution>
+                <id>start-postgres</id>
+                <phase>pre-integration-test</phase>
+                <goals>
+                  <goal>start</goal>
+                </goals>
+              </execution>
+              <execution>
+                <id>stop-postgres</id>
+                <phase>post-integration-test</phase>
+                <goals>
+                  <goal>stop</goal>
+                  <goal>remove</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+        
+        <testResources>
+          <testResource>
+            <directory>src/test/resources</directory>
+            <filtering>true</filtering>
+          </testResource>
+          <testResource>
+            <directory>src/main/resources</directory>
+            <filtering>true</filtering>
+          </testResource>
+        </testResources>
+      </build>
+    </profile>
+    
+    <profile>
+      <id>sqlgen</id>
+      
+      <properties>
+        <skipTests>true</skipTests>
+      </properties>
+      
+      <build>
+        <defaultGoal>clean verify</defaultGoal>
+        
+        <plugins>
+          <plugin>
+            <groupId>org.apache.openjpa</groupId>
+            <artifactId>openjpa-maven-plugin</artifactId>
+            <inherited>true</inherited>
+            <executions>
+              <execution>
+                <id>sqlgen</id>
+                <phase>process-classes</phase>
+                <goals>
+                  <goal>sql</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>          
+        </plugins>
+      </build>
+    </profile>
+    
+    <profile>
+      <id>schemagen</id>
+      
+      <properties>
+        <skipTests>true</skipTests>
+      </properties>
+      
+      <build>
+        <defaultGoal>clean verify</defaultGoal>
+        
+        <plugins>
+          <plugin>
+            <groupId>org.apache.openjpa</groupId>
+            <artifactId>openjpa-maven-plugin</artifactId>
+            <inherited>true</inherited>
+            <executions>
+              <execution>
+                <id>schemagen</id>
+                <phase>process-classes</phase>
+                <goals>
+                  <goal>schema</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>          
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/api/dao/PGAnyDAO.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/api/dao/PGAnyDAO.java
new file mode 100644
index 0000000..2fecad7
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/api/dao/PGAnyDAO.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.persistence.api.dao;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+
+public interface PGAnyDAO {
+
+    <A extends Any<?>> List<A> findByDerAttrValue(
+            String table, AnyUtils anyUtils, String schemaKey, String value, boolean ignoreCaseMatch);
+
+    <A extends Any<?>> A findByPlainAttrUniqueValue(
+            String table, AnyUtils anyUtils, String schemaKey, PlainAttrValue attrUniqueValue, boolean ignoreCaseMatch);
+
+    <A extends Any<?>> List<A> findByPlainAttrValue(
+            String table, AnyUtils anyUtils, String schemaKey, PlainAttrValue attrValue, boolean ignoreCaseMatch);
+
+    <A extends Any<?>> void checkBeforeSave(String table, AnyUtils anyUtils, A any);
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAAnyDAO.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAAnyDAO.java
new file mode 100644
index 0000000..030bba8
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAAnyDAO.java
@@ -0,0 +1,355 @@
+/*
+ * 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.core.persistence.jpa.dao;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.StringJoiner;
+import java.util.regex.Pattern;
+import javax.persistence.Query;
+import org.apache.commons.jexl3.parser.Parser;
+import org.apache.commons.jexl3.parser.ParserConstants;
+import org.apache.commons.jexl3.parser.Token;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.DuplicateException;
+import org.apache.syncope.core.persistence.api.dao.PGAnyDAO;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import org.apache.syncope.core.spring.security.AuthContextUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository
+public class PGJPAAnyDAO extends AbstractDAO<AbstractEntity> implements PGAnyDAO {
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Autowired
+    private DerSchemaDAO derSchemaDAO;
+
+    private String queryBegin(final String table) {
+        return "SELECT DISTINCT id FROM " + table + " u,"
+                + "jsonb_array_elements(u.plainAttrs) attrs,"
+                + "jsonb_array_elements(COALESCE(attrs -> 'values', '[{}]'::jsonb)) attrValues ";
+    }
+
+    private String attrValueMatch(
+            final AnyUtils anyUtils,
+            final PlainSchema schema,
+            final PlainAttrValue attrValue,
+            final boolean ignoreCaseMatch) {
+
+        String key;
+        boolean lower = false;
+
+        switch (schema.getType()) {
+            case Boolean:
+                key = "booleanValue";
+                break;
+
+            case Date:
+                key = "dateValue";
+                break;
+
+            case Double:
+                key = "doubleValue";
+                break;
+
+            case Long:
+                key = "longValue";
+                break;
+
+            case Binary:
+                key = "binaryValue";
+                break;
+
+            default:
+                lower = ignoreCaseMatch;
+                key = "stringValue";
+        }
+
+        if (lower) {
+            return "attrs ->> 'schema' = ? "
+                    + "AND "
+                    + (lower ? "LOWER(" : "")
+                    + (schema.isUniqueConstraint() ? "attrs -> 'uniqueValue'" : "attrValues") + " ->> '" + key
+                    + "'" + (lower ? ")" : "")
+                    + " = "
+                    + (lower ? "LOWER(" : "")
+                    + "?"
+                    + (lower ? ")" : "");
+        } else {
+            PlainAttr<?> container = anyUtils.newPlainAttr();
+            container.setSchema(schema);
+            if (attrValue instanceof PlainAttrUniqueValue) {
+                container.setUniqueValue((PlainAttrUniqueValue) attrValue);
+            } else {
+                ((PGPlainAttr) container).add(attrValue);
+            }
+            return "plainAttrs @> '" + POJOHelper.serialize(Arrays.asList(container)) + "'::jsonb";
+        }
+    }
+
+    private <A extends Any<?>> List<A> buildResult(final AnyUtils anyUtils, final List<Object> queryResult) {
+        List<A> result = new ArrayList<>();
+        queryResult.forEach(anyKey -> {
+            A any = anyUtils.<A>dao().find(anyKey.toString());
+            if (any == null) {
+                LOG.error("Could not find any for key {}", anyKey);
+            } else {
+                result.add(any);
+            }
+        });
+        return result;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Transactional(readOnly = true)
+    @Override
+    public <A extends Any<?>> List<A> findByPlainAttrValue(
+            final String table,
+            final AnyUtils anyUtils,
+            final String schemaKey,
+            final PlainAttrValue attrValue,
+            final boolean ignoreCaseMatch) {
+
+        PlainSchema schema = plainSchemaDAO.find(schemaKey);
+        if (schema == null) {
+            LOG.error("Invalid schema '{}'", schemaKey);
+            return Collections.<A>emptyList();
+        }
+
+        Query query = entityManager().createNativeQuery(
+                queryBegin(table)
+                + "WHERE " + attrValueMatch(anyUtils, schema, attrValue, ignoreCaseMatch));
+        query.setParameter(1, schemaKey);
+        query.setParameter(2, attrValue.getValue());
+
+        return buildResult(anyUtils, query.getResultList());
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public <A extends Any<?>> A findByPlainAttrUniqueValue(
+            final String table,
+            final AnyUtils anyUtils,
+            final String schemaKey,
+            final PlainAttrValue attrUniqueValue,
+            final boolean ignoreCaseMatch) {
+
+        PlainSchema schema = plainSchemaDAO.find(schemaKey);
+        if (schema == null) {
+            LOG.error("Invalid schema '{}'", schemaKey);
+            return null;
+        }
+        if (!schema.isUniqueConstraint()) {
+            LOG.error("This schema has not unique constraint: '{}'", schemaKey);
+            return null;
+        }
+
+        List<A> result = findByPlainAttrValue(table, anyUtils, schemaKey, attrUniqueValue, ignoreCaseMatch);
+        return result.isEmpty()
+                ? null
+                : result.get(0);
+    }
+
+    /**
+     * Split an attribute value recurring on provided literals/tokens.
+     *
+     * @param attrValue value to be split
+     * @param literals literals/tokens
+     * @return split value
+     */
+    private List<String> split(final String attrValue, final List<String> literals) {
+        final List<String> attrValues = new ArrayList<>();
+
+        if (literals.isEmpty()) {
+            attrValues.add(attrValue);
+        } else {
+            for (String token : attrValue.split(Pattern.quote(literals.get(0)))) {
+                if (!token.isEmpty()) {
+                    attrValues.addAll(split(token, literals.subList(1, literals.size())));
+                }
+            }
+        }
+
+        return attrValues;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Transactional(readOnly = true)
+    @Override
+    public <A extends Any<?>> List<A> findByDerAttrValue(
+            final String table,
+            final AnyUtils anyUtils,
+            final String schemaKey,
+            final String value,
+            final boolean ignoreCaseMatch) {
+
+        DerSchema derSchema = derSchemaDAO.find(schemaKey);
+        if (derSchema == null) {
+            LOG.error("Invalid schema '{}'", schemaKey);
+            return Collections.<A>emptyList();
+        }
+
+        Parser parser = new Parser(new StringReader(derSchema.getExpression()));
+
+        // Schema keys
+        List<String> identifiers = new ArrayList<>();
+
+        // Literals
+        List<String> literals = new ArrayList<>();
+
+        // Get schema keys and literals
+        for (Token token = parser.getNextToken(); token != null && StringUtils.isNotBlank(token.toString());
+                token = parser.getNextToken()) {
+
+            if (token.kind == ParserConstants.STRING_LITERAL) {
+                literals.add(token.toString().substring(1, token.toString().length() - 1));
+            }
+
+            if (token.kind == ParserConstants.IDENTIFIER) {
+                identifiers.add(token.toString());
+            }
+        }
+
+        // Sort literals in order to process later literals included into others
+        Collections.sort(literals, (l1, l2) -> {
+            if (l1 == null && l2 == null) {
+                return 0;
+            } else if (l1 != null && l2 == null) {
+                return -1;
+            } else if (l1 == null && l2 != null) {
+                return 1;
+            } else if (l1.length() == l2.length()) {
+                return 0;
+            } else if (l1.length() > l2.length()) {
+                return -1;
+            } else {
+                return 1;
+            }
+        });
+
+        // Split value on provided literals
+        List<String> attrValues = split(value, literals);
+
+        if (attrValues.size() != identifiers.size()) {
+            LOG.error("Ambiguous JEXL expression resolution: literals and values have different size");
+            return Collections.emptyList();
+        }
+
+        StringJoiner clauses = new StringJoiner(" AND id IN ");
+
+        // builder to build the clauses
+        StringBuilder bld = new StringBuilder();
+
+        // Contains used identifiers in order to avoid replications
+        Set<String> used = new HashSet<>();
+
+        List<Object> queryParams = new ArrayList<>();
+
+        // Create several clauses: one for eanch identifiers
+        for (int i = 0; i < identifiers.size(); i++) {
+            if (!used.contains(identifiers.get(i))) {
+                // verify schema existence and get schema type
+                PlainSchema schema = plainSchemaDAO.find(identifiers.get(i));
+                if (schema == null) {
+                    LOG.error("Invalid schema '{}', ignoring", identifiers.get(i));
+                } else {
+                    // clear builder
+                    bld.delete(0, bld.length());
+
+                    PlainAttrValue attrValue;
+                    if (schema.isUniqueConstraint()) {
+                        attrValue = anyUtils.newPlainAttrUniqueValue();
+                    } else {
+                        attrValue = anyUtils.newPlainAttrValue();
+                    }
+                    attrValue.setStringValue(attrValues.get(i));
+
+                    bld.append('(').
+                            append(queryBegin(table)).
+                            append("WHERE ").
+                            append(attrValueMatch(anyUtils, schema, attrValue, ignoreCaseMatch)).
+                            append(')');
+                    queryParams.add(schema.getKey());
+                    queryParams.add(attrValues.get(i));
+
+                    used.add(identifiers.get(i));
+
+                    clauses.add(bld.toString());
+                }
+            }
+        }
+
+        LOG.debug("Generated where clauses {}", clauses);
+
+        Query query = entityManager().createNativeQuery(
+                "SELECT DISTINCT id FROM " + table + " u WHERE id IN " + clauses.toString());
+        for (int i = 0; i < queryParams.size(); i++) {
+            query.setParameter(i + 1, queryParams.get(i));
+        }
+
+        return buildResult(anyUtils, query.getResultList());
+    }
+
+    @Transactional
+    @Override
+    public <A extends Any<?>> void checkBeforeSave(final String table, final AnyUtils anyUtils, final A any) {
+        // check UNIQUE constraints
+        any.getPlainAttrs().stream().
+                filter(attr -> attr.getUniqueValue() != null).
+                map(PGPlainAttr.class::cast).
+                forEach(attr -> {
+                    String schemaKey = attr.getSchemaKey();
+                    List<A> others = findByPlainAttrValue(table, anyUtils, schemaKey, attr.getUniqueValue(), false);
+                    if (others.isEmpty() || (others.size() == 1 && others.get(0).getKey().equals(any.getKey()))) {
+                        LOG.debug("No duplicate value found for {}", attr.getUniqueValue().getValueAsString());
+                    } else {
+                        throw new DuplicateException(
+                                "Value " + attr.getUniqueValue().getValueAsString() + " existing for " + schemaKey);
+                    }
+                });
+
+        // update sysInfo - as org.apache.syncope.core.persistence.jpa.entity.PlainAttrListener is not invoked
+        Date now = new Date();
+        String username = AuthContextUtils.getUsername();
+        LOG.debug("Set last change date '{}' and modifier '{}' for '{}'", now, username, any);
+        any.setLastModifier(username);
+        any.setLastChangeDate(now);
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAAnyObjectDAO.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAAnyObjectDAO.java
new file mode 100644
index 0000000..4879f26
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAAnyObjectDAO.java
@@ -0,0 +1,81 @@
+/*
+ * 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.core.persistence.jpa.dao;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.api.dao.PGAnyDAO;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.jpa.entity.anyobject.PGJPAAnyObject;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.springframework.transaction.annotation.Transactional;
+
+public class PGJPAAnyObjectDAO extends JPAAnyObjectDAO {
+
+    private PGAnyDAO anyDAO;
+
+    private PGAnyDAO anyDAO() {
+        if (anyDAO == null) {
+            anyDAO = ApplicationContextProvider.getApplicationContext().getBean(PGAnyDAO.class);
+        }
+        return anyDAO;
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public AnyObject find(final String key) {
+        return entityManager().find(PGJPAAnyObject.class, key);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public List<AnyObject> findByPlainAttrValue(
+            final String schemaKey,
+            final PlainAttrValue attrValue,
+            final boolean ignoreCaseMatch) {
+
+        return anyDAO().findByPlainAttrValue(PGJPAAnyObject.TABLE, anyUtils(), schemaKey, attrValue, ignoreCaseMatch);
+    }
+
+    @Override
+    public AnyObject findByPlainAttrUniqueValue(
+            final String schemaKey,
+            final PlainAttrValue attrUniqueValue,
+            final boolean ignoreCaseMatch) {
+
+        return anyDAO().findByPlainAttrUniqueValue(PGJPAAnyObject.TABLE, anyUtils(),
+                schemaKey, attrUniqueValue, ignoreCaseMatch);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public List<AnyObject> findByDerAttrValue(
+            final String schemaKey,
+            final String value,
+            final boolean ignoreCaseMatch) {
+
+        return anyDAO().findByDerAttrValue(PGJPAAnyObject.TABLE, anyUtils(), schemaKey, value, ignoreCaseMatch);
+    }
+
+    @Override
+    public AnyObject save(final AnyObject anyObject) {
+        anyDAO().checkBeforeSave(PGJPAAnyObject.TABLE, anyUtils(), anyObject);
+        return super.save(anyObject);
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAAnySearchDAO.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAAnySearchDAO.java
new file mode 100644
index 0000000..0fa44f0
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAAnySearchDAO.java
@@ -0,0 +1,231 @@
+/*
+ * 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.core.persistence.jpa.dao;
+
+import java.util.Arrays;
+import java.util.List;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.core.persistence.api.dao.search.AttributeCond;
+import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+
+public class PGJPAAnySearchDAO extends JPAAnySearchDAO {
+
+    @Override
+    SearchSupport buildSearchSupport(final AnyTypeKind kind) {
+        return new SearchSupport(kind);
+    }
+
+    @Override
+    protected void processOBS(final SearchSupport svs, final OrderBySupport obs, final StringBuilder where) {
+        obs.views.forEach(searchView -> {
+            where.append(',').
+                    append(searchView.name).
+                    append(' ').append(searchView.alias);
+        });
+    }
+
+    @Override
+    protected void parseOrderByForPlainSchema(
+            final SearchSupport svs,
+            final OrderBySupport obs,
+            final OrderBySupport.Item item,
+            final OrderByClause clause,
+            final PlainSchema schema,
+            final String fieldName) {
+
+        // keep track of involvement of non-mandatory schemas in the order by clauses
+        obs.nonMandatorySchemas = !"true".equals(schema.getMandatoryCondition());
+
+        obs.views.add(svs.field());
+
+        item.select = svs.field().alias + ".attrValues ->> '" + fieldName + "' AS " + fieldName;
+        item.where = "attrs ->> 'schema' = '" + fieldName + "'";
+        item.orderBy = fieldName + " " + clause.getDirection().name();
+    }
+
+    private void fillAttrQuery(
+            final AnyUtils anyUtils,
+            final StringBuilder query,
+            final PlainAttrValue attrValue,
+            final PlainSchema schema,
+            final AttributeCond cond,
+            final boolean not,
+            final List<Object> parameters) {
+
+        String key;
+        boolean lower = false;
+        switch (schema.getType()) {
+            case Boolean:
+                key = "booleanValue";
+                break;
+
+            case Date:
+                key = "dateValue";
+                break;
+
+            case Double:
+                key = "doubleValue";
+                break;
+
+            case Long:
+                key = "longValue";
+                break;
+
+            case Binary:
+                key = "binaryValue";
+                break;
+
+            default:
+                lower = cond.getType() == AttributeCond.Type.IEQ || cond.getType() == AttributeCond.Type.ILIKE;
+                key = "stringValue";
+        }
+
+        if (!not && cond.getType() == AttributeCond.Type.EQ) {
+            PlainAttr<?> container = anyUtils.newPlainAttr();
+            container.setSchema(schema);
+            if (attrValue instanceof PlainAttrUniqueValue) {
+                container.setUniqueValue((PlainAttrUniqueValue) attrValue);
+            } else {
+                ((PGPlainAttr) container).add(attrValue);
+            }
+
+            query.append("plainAttrs @> '").
+                    append(POJOHelper.serialize(Arrays.asList(container))).
+                    append("'::jsonb");
+        } else {
+            query.append("attrs ->> 'schema' = ?").append(setParameter(parameters, cond.getSchema())).
+                    append(" AND ").
+                    append(lower ? "LOWER(" : "").
+                    append(schema.isUniqueConstraint()
+                            ? "attrs -> 'uniqueValue'" : "attrValues").
+                    append(" ->> '").append(key).append("'").
+                    append(lower ? ")" : "");
+
+            switch (cond.getType()) {
+                case LIKE:
+                case ILIKE:
+                    if (not) {
+                        query.append("NOT ");
+                    }
+                    query.append(" LIKE ");
+                    break;
+
+                case GE:
+                    if (not) {
+                        query.append('<');
+                    } else {
+                        query.append(">=");
+                    }
+                    break;
+
+                case GT:
+                    if (not) {
+                        query.append("<=");
+                    } else {
+                        query.append('>');
+                    }
+                    break;
+
+                case LE:
+                    if (not) {
+                        query.append('>');
+                    } else {
+                        query.append("<=");
+                    }
+                    break;
+
+                case LT:
+                    if (not) {
+                        query.append(">=");
+                    } else {
+                        query.append('<');
+                    }
+                    break;
+
+                case EQ:
+                case IEQ:
+                default:
+                    if (not) {
+                        query.append('!');
+                    }
+                    query.append('=');
+            }
+
+            query.append(lower ? "LOWER(" : "").
+                    append("?").append(setParameter(parameters, cond.getExpression())).
+                    append(lower ? ")" : "");
+        }
+    }
+
+    @Override
+    protected String getQuery(
+            final AttributeCond cond,
+            final boolean not,
+            final List<Object> parameters,
+            final SearchSupport svs) {
+
+        Pair<PlainSchema, PlainAttrValue> checked;
+        try {
+            checked = check(cond, svs.anyTypeKind);
+        } catch (IllegalArgumentException e) {
+            return EMPTY_QUERY;
+        }
+
+        // normalize NULL / NOT NULL checks
+        if (not) {
+            if (cond.getType() == AttributeCond.Type.ISNULL) {
+                cond.setType(AttributeCond.Type.ISNOTNULL);
+            } else if (cond.getType() == AttributeCond.Type.ISNOTNULL) {
+                cond.setType(AttributeCond.Type.ISNULL);
+            }
+        }
+
+        StringBuilder query = new StringBuilder("SELECT DISTINCT any_id FROM ").
+                append(svs.field().name).append(" WHERE ");
+        switch (cond.getType()) {
+            case ISNOTNULL:
+                query.append("plainAttrs @> '[{\"schema\":\"").
+                        append(checked.getLeft().getKey()).
+                        append("\"}]'::jsonb");
+                break;
+
+            case ISNULL:
+                query.append("any_id NOT IN (").
+                        append("SELECT any_id FROM ").append(svs.field().name).
+                        append(" WHERE plainAttrs @> '[{\"schema\":\"").
+                        append(checked.getLeft().getKey()).
+                        append("\"}]'::jsonb)");
+                break;
+
+            default:
+                fillAttrQuery(anyUtilsFactory.getInstance(svs.anyTypeKind),
+                        query, checked.getRight(), checked.getLeft(), cond, not, parameters);
+        }
+
+        return query.toString();
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAGroupDAO.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAGroupDAO.java
new file mode 100644
index 0000000..4c020c6
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAGroupDAO.java
@@ -0,0 +1,81 @@
+/*
+ * 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.core.persistence.jpa.dao;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.api.dao.PGAnyDAO;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.jpa.entity.group.PGJPAGroup;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.springframework.transaction.annotation.Transactional;
+
+public class PGJPAGroupDAO extends JPAGroupDAO {
+
+    private PGAnyDAO anyDAO;
+
+    private PGAnyDAO anyDAO() {
+        if (anyDAO == null) {
+            anyDAO = ApplicationContextProvider.getApplicationContext().getBean(PGAnyDAO.class);
+        }
+        return anyDAO;
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public Group find(final String key) {
+        return entityManager().find(PGJPAGroup.class, key);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public List<Group> findByPlainAttrValue(
+            final String schemaKey,
+            final PlainAttrValue attrValue,
+            final boolean ignoreCaseMatch) {
+
+        return anyDAO().findByPlainAttrValue(PGJPAGroup.TABLE, anyUtils(), schemaKey, attrValue, ignoreCaseMatch);
+    }
+
+    @Override
+    public Group findByPlainAttrUniqueValue(
+            final String schemaKey,
+            final PlainAttrValue attrUniqueValue,
+            final boolean ignoreCaseMatch) {
+
+        return anyDAO().findByPlainAttrUniqueValue(PGJPAGroup.TABLE, anyUtils(),
+                schemaKey, attrUniqueValue, ignoreCaseMatch);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public List<Group> findByDerAttrValue(
+            final String schemaKey,
+            final String value,
+            final boolean ignoreCaseMatch) {
+
+        return anyDAO().findByDerAttrValue(PGJPAGroup.TABLE, anyUtils(), schemaKey, value, ignoreCaseMatch);
+    }
+
+    @Override
+    public Group save(final Group group) {
+        anyDAO().checkBeforeSave(PGJPAGroup.TABLE, anyUtils(), group);
+        return super.save(group);
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAPlainAttrDAO.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAPlainAttrDAO.java
new file mode 100644
index 0000000..5ede5a6
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAPlainAttrDAO.java
@@ -0,0 +1,34 @@
+/*
+ * 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.core.persistence.jpa.dao;
+
+import org.apache.syncope.core.persistence.api.dao.PlainAttrDAO;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+
+public class PGJPAPlainAttrDAO extends AbstractDAO<PlainAttr<?>> implements PlainAttrDAO {
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T extends PlainAttr<?>> void delete(final T plainAttr) {
+        if (plainAttr.getOwner() != null) {
+            ((Any<T>) plainAttr.getOwner()).remove(plainAttr);
+        }
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAPlainAttrValueDAO.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAPlainAttrValueDAO.java
new file mode 100644
index 0000000..0b67612
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAPlainAttrValueDAO.java
@@ -0,0 +1,46 @@
+/*
+ * 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.core.persistence.jpa.dao;
+
+import static org.apache.syncope.core.persistence.jpa.dao.JPAPlainAttrValueDAO.getEntityReference;
+
+import java.util.stream.Collectors;
+import org.apache.syncope.core.persistence.api.dao.PlainAttrValueDAO;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.Entity;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+
+public class PGJPAPlainAttrValueDAO extends AbstractDAO<PlainAttrValue> implements PlainAttrValueDAO {
+
+    @Override
+    public void deleteAll(final PlainAttr<?> attr, final AnyUtils anyUtils) {
+        if (attr.getUniqueValue() == null) {
+            attr.getValues().stream().map(Entity::getKey).collect(Collectors.toSet()).forEach(attrValueKey -> {
+                PlainAttrValue attrValue = anyUtils.plainAttrValueClass().cast(
+                        entityManager().find(getEntityReference(anyUtils.plainAttrValueClass()), attrValueKey));
+                if (attrValue != null) {
+                    attr.getValues().remove(attrValue);
+                }
+            });
+        } else {
+            attr.setUniqueValue(null);
+        }
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAPlainSchemaDAO.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAPlainSchemaDAO.java
new file mode 100644
index 0000000..ba8b97b
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAPlainSchemaDAO.java
@@ -0,0 +1,38 @@
+/*
+ * 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.core.persistence.jpa.dao;
+
+import java.util.Collections;
+import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+
+public class PGJPAPlainSchemaDAO extends JPAPlainSchemaDAO {
+
+    @Override
+    public <T extends PlainAttr<?>> List<T> findAttrs(final PlainSchema schema, final Class<T> reference) {
+        // not possible
+        return Collections.emptyList();
+    }
+
+    @Override
+    protected void deleteAttrs(final PlainSchema schema) {
+        // nothing to do
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAUserDAO.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAUserDAO.java
new file mode 100644
index 0000000..340ba6e
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/dao/PGJPAUserDAO.java
@@ -0,0 +1,89 @@
+/*
+ * 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.core.persistence.jpa.dao;
+
+import java.util.List;
+import java.util.Set;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.core.persistence.api.dao.PGAnyDAO;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.persistence.jpa.entity.user.PGJPAUser;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+import org.springframework.transaction.annotation.Transactional;
+
+public class PGJPAUserDAO extends JPAUserDAO {
+
+    private PGAnyDAO anyDAO;
+
+    private PGAnyDAO anyDAO() {
+        if (anyDAO == null) {
+            anyDAO = ApplicationContextProvider.getApplicationContext().getBean(PGAnyDAO.class);
+        }
+        return anyDAO;
+    }
+
+    @Transactional(readOnly = true)
+    @Override
+    public User find(final String key) {
+        return entityManager().find(PGJPAUser.class, key);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public List<User> findByPlainAttrValue(
+            final String schemaKey,
+            final PlainAttrValue attrValue,
+            final boolean ignoreCaseMatch) {
+
+        return anyDAO().findByPlainAttrValue(PGJPAUser.TABLE, anyUtils(), schemaKey, attrValue, ignoreCaseMatch);
+    }
+
+    @Override
+    public User findByPlainAttrUniqueValue(
+            final String schemaKey,
+            final PlainAttrValue attrUniqueValue,
+            final boolean ignoreCaseMatch) {
+
+        return anyDAO().findByPlainAttrUniqueValue(PGJPAUser.TABLE, anyUtils(),
+                schemaKey, attrUniqueValue, ignoreCaseMatch);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public List<User> findByDerAttrValue(
+            final String schemaKey,
+            final String value,
+            final boolean ignoreCaseMatch) {
+
+        return anyDAO().findByDerAttrValue(PGJPAUser.TABLE, anyUtils(), schemaKey, value, ignoreCaseMatch);
+    }
+
+    @Override
+    public User save(final User user) {
+        anyDAO().checkBeforeSave(PGJPAUser.TABLE, anyUtils(), user);
+        return super.save(user);
+    }
+
+    @Override
+    public Pair<Set<String>, Set<String>> saveAndGetDynGroupMembs(final User user) {
+        anyDAO().checkBeforeSave(PGJPAUser.TABLE, anyUtils(), user);
+        return super.saveAndGetDynGroupMembs(user);
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGJPAAny.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGJPAAny.java
new file mode 100644
index 0000000..005e616
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGJPAAny.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.entity;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.Any;
+
+public interface PGJPAAny<A extends Any<?>> {
+
+    String getPlainAttrsJSON();
+
+    void setPlainAttrsJSON(String plainAttrs);
+
+    boolean add(PGPlainAttr<A> attr);
+
+    List<? extends PGPlainAttr<A>> getPlainAttrList();
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGJPAEntityFactory.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGJPAEntityFactory.java
new file mode 100644
index 0000000..0054d3f
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGJPAEntityFactory.java
@@ -0,0 +1,132 @@
+/*
+ * 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.core.persistence.jpa.entity;
+
+import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
+import org.apache.syncope.core.persistence.api.entity.Entity;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.conf.Conf;
+import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.persistence.jpa.dao.PGJPAAnySearchDAO;
+import org.apache.syncope.core.persistence.jpa.entity.anyobject.PGAPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.anyobject.PGAPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.jpa.entity.anyobject.PGAPlainAttrValue;
+import org.apache.syncope.core.persistence.jpa.entity.anyobject.PGJPAAnyObject;
+import org.apache.syncope.core.persistence.jpa.entity.conf.PGCPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.conf.PGCPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.jpa.entity.conf.PGCPlainAttrValue;
+import org.apache.syncope.core.persistence.jpa.entity.conf.PGJPAConf;
+import org.apache.syncope.core.persistence.jpa.entity.group.PGGPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.group.PGGPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.jpa.entity.group.PGGPlainAttrValue;
+import org.apache.syncope.core.persistence.jpa.entity.group.PGJPAGroup;
+import org.apache.syncope.core.persistence.jpa.entity.user.PGJPAUser;
+import org.apache.syncope.core.persistence.jpa.entity.user.PGUPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.user.PGUPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.jpa.entity.user.PGUPlainAttrValue;
+import org.apache.syncope.core.spring.security.SecureRandomUtils;
+
+public class PGJPAEntityFactory extends JPAEntityFactory {
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <E extends Entity> E newEntity(final Class<E> reference) {
+        E result;
+
+        if (reference.equals(User.class)) {
+            result = (E) new PGJPAUser();
+            ((PGJPAUser) result).setKey(SecureRandomUtils.generateRandomUUID().toString());
+        } else if (reference.equals(Group.class)) {
+            result = (E) new PGJPAGroup();
+            ((PGJPAGroup) result).setKey(SecureRandomUtils.generateRandomUUID().toString());
+        } else if (reference.equals(AnyObject.class)) {
+            result = (E) new PGJPAAnyObject();
+            ((PGJPAAnyObject) result).setKey(SecureRandomUtils.generateRandomUUID().toString());
+        } else if (reference.equals(Conf.class)) {
+            result = (E) new PGJPAConf();
+            ((PGJPAConf) result).setKey(SecureRandomUtils.generateRandomUUID().toString());
+        } else if (reference.equals(APlainAttr.class)) {
+            result = (E) new PGAPlainAttr();
+        } else if (reference.equals(APlainAttrValue.class)) {
+            result = (E) new PGAPlainAttrValue();
+        } else if (reference.equals(APlainAttrUniqueValue.class)) {
+            result = (E) new PGAPlainAttrUniqueValue();
+        } else if (reference.equals(CPlainAttr.class)) {
+            result = (E) new PGCPlainAttr();
+        } else if (reference.equals(CPlainAttrValue.class)) {
+            result = (E) new PGCPlainAttrValue();
+        } else if (reference.equals(CPlainAttrUniqueValue.class)) {
+            result = (E) new PGCPlainAttrUniqueValue();
+        } else if (reference.equals(GPlainAttr.class)) {
+            result = (E) new PGGPlainAttr();
+        } else if (reference.equals(GPlainAttrValue.class)) {
+            result = (E) new PGGPlainAttrValue();
+        } else if (reference.equals(GPlainAttrUniqueValue.class)) {
+            result = (E) new PGGPlainAttrUniqueValue();
+        } else if (reference.equals(UPlainAttr.class)) {
+            result = (E) new PGUPlainAttr();
+        } else if (reference.equals(UPlainAttrValue.class)) {
+            result = (E) new PGUPlainAttrValue();
+        } else if (reference.equals(UPlainAttrUniqueValue.class)) {
+            result = (E) new PGUPlainAttrUniqueValue();
+        } else {
+            result = super.newEntity(reference);
+        }
+
+        return result;
+    }
+
+    @Override
+    public Class<? extends User> userClass() {
+        return PGJPAUser.class;
+    }
+
+    @Override
+    public Class<? extends Group> groupClass() {
+        return PGJPAGroup.class;
+    }
+
+    @Override
+    public Class<? extends AnyObject> anyObjectClass() {
+        return PGJPAAnyObject.class;
+    }
+
+    @Override
+    public Class<? extends Conf> confClass() {
+        return PGJPAConf.class;
+    }
+
+    @Override
+    public Class<? extends AnySearchDAO> anySearchDAOClass() {
+        return PGJPAAnySearchDAO.class;
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGJPAEntityListener.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGJPAEntityListener.java
new file mode 100644
index 0000000..ddbb13e
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGJPAEntityListener.java
@@ -0,0 +1,49 @@
+/*
+ * 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.core.persistence.jpa.entity;
+
+import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+
+public abstract class PGJPAEntityListener<A extends Any<?>> {
+
+    protected abstract List<? extends PGPlainAttr<A>> getValues(String plainAttrsJSON);
+
+    @SuppressWarnings("unchecked")
+    protected void read(final PGJPAAny<A> entity) {
+        if (entity.getPlainAttrsJSON() != null) {
+            getValues(entity.getPlainAttrsJSON()).stream().filter(attr -> attr.getSchema() != null).
+                    map(attr -> {
+                        attr.setOwner((A) entity);
+                        attr.getValues().forEach(value -> value.setAttr(attr));
+                        if (attr.getUniqueValue() != null) {
+                            attr.getUniqueValue().setAttr(attr);
+                        }
+                        return attr;
+                    }).forEach(attr -> entity.add(attr));
+        }
+    }
+
+    protected void save(final PGJPAAny<A> entity) {
+        entity.setPlainAttrsJSON(entity.getPlainAttrList().isEmpty()
+                ? "[{}]"
+                : POJOHelper.serialize(entity.getPlainAttrList()));
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGPlainAttr.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGPlainAttr.java
new file mode 100644
index 0000000..a802d3c
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/PGPlainAttr.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.entity;
+
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+
+public interface PGPlainAttr<A extends Any<?>> extends PlainAttr<A> {
+
+    String getSchemaKey();
+
+    boolean add(PlainAttrValue value);
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGAPlainAttr.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGAPlainAttr.java
new file mode 100644
index 0000000..292107e
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGAPlainAttr.java
@@ -0,0 +1,196 @@
+/*
+ * 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.core.persistence.jpa.entity.anyobject;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+
+@JsonIgnoreProperties("valuesAsStrings")
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class PGAPlainAttr extends AbstractPlainAttr<AnyObject> implements APlainAttr, PGPlainAttr<AnyObject> {
+
+    private static final long serialVersionUID = 806271775349587902L;
+
+    /**
+     * The owner of this attribute.
+     */
+    @JsonIgnore
+    private PGJPAAnyObject owner;
+
+    @JsonProperty
+    private String schema;
+
+    /**
+     * The membership of this attribute; might be {@code NULL} if this attribute is not related to a membership.
+     */
+    @JsonProperty
+    private String membership;
+
+    /**
+     * Values of this attribute (if schema is not UNIQUE).
+     */
+    private final List<PGAPlainAttrValue> values = new ArrayList<>();
+
+    /**
+     * Value of this attribute (if schema is UNIQUE).
+     */
+    @JsonProperty
+    private PGAPlainAttrUniqueValue uniqueValue;
+
+    @Override
+    public AnyObject getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final AnyObject owner) {
+        checkType(owner, PGJPAAnyObject.class);
+        this.owner = (PGJPAAnyObject) owner;
+    }
+
+    @JsonIgnore
+    @Override
+    public String getSchemaKey() {
+        return schema;
+    }
+
+    @JsonIgnore
+    @Override
+    public JPAPlainSchema getSchema() {
+        return (JPAPlainSchema) ApplicationContextProvider.getBeanFactory().getBean(PlainSchemaDAO.class).find(schema);
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        if (schema != null) {
+            this.schema = schema.getKey();
+        }
+    }
+
+    @JsonSetter("schema")
+    public void setSchema(final String schema) {
+        this.schema = schema;
+    }
+
+    @JsonIgnore
+    public String getMembershipKey() {
+        return membership;
+    }
+
+    @JsonIgnore
+    @Override
+    public AMembership getMembership() {
+        return ApplicationContextProvider.getBeanFactory().getBean(AnyObjectDAO.class).findMembership(membership);
+    }
+
+    @Override
+    public void setMembership(final AMembership membership) {
+        if (membership != null) {
+            this.membership = membership.getKey();
+        }
+    }
+
+    @JsonSetter("membership")
+    public void setMembership(final String membership) {
+        this.membership = membership;
+    }
+
+    @Override
+    protected boolean addForMultiValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, PGAPlainAttrValue.class);
+        return values.add((PGAPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public boolean add(final PlainAttrValue value) {
+        return addForMultiValue(value);
+    }
+
+    @Override
+    public List<? extends APlainAttrValue> getValues() {
+        return values;
+    }
+
+    @JsonIgnore
+    public List<PGAPlainAttrValue> getPGValues() {
+        return values;
+    }
+
+    @Override
+    public PGAPlainAttrUniqueValue getUniqueValue() {
+        return uniqueValue;
+    }
+
+    @JsonIgnore
+    @Override
+    public void setUniqueValue(final PlainAttrUniqueValue uniqueValue) {
+        checkType(uniqueValue, PGAPlainAttrUniqueValue.class);
+        this.uniqueValue = (PGAPlainAttrUniqueValue) uniqueValue;
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().
+                append(schema).
+                append(membership).
+                append(values).
+                append(uniqueValue).
+                build();
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final PGAPlainAttr other = (PGAPlainAttr) obj;
+        return new EqualsBuilder().
+                append(schema, other.schema).
+                append(membership, other.membership).
+                append(values, other.values).
+                append(uniqueValue, other.uniqueValue).
+                build();
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGAPlainAttrUniqueValue.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGAPlainAttrUniqueValue.java
new file mode 100644
index 0000000..dd24599
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGAPlainAttrUniqueValue.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.core.persistence.jpa.entity.anyobject;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@JsonIgnoreProperties({ "valueAsString", "value" })
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PGAPlainAttrUniqueValue extends AbstractPlainAttrValue implements APlainAttrUniqueValue {
+
+    private static final long serialVersionUID = -4053996864791245312L;
+
+    @JsonIgnore
+    private PGAPlainAttr attr;
+
+    @Override
+    public APlainAttr getAttr() {
+        return attr;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr<?> attr) {
+        checkType(attr, PGAPlainAttr.class);
+        this.attr = (PGAPlainAttr) attr;
+    }
+
+    @JsonIgnore
+    @Override
+    public PlainSchema getSchema() {
+        return getAttr() == null ? null : getAttr().getSchema();
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        // nothing to do
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGAPlainAttrValue.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGAPlainAttrValue.java
new file mode 100644
index 0000000..b3b76fd
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGAPlainAttrValue.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.core.persistence.jpa.entity.anyobject;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttrValue;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@JsonIgnoreProperties({ "valueAsString", "value" })
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PGAPlainAttrValue extends AbstractPlainAttrValue implements APlainAttrValue {
+
+    private static final long serialVersionUID = 1832825176101443555L;
+
+    @JsonIgnore
+    private PGAPlainAttr attr;
+
+    @Override
+    public APlainAttr getAttr() {
+        return attr;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr<?> attr) {
+        checkType(attr, PGAPlainAttr.class);
+        this.attr = (PGAPlainAttr) attr;
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGJPAAnyObject.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGJPAAnyObject.java
new file mode 100644
index 0000000..dad8536
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGJPAAnyObject.java
@@ -0,0 +1,97 @@
+/*
+ * 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.core.persistence.jpa.entity.anyobject;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.Lob;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
+import org.apache.syncope.core.persistence.api.entity.anyobject.APlainAttr;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.PGJPAAny;
+import org.apache.syncope.core.persistence.jpa.validation.entity.PGJPAAnyCheck;
+
+@Entity
+@Table(name = JPAAnyObject.TABLE)
+@EntityListeners({ PGJPAAnyObjectListener.class })
+@PGJPAAnyCheck
+public class PGJPAAnyObject extends JPAAnyObject implements PGJPAAny<AnyObject>, AnyObject {
+
+    private static final long serialVersionUID = -8543654943709531885L;
+
+    @Lob
+    @Column(columnDefinition = "jsonb")
+    private String plainAttrs;
+
+    @Transient
+    private final List<PGAPlainAttr> plainAttrList = new ArrayList<>();
+
+    @Override
+    public String getPlainAttrsJSON() {
+        return plainAttrs;
+    }
+
+    @Override
+    public void setPlainAttrsJSON(final String plainAttrs) {
+        this.plainAttrs = plainAttrs;
+    }
+
+    @Override
+    public List<PGAPlainAttr> getPlainAttrList() {
+        return plainAttrList;
+    }
+
+    @Override
+    public boolean add(final PGPlainAttr<AnyObject> attr) {
+        return add((APlainAttr) attr);
+    }
+
+    @Override
+    public boolean add(final APlainAttr attr) {
+        checkType(attr, PGAPlainAttr.class);
+        return plainAttrList.add((PGAPlainAttr) attr);
+    }
+
+    @Override
+    public boolean remove(final APlainAttr attr) {
+        return plainAttrList.removeIf(pgattr
+                -> pgattr.getSchemaKey().equals(attr.getSchema().getKey())
+                && attr.getOwner().getKey().equals(getKey())
+                && attr.getMembership() == null
+                ? true
+                : pgattr.getMembership() != null && pgattr.getMembershipKey().equals(attr.getMembership().getKey()));
+    }
+
+    @Override
+    protected List<? extends APlainAttr> internalGetPlainAttrs() {
+        return plainAttrList;
+    }
+
+    @Override
+    public boolean remove(final AMembership membership) {
+        plainAttrList.removeIf(attr -> attr.getMembership().getKey().equals(membership.getKey()));
+        return super.remove(membership);
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGJPAAnyObjectListener.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGJPAAnyObjectListener.java
new file mode 100644
index 0000000..61b201f
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/PGJPAAnyObjectListener.java
@@ -0,0 +1,49 @@
+/*
+ * 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.core.persistence.jpa.entity.anyobject;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import java.util.List;
+import javax.persistence.PostLoad;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.jpa.entity.PGJPAEntityListener;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+
+public class PGJPAAnyObjectListener extends PGJPAEntityListener<AnyObject> {
+
+    @Override
+    protected List<? extends PGPlainAttr<AnyObject>> getValues(final String plainAttrsJSON) {
+        return POJOHelper.deserialize(plainAttrsJSON, new TypeReference<List<PGAPlainAttr>>() {
+        });
+    }
+
+    @PostLoad
+    public void read(final PGJPAAnyObject anyObject) {
+        super.read(anyObject);
+    }
+
+    @PrePersist
+    @PreUpdate
+    public void save(final PGJPAAnyObject anyObject) {
+        super.save(anyObject);
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGCPlainAttr.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGCPlainAttr.java
new file mode 100644
index 0000000..a45d7d5
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGCPlainAttr.java
@@ -0,0 +1,163 @@
+/*
+ * 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.core.persistence.jpa.entity.conf;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.conf.Conf;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+
+@JsonIgnoreProperties("valuesAsStrings")
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class PGCPlainAttr extends AbstractPlainAttr<Conf> implements CPlainAttr, PGPlainAttr<Conf> {
+
+    private static final long serialVersionUID = 806271775349587902L;
+
+    /**
+     * The owner of this attribute.
+     */
+    @JsonIgnore
+    private PGJPAConf owner;
+
+    @JsonProperty
+    private String schema;
+
+    /**
+     * Values of this attribute (if schema is not UNIQUE).
+     */
+    private final List<PGCPlainAttrValue> values = new ArrayList<>();
+
+    /**
+     * Value of this attribute (if schema is UNIQUE).
+     */
+    @JsonProperty
+    private PGCPlainAttrUniqueValue uniqueValue;
+
+    @Override
+    public Conf getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Conf owner) {
+        checkType(owner, PGJPAConf.class);
+        this.owner = (PGJPAConf) owner;
+    }
+
+    @JsonIgnore
+    @Override
+    public String getSchemaKey() {
+        return schema;
+    }
+
+    @JsonIgnore
+    @Override
+    public JPAPlainSchema getSchema() {
+        return (JPAPlainSchema) ApplicationContextProvider.getBeanFactory().getBean(PlainSchemaDAO.class).find(schema);
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        if (schema != null) {
+            this.schema = schema.getKey();
+        }
+    }
+
+    @JsonSetter("schema")
+    public void setSchema(final String schema) {
+        this.schema = schema;
+    }
+
+    @Override
+    protected boolean addForMultiValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, PGCPlainAttrValue.class);
+        return values.add((PGCPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public boolean add(final PlainAttrValue value) {
+        return addForMultiValue(value);
+    }
+
+    @Override
+    public List<? extends CPlainAttrValue> getValues() {
+        return values;
+    }
+
+    @JsonIgnore
+    public List<PGCPlainAttrValue> getPGValues() {
+        return values;
+    }
+
+    @Override
+    public PGCPlainAttrUniqueValue getUniqueValue() {
+        return uniqueValue;
+    }
+
+    @JsonIgnore
+    @Override
+    public void setUniqueValue(final PlainAttrUniqueValue uniqueValue) {
+        checkType(uniqueValue, PGCPlainAttrUniqueValue.class);
+        this.uniqueValue = (PGCPlainAttrUniqueValue) uniqueValue;
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().
+                append(schema).
+                append(values).
+                append(uniqueValue).
+                build();
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final PGCPlainAttr other = (PGCPlainAttr) obj;
+        return new EqualsBuilder().
+                append(schema, other.schema).
+                append(values, other.values).
+                append(uniqueValue, other.uniqueValue).
+                build();
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGCPlainAttrUniqueValue.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGCPlainAttrUniqueValue.java
new file mode 100644
index 0000000..5877f1c
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGCPlainAttrUniqueValue.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.core.persistence.jpa.entity.conf;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@JsonIgnoreProperties({ "valueAsString", "value" })
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PGCPlainAttrUniqueValue extends AbstractPlainAttrValue implements CPlainAttrUniqueValue {
+
+    private static final long serialVersionUID = -4326417972859745823L;
+
+    @JsonIgnore
+    private PGCPlainAttr attr;
+
+    @Override
+    public CPlainAttr getAttr() {
+        return attr;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr<?> attr) {
+        checkType(attr, PGCPlainAttr.class);
+        this.attr = (PGCPlainAttr) attr;
+    }
+
+    @JsonIgnore
+    @Override
+    public PlainSchema getSchema() {
+        return getAttr() == null ? null : getAttr().getSchema();
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        // nothing to do
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGCPlainAttrValue.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGCPlainAttrValue.java
new file mode 100644
index 0000000..a537f0f
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGCPlainAttrValue.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.core.persistence.jpa.entity.conf;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttrValue;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@JsonIgnoreProperties({ "valueAsString", "value" })
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PGCPlainAttrValue extends AbstractPlainAttrValue implements CPlainAttrValue {
+
+    private static final long serialVersionUID = 1832825176101443555L;
+
+    @JsonIgnore
+    private PGCPlainAttr attr;
+
+    @Override
+    public CPlainAttr getAttr() {
+        return attr;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr<?> attr) {
+        checkType(attr, PGCPlainAttr.class);
+        this.attr = (PGCPlainAttr) attr;
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGJPAConf.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGJPAConf.java
new file mode 100644
index 0000000..a297d18
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGJPAConf.java
@@ -0,0 +1,85 @@
+/*
+ * 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.core.persistence.jpa.entity.conf;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.Lob;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.conf.Conf;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.PGJPAAny;
+import org.apache.syncope.core.persistence.jpa.validation.entity.PGJPAAnyCheck;
+
+@Entity
+@Table(name = JPAConf.TABLE)
+@EntityListeners({ PGJPAConfListener.class })
+@PGJPAAnyCheck
+public class PGJPAConf extends JPAConf implements PGJPAAny<Conf>, Conf {
+
+    private static final long serialVersionUID = -8543654943709531885L;
+
+    @Lob
+    @Column(columnDefinition = "jsonb")
+    private String plainAttrs;
+
+    @Transient
+    private final List<PGCPlainAttr> plainAttrList = new ArrayList<>();
+
+    @Override
+    public String getPlainAttrsJSON() {
+        return plainAttrs;
+    }
+
+    @Override
+    public void setPlainAttrsJSON(final String plainAttrs) {
+        this.plainAttrs = plainAttrs;
+    }
+
+    @Override
+    public List<PGCPlainAttr> getPlainAttrList() {
+        return plainAttrList;
+    }
+
+    @Override
+    public boolean add(final PGPlainAttr<Conf> attr) {
+        return add((CPlainAttr) attr);
+    }
+
+    @Override
+    public boolean add(final CPlainAttr attr) {
+        checkType(attr, PGCPlainAttr.class);
+        return plainAttrList.add((PGCPlainAttr) attr);
+    }
+
+    @Override
+    public boolean remove(final CPlainAttr attr) {
+        return plainAttrList.removeIf(pgattr -> pgattr.getSchemaKey().equals(attr.getSchema().getKey()));
+    }
+
+    @Override
+    public List<? extends CPlainAttr> getPlainAttrs() {
+        return plainAttrList;
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGJPAConfListener.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGJPAConfListener.java
new file mode 100644
index 0000000..f1a7198
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/PGJPAConfListener.java
@@ -0,0 +1,49 @@
+/*
+ * 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.core.persistence.jpa.entity.conf;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import java.util.List;
+import javax.persistence.PostLoad;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import org.apache.syncope.core.persistence.api.entity.conf.Conf;
+import org.apache.syncope.core.persistence.jpa.entity.PGJPAEntityListener;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+
+public class PGJPAConfListener extends PGJPAEntityListener<Conf> {
+
+    @Override
+    protected List<? extends PGPlainAttr<Conf>> getValues(final String plainAttrsJSON) {
+        return POJOHelper.deserialize(plainAttrsJSON, new TypeReference<List<PGCPlainAttr>>() {
+        });
+    }
+
+    @PostLoad
+    public void read(final PGJPAConf conf) {
+        super.read(conf);
+    }
+
+    @PrePersist
+    @PreUpdate
+    public void save(final PGJPAConf conf) {
+        super.save(conf);
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGGPlainAttr.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGGPlainAttr.java
new file mode 100644
index 0000000..9e78535
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGGPlainAttr.java
@@ -0,0 +1,163 @@
+/*
+ * 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.core.persistence.jpa.entity.group;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+
+@JsonIgnoreProperties("valuesAsStrings")
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class PGGPlainAttr extends AbstractPlainAttr<Group> implements GPlainAttr, PGPlainAttr<Group> {
+
+    private static final long serialVersionUID = 806271775349587902L;
+
+    /**
+     * The owner of this attribute.
+     */
+    @JsonIgnore
+    private PGJPAGroup owner;
+
+    @JsonProperty
+    private String schema;
+
+    /**
+     * Values of this attribute (if schema is not UNIQUE).
+     */
+    private final List<PGGPlainAttrValue> values = new ArrayList<>();
+
+    /**
+     * Value of this attribute (if schema is UNIQUE).
+     */
+    @JsonProperty
+    private PGGPlainAttrUniqueValue uniqueValue;
+
+    @Override
+    public Group getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final Group owner) {
+        checkType(owner, PGJPAGroup.class);
+        this.owner = (PGJPAGroup) owner;
+    }
+
+    @JsonIgnore
+    @Override
+    public String getSchemaKey() {
+        return schema;
+    }
+
+    @JsonIgnore
+    @Override
+    public JPAPlainSchema getSchema() {
+        return (JPAPlainSchema) ApplicationContextProvider.getBeanFactory().getBean(PlainSchemaDAO.class).find(schema);
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        if (schema != null) {
+            this.schema = schema.getKey();
+        }
+    }
+
+    @JsonSetter("schema")
+    public void setSchema(final String schema) {
+        this.schema = schema;
+    }
+
+    @Override
+    protected boolean addForMultiValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, PGGPlainAttrValue.class);
+        return values.add((PGGPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public boolean add(final PlainAttrValue value) {
+        return addForMultiValue(value);
+    }
+
+    @Override
+    public List<? extends GPlainAttrValue> getValues() {
+        return values;
+    }
+
+    @JsonIgnore
+    public List<PGGPlainAttrValue> getPGValues() {
+        return values;
+    }
+
+    @Override
+    public PGGPlainAttrUniqueValue getUniqueValue() {
+        return uniqueValue;
+    }
+
+    @JsonIgnore
+    @Override
+    public void setUniqueValue(final PlainAttrUniqueValue uniqueValue) {
+        checkType(uniqueValue, PGGPlainAttrUniqueValue.class);
+        this.uniqueValue = (PGGPlainAttrUniqueValue) uniqueValue;
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().
+                append(schema).
+                append(values).
+                append(uniqueValue).
+                build();
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final PGGPlainAttr other = (PGGPlainAttr) obj;
+        return new EqualsBuilder().
+                append(schema, other.schema).
+                append(values, other.values).
+                append(uniqueValue, other.uniqueValue).
+                build();
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGGPlainAttrUniqueValue.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGGPlainAttrUniqueValue.java
new file mode 100644
index 0000000..c6219a0
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGGPlainAttrUniqueValue.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.core.persistence.jpa.entity.group;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@JsonIgnoreProperties({ "valueAsString", "value" })
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PGGPlainAttrUniqueValue extends AbstractPlainAttrValue implements GPlainAttrUniqueValue {
+
+    private static final long serialVersionUID = -4326417972859745823L;
+
+    @JsonIgnore
+    private PGGPlainAttr attr;
+
+    @Override
+    public GPlainAttr getAttr() {
+        return attr;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr<?> attr) {
+        checkType(attr, PGGPlainAttr.class);
+        this.attr = (PGGPlainAttr) attr;
+    }
+
+    @JsonIgnore
+    @Override
+    public PlainSchema getSchema() {
+        return getAttr() == null ? null : getAttr().getSchema();
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        // nothing to do
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGGPlainAttrValue.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGGPlainAttrValue.java
new file mode 100644
index 0000000..398e5b0
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGGPlainAttrValue.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.core.persistence.jpa.entity.group;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.group.GPlainAttrValue;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@JsonIgnoreProperties({ "valueAsString", "value" })
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PGGPlainAttrValue extends AbstractPlainAttrValue implements GPlainAttrValue {
+
+    private static final long serialVersionUID = 1832825176101443555L;
+
+    @JsonIgnore
+    private PGGPlainAttr attr;
+
+    @Override
+    public GPlainAttr getAttr() {
+        return attr;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr<?> attr) {
+        checkType(attr, PGGPlainAttr.class);
+        this.attr = (PGGPlainAttr) attr;
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGJPAGroup.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGJPAGroup.java
new file mode 100644
index 0000000..6207dfc
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGJPAGroup.java
@@ -0,0 +1,87 @@
+/*
+ * 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.core.persistence.jpa.entity.group;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.Lob;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import org.apache.syncope.core.persistence.api.entity.group.GPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.PGJPAAny;
+import org.apache.syncope.core.persistence.jpa.validation.entity.PGJPAAnyCheck;
+
+@Entity
+@Table(name = JPAGroup.TABLE)
+@EntityListeners({ PGJPAGroupListener.class })
+@PGJPAAnyCheck
+public class PGJPAGroup extends JPAGroup implements PGJPAAny<Group>, Group {
+
+    private static final long serialVersionUID = -8543654943709531885L;
+
+    @Lob
+    @Column(columnDefinition = "jsonb")
+    private String plainAttrs;
+
+    @Transient
+    private final List<PGGPlainAttr> plainAttrList = new ArrayList<>();
+
+    @Override
+    public String getPlainAttrsJSON() {
+        return plainAttrs;
+    }
+
+    @Override
+    public void setPlainAttrsJSON(final String plainAttrs) {
+        this.plainAttrs = plainAttrs;
+    }
+
+    @Override
+    public List<PGGPlainAttr> getPlainAttrList() {
+        return plainAttrList;
+    }
+
+    @Override
+    public boolean add(final PGPlainAttr<Group> attr) {
+        return add((GPlainAttr) attr);
+    }
+
+    @Override
+    public boolean add(final GPlainAttr attr) {
+        checkType(attr, PGGPlainAttr.class);
+        return plainAttrList.add((PGGPlainAttr) attr);
+    }
+
+    @Override
+    public boolean remove(final GPlainAttr attr) {
+        return plainAttrList.removeIf(pgattr
+                -> pgattr.getSchemaKey().equals(attr.getSchema().getKey())
+                && attr.getOwner().getKey().equals(getKey()));
+    }
+
+    @Override
+    public List<? extends GPlainAttr> getPlainAttrs() {
+        return plainAttrList;
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGJPAGroupListener.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGJPAGroupListener.java
new file mode 100644
index 0000000..b32f471
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/PGJPAGroupListener.java
@@ -0,0 +1,49 @@
+/*
+ * 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.core.persistence.jpa.entity.group;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import java.util.List;
+import javax.persistence.PostLoad;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.jpa.entity.PGJPAEntityListener;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+
+public class PGJPAGroupListener extends PGJPAEntityListener<Group> {
+
+    @Override
+    protected List<? extends PGPlainAttr<Group>> getValues(final String plainAttrsJSON) {
+        return POJOHelper.deserialize(plainAttrsJSON, new TypeReference<List<PGGPlainAttr>>() {
+        });
+    }
+
+    @PostLoad
+    public void read(final PGJPAGroup group) {
+        super.read(group);
+    }
+
+    @PrePersist
+    @PreUpdate
+    public void save(final PGJPAGroup group) {
+        super.save(group);
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGJPAUser.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGJPAUser.java
new file mode 100644
index 0000000..486ba1c
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGJPAUser.java
@@ -0,0 +1,90 @@
+/*
+ * 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.core.persistence.jpa.entity.user;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.Lob;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.PGJPAAny;
+import org.apache.syncope.core.persistence.jpa.validation.entity.PGJPAAnyCheck;
+
+@Entity
+@Table(name = JPAUser.TABLE)
+@EntityListeners({ PGJPAUserListener.class })
+@PGJPAAnyCheck
+public class PGJPAUser extends JPAUser implements PGJPAAny<User>, User {
+
+    private static final long serialVersionUID = -8543654943709531885L;
+
+    @Lob
+    @Column(columnDefinition = "jsonb")
+    private String plainAttrs;
+
+    @Transient
+    private final List<PGUPlainAttr> plainAttrList = new ArrayList<>();
+
+    @Override
+    public String getPlainAttrsJSON() {
+        return plainAttrs;
+    }
+
+    @Override
+    public void setPlainAttrsJSON(final String plainAttrs) {
+        this.plainAttrs = plainAttrs;
+    }
+
+    @Override
+    public List<PGUPlainAttr> getPlainAttrList() {
+        return plainAttrList;
+    }
+
+    @Override
+    public boolean add(final PGPlainAttr<User> attr) {
+        return add((UPlainAttr) attr);
+    }
+
+    @Override
+    public boolean add(final UPlainAttr attr) {
+        checkType(attr, PGUPlainAttr.class);
+        return plainAttrList.add((PGUPlainAttr) attr);
+    }
+
+    @Override
+    public boolean remove(final UPlainAttr attr) {
+        return plainAttrList.removeIf(pgattr
+                -> pgattr.getSchemaKey().equals(attr.getSchema().getKey())
+                && attr.getOwner().getKey().equals(getKey())
+                && attr.getMembership() == null
+                ? true
+                : pgattr.getMembership() != null && pgattr.getMembershipKey().equals(attr.getMembership().getKey()));
+    }
+
+    @Override
+    protected List<? extends UPlainAttr> internalGetPlainAttrs() {
+        return plainAttrList;
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGJPAUserListener.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGJPAUserListener.java
new file mode 100644
index 0000000..5baf4fc
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGJPAUserListener.java
@@ -0,0 +1,49 @@
+/*
+ * 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.core.persistence.jpa.entity.user;
+
+import com.fasterxml.jackson.core.type.TypeReference;
+import java.util.List;
+import javax.persistence.PostLoad;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.persistence.jpa.entity.PGJPAEntityListener;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+
+public class PGJPAUserListener extends PGJPAEntityListener<User> {
+
+    @Override
+    protected List<? extends PGPlainAttr<User>> getValues(final String plainAttrsJSON) {
+        return POJOHelper.deserialize(plainAttrsJSON, new TypeReference<List<PGUPlainAttr>>() {
+        });
+    }
+
+    @PostLoad
+    public void read(final PGJPAUser user) {
+        super.read(user);
+    }
+
+    @PrePersist
+    @PreUpdate
+    public void save(final PGJPAUser user) {
+        super.save(user);
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGUPlainAttr.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGUPlainAttr.java
new file mode 100644
index 0000000..09abb26
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGUPlainAttr.java
@@ -0,0 +1,196 @@
+/*
+ * 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.core.persistence.jpa.entity.user;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonSetter;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.user.UMembership;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
+import org.apache.syncope.core.persistence.jpa.entity.PGPlainAttr;
+import org.apache.syncope.core.spring.ApplicationContextProvider;
+
+@JsonIgnoreProperties("valuesAsStrings")
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class PGUPlainAttr extends AbstractPlainAttr<User> implements UPlainAttr, PGPlainAttr<User> {
+
+    private static final long serialVersionUID = 806271775349587902L;
+
+    /**
+     * The owner of this attribute.
+     */
+    @JsonIgnore
+    private PGJPAUser owner;
+
+    @JsonProperty
+    private String schema;
+
+    /**
+     * The membership of this attribute; might be {@code NULL} if this attribute is not related to a membership.
+     */
+    @JsonProperty
+    private String membership;
+
+    /**
+     * Values of this attribute (if schema is not UNIQUE).
+     */
+    private final List<PGUPlainAttrValue> values = new ArrayList<>();
+
+    /**
+     * Value of this attribute (if schema is UNIQUE).
+     */
+    @JsonProperty
+    private PGUPlainAttrUniqueValue uniqueValue;
+
+    @Override
+    public User getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final User owner) {
+        checkType(owner, PGJPAUser.class);
+        this.owner = (PGJPAUser) owner;
+    }
+
+    @JsonIgnore
+    @Override
+    public String getSchemaKey() {
+        return schema;
+    }
+
+    @JsonIgnore
+    @Override
+    public JPAPlainSchema getSchema() {
+        return (JPAPlainSchema) ApplicationContextProvider.getBeanFactory().getBean(PlainSchemaDAO.class).find(schema);
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        if (schema != null) {
+            this.schema = schema.getKey();
+        }
+    }
+
+    @JsonSetter("schema")
+    public void setSchema(final String schema) {
+        this.schema = schema;
+    }
+
+    @JsonIgnore
+    public String getMembershipKey() {
+        return membership;
+    }
+
+    @JsonIgnore
+    @Override
+    public UMembership getMembership() {
+        return ApplicationContextProvider.getBeanFactory().getBean(UserDAO.class).findMembership(membership);
+    }
+
+    @Override
+    public void setMembership(final UMembership membership) {
+        if (membership != null) {
+            this.membership = membership.getKey();
+        }
+    }
+
+    @JsonSetter("membership")
+    public void setMembership(final String membership) {
+        this.membership = membership;
+    }
+
+    @Override
+    protected boolean addForMultiValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, PGUPlainAttrValue.class);
+        return values.add((PGUPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public boolean add(final PlainAttrValue value) {
+        return addForMultiValue(value);
+    }
+
+    @Override
+    public List<? extends UPlainAttrValue> getValues() {
+        return values;
+    }
+
+    @JsonIgnore
+    public List<PGUPlainAttrValue> getPGValues() {
+        return values;
+    }
+
+    @Override
+    public PGUPlainAttrUniqueValue getUniqueValue() {
+        return uniqueValue;
+    }
+
+    @JsonIgnore
+    @Override
+    public void setUniqueValue(final PlainAttrUniqueValue uniqueValue) {
+        checkType(uniqueValue, PGUPlainAttrUniqueValue.class);
+        this.uniqueValue = (PGUPlainAttrUniqueValue) uniqueValue;
+    }
+
+    @Override
+    public int hashCode() {
+        return new HashCodeBuilder().
+                append(schema).
+                append(membership).
+                append(values).
+                append(uniqueValue).
+                build();
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final PGUPlainAttr other = (PGUPlainAttr) obj;
+        return new EqualsBuilder().
+                append(schema, other.schema).
+                append(membership, other.membership).
+                append(values, other.values).
+                append(uniqueValue, other.uniqueValue).
+                build();
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGUPlainAttrUniqueValue.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGUPlainAttrUniqueValue.java
new file mode 100644
index 0000000..9b6cd3e
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGUPlainAttrUniqueValue.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.core.persistence.jpa.entity.user;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrUniqueValue;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@JsonIgnoreProperties({ "valueAsString", "value" })
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PGUPlainAttrUniqueValue extends AbstractPlainAttrValue implements UPlainAttrUniqueValue {
+
+    private static final long serialVersionUID = -4053996864791245312L;
+
+    @JsonIgnore
+    private PGUPlainAttr attr;
+
+    @Override
+    public UPlainAttr getAttr() {
+        return attr;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr<?> attr) {
+        checkType(attr, PGUPlainAttr.class);
+        this.attr = (PGUPlainAttr) attr;
+    }
+
+    @JsonIgnore
+    @Override
+    public PlainSchema getSchema() {
+        return getAttr() == null ? null : getAttr().getSchema();
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        // nothing to do
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGUPlainAttrValue.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGUPlainAttrValue.java
new file mode 100644
index 0000000..6ba15d5
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/PGUPlainAttrValue.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.core.persistence.jpa.entity.user;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
+import org.apache.syncope.core.persistence.api.entity.user.UPlainAttrValue;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
+
+@JsonIgnoreProperties({ "valueAsString", "value" })
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PGUPlainAttrValue extends AbstractPlainAttrValue implements UPlainAttrValue {
+
+    private static final long serialVersionUID = 1832825176101443555L;
+
+    @JsonIgnore
+    private PGUPlainAttr attr;
+
+    @Override
+    public UPlainAttr getAttr() {
+        return attr;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr<?> attr) {
+        checkType(attr, PGUPlainAttr.class);
+        this.attr = (PGUPlainAttr) attr;
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PGJPAAnyCheck.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PGJPAAnyCheck.java
new file mode 100644
index 0000000..ef6f87d
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PGJPAAnyCheck.java
@@ -0,0 +1,41 @@
+/*
+ * 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.core.persistence.jpa.validation.entity;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+
+@Target({ ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Constraint(validatedBy = PGJPAAnyValidator.class)
+@Documented
+public @interface PGJPAAnyCheck {
+
+    String message() default "{org.apache.syncope.core.persistence.validation.any}";
+
+    Class<?>[] groups() default {};
+
+    Class<? extends Payload>[] payload() default {};
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PGJPAAnyValidator.java b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PGJPAAnyValidator.java
new file mode 100644
index 0000000..089808c
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/java/org/apache/syncope/core/persistence/jpa/validation/entity/PGJPAAnyValidator.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.core.persistence.jpa.validation.entity;
+
+import java.util.concurrent.atomic.AtomicReference;
+import javax.validation.ConstraintValidatorContext;
+import org.apache.syncope.core.persistence.api.entity.PlainAttr;
+import org.apache.syncope.core.persistence.jpa.entity.PGJPAAny;
+
+public class PGJPAAnyValidator extends AbstractValidator<PGJPAAnyCheck, PGJPAAny<?>> {
+
+    @Override
+    public boolean isValid(final PGJPAAny<?> entity, final ConstraintValidatorContext context) {
+        context.disableDefaultConstraintViolation();
+
+        PlainAttrValidator attrValidator = new PlainAttrValidator();
+        PlainAttrValueValidator attrValueValidator = new PlainAttrValueValidator();
+
+        AtomicReference<Boolean> isValid = new AtomicReference<>(Boolean.TRUE);
+        entity.getPlainAttrList().forEach(attr -> {
+            PlainAttr<?> plainAttr = (PlainAttr<?>) attr;
+            isValid.getAndSet(isValid.get() && attrValidator.isValid(plainAttr, context));
+            plainAttr.getValues().forEach(value
+                    -> isValid.getAndSet(isValid.get() && attrValueValidator.isValid(value, context)));
+        });
+
+        return isValid.get();
+    }
+}
diff --git a/core/persistence-jpa-pgjsonb/src/main/resources/META-INF/spring-orm-pgjsonb.xml b/core/persistence-jpa-pgjsonb/src/main/resources/META-INF/spring-orm-pgjsonb.xml
new file mode 100644
index 0000000..3e5b103
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/resources/META-INF/spring-orm-pgjsonb.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
+                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                 xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm 
+                                     http://java.sun.com/xml/ns/persistence/orm_2_0.xsd"
+                 version="2.0">
+  
+  <persistence-unit-metadata>
+    <persistence-unit-defaults>
+      <entity-listeners>
+        <entity-listener class="org.apache.syncope.core.persistence.jpa.validation.entity.EntityValidationListener">
+          <pre-persist method-name="validate"/>
+          <pre-update method-name="validate"/>
+        </entity-listener>
+      </entity-listeners>
+    </persistence-unit-defaults>
+  </persistence-unit-metadata>
+  
+</entity-mappings>
diff --git a/core/persistence-jpa-pgjsonb/src/main/resources/domains/Master.properties b/core/persistence-jpa-pgjsonb/src/main/resources/domains/Master.properties
new file mode 100644
index 0000000..d9a648f
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/resources/domains/Master.properties
@@ -0,0 +1,28 @@
+# 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.
+Master.driverClassName=org.postgresql.Driver
+Master.url=jdbc:postgresql://localhost:5432/syncope?stringtype=unspecified
+Master.schema=
+Master.username=syncope
+Master.password=syncope
+Master.databasePlatform=org.apache.openjpa.jdbc.sql.PostgresDictionary
+Master.orm=META-INF/spring-orm-pgjsonb.xml
+
+Master.pool.maxActive=10
+Master.pool.minIdle=2
+
+Master.audit.sql=audit.sql
diff --git a/core/persistence-jpa-pgjsonb/src/main/resources/indexes.xml b/core/persistence-jpa-pgjsonb/src/main/resources/indexes.xml
new file mode 100644
index 0000000..3e5b92b
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/resources/indexes.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+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.
+-->
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+  <comment>Additional indexes (in respect to JPA's)</comment>
+
+  <entry key="SyncopeUser_plainAttrs_idx">CREATE INDEX SyncopeUser_plainAttrs_idx ON SyncopeUser USING gin ((plainAttrs) jsonb_path_ops)</entry>
+  <entry key="SyncopeGroup_plainAttrs_idx">CREATE INDEX SyncopeGroup_plainAttrs_idx ON SyncopeGroup USING gin ((plainAttrs) jsonb_path_ops)</entry>
+  <entry key="AnyObject_plainAttrs_idx">CREATE INDEX AnyObject_plainAttrs_idx ON AnyObject USING gin ((plainAttrs) jsonb_path_ops)</entry>
+  <entry key="SyncopeConf_plainAttrs_idx">CREATE INDEX SyncopeConf_plainAttrs_idx ON SyncopeConf USING gin ((plainAttrs) jsonb_path_ops)</entry>
+
+  <entry key="UDynGroupMembers_any_id">CREATE INDEX UDynGroupMembers_any_id ON UDynGroupMembers(any_id)</entry>
+  <entry key="UDynGroupMembers_group_id">CREATE INDEX UDynGroupMembers_group_id ON UDynGroupMembers(group_id)</entry>
+  <entry key="ADynGroupMembers_any_id">CREATE INDEX ADynGroupMembers_any_id ON ADynGroupMembers(any_id)</entry>
+  <entry key="ADynGroupMembers_group_id">CREATE INDEX ADynGroupMembers_group_id ON ADynGroupMembers(group_id)</entry>
+
+  <entry key="DynRoleMembers_any_id">CREATE INDEX DynRoleMembers_any_id ON DynRoleMembers(any_id)</entry>
+  <entry key="DynRoleMembers_role_id">CREATE INDEX DynRoleMembers_role_id ON DynRoleMembers(role_id)</entry>
+
+  <entry key="DynRealmMembers_any_id">CREATE INDEX DynRealmMembers_any_id ON DynRealmMembers(any_id)</entry>
+  <entry key="DynRealmMembers_realm_id">CREATE INDEX DynRealmMembers_dynRealm_id ON DynRealmMembers(dynRealm_id)</entry>
+
+  <entry key="CPlainAttrValue_stringvalueIndex">CREATE INDEX CAttrValue_stringvalueIndex ON CPlainAttrValue(stringvalue)</entry>
+  <entry key="CPlainAttrValue_datevalueIndex">CREATE INDEX CAttrValue_datevalueIndex ON CPlainAttrValue(datevalue)</entry>
+  <entry key="CPlainAttrValue_longvalueIndex">CREATE INDEX CAttrValue_longvalueIndex ON CPlainAttrValue(longvalue)</entry>
+  <entry key="CPlainAttrValue_doublevalueIndex">CREATE INDEX CAttrValue_doublevalueIndex ON CPlainAttrValue(doublevalue)</entry>
+  <entry key="CPlainAttrValue_booleanvalueIndex">CREATE INDEX CAttrValue_booleanvalueIndex ON CPlainAttrValue(booleanvalue)</entry>
+
+  <entry key="UMembership_GroupIndex">CREATE INDEX UMembership_GroupIndex ON UMembership(group_id)</entry>
+  <entry key="UMembership_UserIndex">CREATE INDEX UMembership_UserIndex ON UMembership(user_id)</entry>
+  <entry key="AMembership_GroupIndex">CREATE INDEX AMembership_GroupIndex ON AMembership(group_id)</entry>
+  <entry key="AMembership_AnyObjectIndex">CREATE INDEX AMembership_AnyObjectIndex ON AMembership(anyObject_id)</entry>
+
+  <entry key="URelationship_RightIndex">CREATE INDEX URelationship_RightIndex ON URelationship(anyObject_id)</entry>
+  <entry key="URelationship_LeftIndex">CREATE INDEX URelationship_LeftIndex ON URelationship(user_id)</entry>
+  <entry key="ARelationship_RightIndex">CREATE INDEX ARelationship_RightIndex ON ARelationship(right_anyObject_id)</entry>
+  <entry key="ARelationship_AnyObjectIndex">CREATE INDEX ARelationship_AnyObjectIndex ON ARelationship(left_anyObject_id)</entry>
+
+  <entry key="CPlainAttrValue_attrIndex">CREATE INDEX CPlainAttrValue_attrIndex on CPlainAttrValue(attribute_id)</entry>
+  <entry key="CPAttrUniqueValue_attrIndex">CREATE INDEX CPAttrUniqueValue_attrIndex on CPlainAttrUniqueValue(attribute_id)</entry>
+
+  <entry key="CPlainAttr_owner_Index">CREATE INDEX CPlainAttr_owner_Index on CPlainAttr(owner_id)</entry>
+  <entry key="CPlainAttr_schema_Index">CREATE INDEX CPlainAttr_schema_Index on CPlainAttr(schema_id)</entry>
+
+  <entry key="Task_executedIndex">CREATE INDEX Task_executedIndex ON Task(executed)</entry>
+</properties>
diff --git a/core/persistence-jpa-pgjsonb/src/main/resources/persistence.properties b/core/persistence-jpa-pgjsonb/src/main/resources/persistence.properties
new file mode 100644
index 0000000..c3196eb
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/resources/persistence.properties
@@ -0,0 +1,26 @@
+# 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.
+content.directory=${conf.directory}
+entity.factory=org.apache.syncope.core.persistence.jpa.entity.PGJPAEntityFactory
+plainSchema.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAPlainSchemaDAO
+plainAttr.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAPlainAttrDAO
+plainAttrValue.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAPlainAttrValueDAO
+any.search.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAAnySearchDAO
+user.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAUserDAO
+group.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAGroupDAO
+anyObject.dao=org.apache.syncope.core.persistence.jpa.dao.PGJPAAnyObjectDAO
+openjpa.RemoteCommitProvider=sjvm
diff --git a/core/persistence-jpa-pgjsonb/src/main/resources/views.xml b/core/persistence-jpa-pgjsonb/src/main/resources/views.xml
new file mode 100644
index 0000000..eb450be
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/main/resources/views.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+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.
+-->
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+<properties>
+  
+  <entry key="UDynGroupMembers">
+    CREATE TABLE UDynGroupMembers(
+    any_id CHAR(36),
+    group_id CHAR(36),
+    UNIQUE(any_id, group_id))
+  </entry>
+  <entry key="ADynGroupMembers">
+    CREATE TABLE ADynGroupMembers(
+    anyType_id VARCHAR(255),
+    any_id CHAR(36),
+    group_id CHAR(36),
+    UNIQUE(anyType_id, any_id, group_id))
+  </entry>
+  <entry key="DynRoleMembers">
+    CREATE TABLE DynRoleMembers(
+    any_id CHAR(36),
+    role_id VARCHAR(255),
+    UNIQUE(any_id, role_id))
+  </entry>
+  <entry key="DynRealmMembers">
+    CREATE TABLE DynRealmMembers(
+    any_id CHAR(36),
+    dynRealm_id VARCHAR(255),
+    UNIQUE(any_id, dynRealm_id))
+  </entry>
+
+  <!-- user -->
+  <entry key="user_search">
+    CREATE VIEW user_search AS
+
+    SELECT u.id as any_id, u.*,attrs,attrValues
+    FROM SyncopeUser u, jsonb_array_elements(COALESCE(u.plainAttrs, '[{}]'::jsonb)) attrs,
+    jsonb_array_elements(COALESCE(attrs -> 'values', '[{}]'::jsonb)) attrValues
+  </entry>
+  <entry key="user_search_urelationship">
+    CREATE VIEW user_search_urelationship AS
+
+    SELECT m.user_id AS any_id, m.anyObject_id AS right_any_id, m.type_id AS type
+    FROM URelationship m
+  </entry>
+  <entry key="user_search_umembership">
+    CREATE VIEW user_search_umembership AS
+
+    SELECT m.user_id AS any_id, g.id AS group_id, g.name AS group_name
+    FROM UMembership m, SyncopeGroup g
+    WHERE m.group_id = g.id
+  </entry>
+  <entry key="user_search_role">
+    CREATE VIEW user_search_role AS
+
+    SELECT ss.user_id AS any_id, ss.role_id AS role_id
+    FROM SyncopeUser_SyncopeRole ss
+  </entry>
+  <entry key="user_search_priv">
+    CREATE VIEW user_search_priv AS
+
+    SELECT ss.user_id AS any_id, sp.privilege_id AS privilege_id
+    FROM SyncopeUser_SyncopeRole ss, SyncopeRole_Privilege sp
+    WHERE ss.role_id = sp.role_id
+  </entry>
+  <entry key="user_search_dynpriv">
+    CREATE VIEW user_search_dynpriv AS
+
+    SELECT any_id, privilege_id
+    FROM DynRoleMembers drm, SyncopeRole_Privilege rp
+    WHERE drm.role_id = rp.role_id
+  </entry>
+  <entry key="user_search_resource">
+    CREATE VIEW user_search_resource AS
+
+    SELECT st.user_id AS any_id, st.resource_id AS resource_id
+    FROM SyncopeUser_ExternalResource st
+  </entry>
+  <entry key="user_search_group_res">
+    CREATE VIEW user_search_group_res AS
+
+    SELECT m.user_id AS any_id, st.resource_id AS resource_id
+    FROM UMembership m, SyncopeGroup r, SyncopeGroup_ExternalResource st
+    WHERE m.group_id = r.id AND st.group_id = r.id
+  </entry>
+
+  <!-- anyObject -->
+  <entry key="anyObject_search">
+    CREATE VIEW anyObject_search AS
+
+    SELECT a.id as any_id, a.*,attrs,attrValues
+    FROM AnyObject a, jsonb_array_elements(COALESCE(a.plainAttrs, '[{}]'::jsonb)) attrs,
+    jsonb_array_elements(COALESCE(attrs -> 'values', '[{}]'::jsonb)) attrValues
+  </entry>
+  <entry key="anyObject_search_arelationship">
+    CREATE VIEW anyObject_search_arelationship AS
+
+    SELECT m.left_anyObject_id AS any_id, m.right_anyObject_id AS right_any_id, m.type_id AS type
+    FROM ARelationship m
+  </entry>
+  <entry key="anyObject_search_amembership">
+    CREATE VIEW anyObject_search_amembership AS
+
+    SELECT m.anyObject_id AS any_id, g.id AS group_id, g.name AS group_name
+    FROM AMembership m, SyncopeGroup g
+    WHERE m.group_id = g.id
+  </entry>
+  <entry key="anyObject_search_resource">
+    CREATE VIEW anyObject_search_resource AS
+
+    SELECT st.anyObject_id AS any_id, st.resource_id AS resource_id
+    FROM AnyObject_ExternalResource st
+  </entry>
+  <entry key="anyObject_search_group_res">
+    CREATE VIEW anyObject_search_group_res AS
+
+    SELECT m.anyObject_id AS any_id, st.resource_id AS resource_id
+    FROM AMembership m, SyncopeGroup r, SyncopeGroup_ExternalResource st
+    WHERE m.group_id = r.id AND st.group_id = r.id
+  </entry>
+
+  <!-- group -->
+  <entry key="group_search">
+    CREATE VIEW group_search AS
+
+    SELECT g.id as any_id, g.*,attrs,attrValues
+    FROM SyncopeGroup g, jsonb_array_elements(COALESCE(g.plainAttrs, '[{}]'::jsonb)) attrs,
+    jsonb_array_elements(COALESCE(attrs -> 'values', '[{}]'::jsonb)) attrValues
+  </entry>
+  <entry key="group_search_resource">
+    CREATE VIEW group_search_resource AS
+
+    SELECT st.group_id AS any_id, st.resource_id AS resource_id
+    FROM SyncopeGroup_ExternalResource st
+  </entry>
+
+</properties>
diff --git a/core/persistence-jpa-pgjsonb/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa-pgjsonb/src/test/resources/domains/MasterContent.xml
new file mode 100644
index 0000000..32efc96
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/test/resources/domains/MasterContent.xml
@@ -0,0 +1,2410 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<dataset>
+  <SyncopeDomain id="Two" adminCipherAlgorithm="SHA" adminPwd="2AA60A8FF7FCD473D321E0146AFD9E26DF395147"/>  
+  
+  <SyncopeSchema id="password.cipher.algorithm"/>
+  <PlainSchema id="password.cipher.algorithm" type="String"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <!-- notificationjob.cronExpression:
+  + not existing: NotificationJob runs according to NotificationJob.DEFAULT_CRON_EXP
+  + provided as empty string: NotificationJob disabled
+  + provided as non-empty string: NotificationJob runs according to the given value -->
+  <SyncopeSchema id="notificationjob.cronExpression"/>
+  <PlainSchema id="notificationjob.cronExpression" type="String"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  
+  <SyncopeSchema id="notification.maxRetries"/>
+  <PlainSchema id="notification.maxRetries" type="Long"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <SyncopeSchema id="token.length"/>
+  <PlainSchema id="token.length" type="Long"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <SyncopeSchema id="token.expireTime"/>
+  <PlainSchema id="token.expireTime" type="Long"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <SyncopeSchema id="selfRegistration.allowed"/>
+  <PlainSchema id="selfRegistration.allowed" type="Boolean"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <SyncopeSchema id="passwordReset.allowed"/>
+  <PlainSchema id="passwordReset.allowed" type="Boolean"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <SyncopeSchema id="passwordReset.securityQuestion"/>
+  <PlainSchema id="passwordReset.securityQuestion" type="Boolean"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <SyncopeSchema id="authentication.attributes"/>
+  <PlainSchema id="authentication.attributes" type="String" multivalue="1" uniqueConstraint="0" readonly="0"/>
+
+  <SyncopeSchema id="authentication.statuses"/>
+  <PlainSchema id="authentication.statuses" type="String" multivalue="1" uniqueConstraint="0" readonly="0"/>
+
+  <!-- Save user login date upon successful authentication -->
+  <SyncopeSchema id="log.lastlogindate"/>
+  <PlainSchema id="log.lastlogindate" type="Boolean"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <!-- Return hashed password values when reading users -->
+  <SyncopeSchema id="return.password.value"/>
+  <PlainSchema id="return.password.value" type="Boolean"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  
+  <!--  JWT lifetime in minutes -->                   
+  <SyncopeSchema id="jwt.lifetime.minutes"/>
+  <PlainSchema id="jwt.lifetime.minutes" type="Long"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+    
+  <!--  Connector and Resource configuration history -->                   
+  <SyncopeSchema id="connector.conf.history.size"/>
+  <PlainSchema id="connector.conf.history.size" type="Long"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  
+  <SyncopeSchema id="resource.conf.history.size"/>
+  <PlainSchema id="resource.conf.history.size" type="Long"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  
+  <SyncopeConf id="cd64d66f-6fff-4008-b966-a06b1cc1436d"
+               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;SHA1&quot;}],&quot;schema&quot;:&quot;password.cipher.algorithm&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;0/20 * * * * ?&quot;}],&quot;schema&quot;:&quot;notificationjob.cronExpression&quot;},{&quot;values&quot;:[{&quot;longValue&quot;:3}],&quot;schema&quot;:&quot;notification.maxRetries&quot;},{&quot;values&quot;:[{&quot;longValue&quot;:256}],&quot;schema&quot;:&quot;token.length&quot;},{&qu [...]
+
+  <!-- sample policies -->
+  <PasswordPolicy id="ce93fcda-dc3a-4369-a7b0-a6108c261c85" description="a password policy"
+                  historyLength="1" allowNullPassword="1"/>
+  <Implementation id="DefaultPasswordRuleConf1" type="PASSWORD_RULE" engine="JAVA"
+                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":8,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":false,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustE [...]
+  <PasswordPolicyRule policy_id="ce93fcda-dc3a-4369-a7b0-a6108c261c85" implementation_id="DefaultPasswordRuleConf1"/>
+  <PasswordPolicy id="986d1236-3ac5-4a19-810c-5ab21d79cba1"
+                  description="sample password policy" historyLength="0" allowNullPassword="1"/> 
+  <Implementation id="DefaultPasswordRuleConf2" type="PASSWORD_RULE"  engine="JAVA"
+                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":10,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustE [...]
+  <PasswordPolicyRule policy_id="986d1236-3ac5-4a19-810c-5ab21d79cba1" implementation_id="DefaultPasswordRuleConf2"/>
+  <AccountPolicy id="20ab5a8c-4b0c-432c-b957-f7fb9784d9f7" description="an account policy"
+                 propagateSuspension="0" maxAuthenticationAttempts="0"/>
+  <Implementation id="DefaultAccountRuleConf1" type="ACCOUNT_RULE" engine="JAVA"
+                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultAccountRuleConf","maxLength":0,"minLength":0,"pattern":null,"allUpperCase":false,"allLowerCase":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":[],"suffixesNotPermitted":[]}'/>
+  <AccountPolicyRule policy_id="20ab5a8c-4b0c-432c-b957-f7fb9784d9f7" implementation_id="DefaultAccountRuleConf1"/>
+  <AccountPolicy id="06e2ed52-6966-44aa-a177-a0ca7434201f" description="sample account policy"
+                 propagateSuspension="0" maxAuthenticationAttempts="3"/>
+  <Implementation id="DefaultAccountRuleConf2" type="ACCOUNT_RULE"  engine="JAVA"
+                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultAccountRuleConf","maxLength":0,"minLength":4,"pattern":null,"allUpperCase":false,"allLowerCase":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
+  <AccountPolicyRule policy_id="06e2ed52-6966-44aa-a177-a0ca7434201f" implementation_id="DefaultAccountRuleConf2"/>
+  <PasswordPolicy id="55e5de0b-c79c-4e66-adda-251b6fb8579a" description="sample password policy" historyLength="0" allowNullPassword="0"/> 
+  <Implementation id="DefaultPasswordRuleConf3" type="PASSWORD_RULE" engine="JAVA"
+                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":10,"nonAlphanumericRequired":true,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":true,"uppercaseRequired":true,"mustStartWithDigit":true,"mustntStartWithDigit":false,"mustEndWithDigit":true,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWit [...]
+  <PasswordPolicyRule policy_id="55e5de0b-c79c-4e66-adda-251b6fb8579a" implementation_id="DefaultPasswordRuleConf3"/>
+
+  <RelationshipType id="inclusion" description="Models the act that an object is included in another"/>
+  <RelationshipType id="neighborhood" description="Models the act that an object is near another"/>
+  
+  <AnyTypeClass id="generic membership"/>
+
+  <AnyType id="USER" kind="USER"/>
+  <AnyTypeClass id="minimal user"/>
+  <AnyType_AnyTypeClass anyType_id="USER" anyTypeClass_id="minimal user"/>
+  <AnyTypeClass id="other"/>
+  <AnyType_AnyTypeClass anyType_id="USER" anyTypeClass_id="other"/>
+
+  <AnyType id="GROUP" kind="GROUP"/>
+  <AnyTypeClass id="minimal group"/>
+  <AnyType_AnyTypeClass anyType_id="GROUP" anyTypeClass_id="minimal group"/>
+  
+  <AnyType id="PRINTER" kind="ANY_OBJECT"/>
+  <AnyTypeClass id="minimal printer"/>
+  <AnyType_AnyTypeClass anyType_id="PRINTER" anyTypeClass_id="minimal printer"/>
+      
+  <AnyTypeClass id="csv"/>
+
+  <SyncopeSchema id="fullname"/>
+  <PlainSchema id="fullname" type="String" anyTypeClass_id="minimal user"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="1" readonly="0"/>
+  <SyncopeSchema id="userId"/>
+  <Implementation id="EmailAddressValidator" type="VALIDATOR" engine="JAVA"
+                  body="org.apache.syncope.core.persistence.jpa.attrvalue.validation.EmailAddressValidator"/>
+  <PlainSchema id="userId" type="String" anyTypeClass_id="minimal user"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="1" readonly="0"
+               validator_id="EmailAddressValidator"/>
+  <SyncopeSchema id="loginDate"/>
+  <PlainSchema id="loginDate" type="Date" anyTypeClass_id="other"
+               mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"
+               conversionPattern="yyyy-MM-dd"/>
+  <SyncopeSchema id="firstname"/>
+  <PlainSchema id="firstname" type="String" anyTypeClass_id="minimal user"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SchemaLabel id="d90f90d0-cf15-407e-bac7-d46a8eb57c05" schema_id="firstname" locale="en" display="Firstname"/>
+  <SchemaLabel id="a9465ef0-b8b4-4af4-840d-77031a6b54a0" schema_id="firstname" locale="it" display="Nome"/>
+  <SchemaLabel id="ac8b7383-62df-490d-9364-88dbd3d301aa" schema_id="firstname" locale="pt_BR" display="Nome pr├│prio"/>
+  <SyncopeSchema id="surname"/>
+  <PlainSchema id="surname" type="String" anyTypeClass_id="minimal user"
+               mandatoryCondition="true" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SchemaLabel id="69712058-162a-4e2a-b07e-c78d82dc286d" schema_id="surname" locale="en" display="Surname"/>
+  <SchemaLabel id="77e7bbbb-d30c-47e1-b6d2-e0a9e8c11fe2" schema_id="surname" locale="it" display="Cognome"/>
+  <SyncopeSchema id="ctype"/>
+  <PlainSchema id="ctype" type="String" anyTypeClass_id="other"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="email"/>
+  <PlainSchema id="email" type="String" anyTypeClass_id="minimal user"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+               validator_id="EmailAddressValidator"/>
+  <SyncopeSchema id="activationDate"/>
+  <PlainSchema id="activationDate" type="Date" anyTypeClass_id="other"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+               conversionPattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ"/>
+  <SyncopeSchema id="uselessReadonly"/>
+  <PlainSchema id="uselessReadonly" type="String" anyTypeClass_id="other"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="1"/>
+  <SyncopeSchema id="cool"/>
+  <PlainSchema id="cool" type="Boolean" anyTypeClass_id="other" 
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="gender"/>
+  <PlainSchema id="gender" type="Enum" anyTypeClass_id="other"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+               enumerationValues="M;F"/>
+  <SyncopeSchema id="aLong"/>
+  <PlainSchema id="aLong" type="Long" anyTypeClass_id="other"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="makeItDouble"/>
+  <PlainSchema id="makeItDouble" type="Long" anyTypeClass_id="other"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="obscure"/>
+  <PlainSchema id="obscure" type="Encrypted" anyTypeClass_id="other"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+               secretKey="7abcdefghilmnopqrstuvz9#" cipherAlgorithm="SHA"/>
+  <SyncopeSchema id="photo"/>
+  <PlainSchema id="photo" type="Binary" anyTypeClass_id="other"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+               mimeType="image/jpeg"/>
+  
+  <Implementation id="BinaryValidator" type="VALIDATOR" engine="JAVA"
+                  body="org.apache.syncope.core.persistence.jpa.attrvalue.validation.BinaryValidator"/>
+
+  <SyncopeSchema id="csvuserid"/>
+  <DerSchema id="csvuserid" expression="firstname + ',' + surname" anyTypeClass_id="csv"/>
+  <SyncopeSchema id="cn"/>
+  <DerSchema id="cn" expression="surname + ', ' + firstname" anyTypeClass_id="minimal user"/>
+  <SyncopeSchema id="noschema"/>
+  <DerSchema id="noschema" expression="surname + ', ' + notfound" anyTypeClass_id="other"/>
+  <SyncopeSchema id="info"/>
+  <DerSchema id="info" expression="username + ' - ' + creationDate + '[' + failedLogins + ']'" anyTypeClass_id="minimal user"/>
+
+  <SyncopeSchema id="icon"/>
+  <PlainSchema id="icon" type="String" anyTypeClass_id="minimal group"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>                
+  <SyncopeSchema id="show"/>
+  <PlainSchema id="show" type="Boolean" anyTypeClass_id="minimal group"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="rderived_sx"/>
+  <PlainSchema id="rderived_sx" type="String" anyTypeClass_id="minimal group"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="rderived_dx"/>
+  <PlainSchema id="rderived_dx" type="String" anyTypeClass_id="minimal group"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>           
+  <SyncopeSchema id="title"/>
+  <PlainSchema id="title" type="String" anyTypeClass_id="minimal group"
+               mandatoryCondition="false" multivalue="1" uniqueConstraint="0" readonly="0"/>
+
+  <SyncopeSchema id="rderiveddata"/>
+  <DerSchema id="rderiveddata" expression="rderived_sx + '-' + rderived_dx"
+             anyTypeClass_id="minimal group"/>
+  <SyncopeSchema id="displayProperty"/>
+  <DerSchema id="displayProperty" expression="icon + ': ' + show"
+             anyTypeClass_id="minimal group"/>
+  <SyncopeSchema id="rderToBePropagated"/>
+  <DerSchema id="rderToBePropagated" expression="rderived_sx + '-' + rderived_dx"
+             anyTypeClass_id="minimal group"/>
+
+  <SyncopeSchema id="rderivedschema"/>
+  <DerSchema id="rderivedschema" expression="rderived_sx + '-' + rderived_dx"  anyTypeClass_id="minimal group"/>
+
+  <SyncopeSchema id="subscriptionDate"/>
+  <PlainSchema id="subscriptionDate" type="Date" anyTypeClass_id="generic membership"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
+               conversionPattern="yyyy-MM-dd'T'HH:mm:ss.SSSZ"/>
+  <SyncopeSchema id="mderived_sx"/>
+  <PlainSchema id="mderived_sx" type="String" anyTypeClass_id="generic membership"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="mderived_dx"/>
+  <PlainSchema id="mderived_dx" type="String" anyTypeClass_id="generic membership"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>          
+  <SyncopeSchema id="postalAddress"/>
+  <PlainSchema id="postalAddress" type="String" anyTypeClass_id="generic membership"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <SyncopeSchema id="mderiveddata"/>
+  <DerSchema id="mderiveddata" expression="mderived_sx + '-' + mderived_dx"/>
+  <SyncopeSchema id="mderToBePropagated"/>
+  <DerSchema id="mderToBePropagated" expression="mderived_sx + '-' + mderived_dx" 
+             anyTypeClass_id="generic membership"/>
+         
+  <SyncopeSchema id="model"/>
+  <PlainSchema id="model" type="String" anyTypeClass_id="minimal printer"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+  <SyncopeSchema id="location"/>
+  <PlainSchema id="location" type="String" anyTypeClass_id="minimal printer"
+               mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>
+
+  <Realm id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" name="/" passwordPolicy_id="986d1236-3ac5-4a19-810c-5ab21d79cba1"/>
+  <Realm id="722f3d84-9c2b-4525-8f6e-e4b82c55a36c" name="odd" 
+         parent_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" accountPolicy_id="06e2ed52-6966-44aa-a177-a0ca7434201f"/>
+  <Realm id="c5b75db1-fce7-470f-b780-3b9934d82a9d" name="even" 
+         parent_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"/>
+  <Realm id="0679e069-7355-4b20-bd11-a5a0a5453c7c" name="two" 
+         parent_id="c5b75db1-fce7-470f-b780-3b9934d82a9d"
+         accountPolicy_id="20ab5a8c-4b0c-432c-b957-f7fb9784d9f7"
+         passwordPolicy_id="ce93fcda-dc3a-4369-a7b0-a6108c261c85"/>
+  
+  <AnyObject id="fc6dbc3a-6c07-4965-8781-921e7401a4a5" name="HP LJ 1300n"
+             realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" type_id="PRINTER"
+             creator="admin" lastModifier="admin" 
+             creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"
+             plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Canon MFC8030&quot;}],&quot;schema&quot;:&quot;model&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;1st floor&quot;}],&quot;schema&quot;:&quot;location&quot;}]"/>
+  <AnyObject id="8559d14d-58c2-46eb-a2d4-a7d35161e8f8" name="Canon MF 8030cn"
+             realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" type_id="PRINTER"
+             creator="admin" lastModifier="admin" 
+             creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"
+             plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;HP Laserjet 1300n&quot;}],&quot;schema&quot;:&quot;model&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;2nd floor&quot;}],&quot;schema&quot;:&quot;location&quot;}]"/>
+  <AnyObject id="9e1d130c-d6a3-48b1-98b3-182477ed0688" name="Epson Stylus Color"
+             realm_id="0679e069-7355-4b20-bd11-a5a0a5453c7c" type_id="PRINTER"
+             creator="admin" lastModifier="admin" 
+             creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  
+  <ARelationship id="11a0ec66-b59b-428a-af3d-f856950ff1c5" type_id="neighborhood"
+                 left_anyObject_id="fc6dbc3a-6c07-4965-8781-921e7401a4a5"
+                 right_anyObject_id="8559d14d-58c2-46eb-a2d4-a7d35161e8f8"/>
+  
+  <Application id="mightyApp" description="A cool application"/>
+  <Privilege id="postMighty" description="Ability to POST"
+             spec="{ &quot;method&quot;: &quot;POST&quot;, &quot;url&quot;: &quot;/a/b/c&quot; }"
+             application_id="mightyApp"/>
+  <Privilege id="getMighty" description="Ability to GET"
+             spec="{ &quot;method&quot;: &quot;GET&quot;, &quot;url&quot;: &quot;/a/b/c&quot; }"
+             application_id="mightyApp"/>
+
+  <SyncopeRole id="User reviewer"/>
+  <SyncopeRole_entitlements entitlement="USER_READ" role_id="User reviewer"/>
+  <SyncopeRole_entitlements entitlement="USER_LIST" role_id="User reviewer"/>
+  <SyncopeRole_entitlements entitlement="USER_SEARCH" role_id="User reviewer"/>
+  <SyncopeRole_entitlements entitlement="ANYTYPE_LIST" role_id="User reviewer"/>
+  <SyncopeRole_entitlements entitlement="ANYTYPE_READ" role_id="User reviewer"/>
+  <SyncopeRole_entitlements entitlement="ANYTYPECLASS_LIST" role_id="User reviewer"/>
+  <SyncopeRole_entitlements entitlement="ANYTYPECLASS_READ" role_id="User reviewer"/>
+  <SyncopeRole_Realm role_id="User reviewer" realm_id="722f3d84-9c2b-4525-8f6e-e4b82c55a36c"/>
+  <SyncopeRole_Realm role_id="User reviewer" realm_id="c5b75db1-fce7-470f-b780-3b9934d82a9d"/>
+  
+  <SyncopeRole id="User manager"/>
+  <SyncopeRole_entitlements entitlement="USER_READ" role_id="User manager"/>
+  <SyncopeRole_entitlements entitlement="USER_LIST" role_id="User manager"/>
+  <SyncopeRole_entitlements entitlement="USER_SEARCH" role_id="User manager"/>
+  <SyncopeRole_entitlements entitlement="ANYTYPE_LIST" role_id="User manager"/>
+  <SyncopeRole_entitlements entitlement="ANYTYPE_READ" role_id="User manager"/>
+  <SyncopeRole_entitlements entitlement="ANYTYPECLASS_LIST" role_id="User manager"/>
+  <SyncopeRole_entitlements entitlement="ANYTYPECLASS_READ" role_id="User manager"/>
+  <SyncopeRole_entitlements entitlement="USER_REQUEST_FORM_CLAIM" role_id="User manager"/>
+  <SyncopeRole_entitlements entitlement="USER_REQUEST_FORM_SUBMIT" role_id="User manager"/>
+  <SyncopeRole_Realm role_id="User manager" realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"/>
+
+  <SyncopeRole id="Other"/>
+  <SyncopeRole_entitlements entitlement="SCHEMA_READ" role_id="Other"/>
+  <SyncopeRole_entitlements entitlement="GROUP_READ" role_id="Other"/>
+  <SyncopeRole_entitlements entitlement="USER_REQUEST_FORM_CLAIM" role_id="Other"/>
+  <SyncopeRole_Realm role_id="Other" realm_id="722f3d84-9c2b-4525-8f6e-e4b82c55a36c"/>
+  <SyncopeRole_Privilege role_id="Other" privilege_id="postMighty"/>
+  
+  <SyncopeRole id="Search for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="USER_READ" role_id="Search for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="USER_SEARCH" role_id="Search for realm evenTwo"/>
+  <SyncopeRole_Realm role_id="Search for realm evenTwo" realm_id="0679e069-7355-4b20-bd11-a5a0a5453c7c"/>
+
+  <SyncopeRole id="Connector and Resource for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="CONNECTOR_READ" role_id="Connector and Resource for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="CONNECTOR_UPDATE" role_id="Connector and Resource for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="CONNECTOR_DELETE" role_id="Connector and Resource for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="CONNECTOR_LIST" role_id="Connector and Resource for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="RESOURCE_READ" role_id="Connector and Resource for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="RESOURCE_UPDATE" role_id="Connector and Resource for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="RESOURCE_DELETE" role_id="Connector and Resource for realm evenTwo"/>
+  <SyncopeRole_entitlements entitlement="RESOURCE_LIST" role_id="Connector and Resource for realm evenTwo"/>
+  <SyncopeRole_Realm role_id="Connector and Resource for realm evenTwo"
+                     realm_id="0679e069-7355-4b20-bd11-a5a0a5453c7c"/>
+
+  <SyncopeUser mustChangePassword="0" id="1417acbe-cbf6-4277-9372-e75e04f97000" status="active"
+               password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
+               realm_id="c5b75db1-fce7-470f-b780-3b9934d82a9d"
+               username="rossini" creator="admin" lastModifier="admin"
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"
+               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;G&quot;}],&quot;schema&quot;:&quot;ctype&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Gioacchino&quot;}],&quot;schema&quot;:&quot;firstname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Rossini&quot;}],&quot;schema&quot;:&quot;surname&quot;},{&quot;values&quot;:[{&quot;dateValue&quot;:1243288800000},{&quot;dateValue&quot;:1274824800000}],&quot;schema&quot;:&quot;loginDate&quot;},{&q [...]
+  <SyncopeUser_SyncopeRole user_id="1417acbe-cbf6-4277-9372-e75e04f97000" role_id="Other"/>
+  <SyncopeUser mustChangePassword="0" id="74cd8ece-715a-44a4-a736-e17b46c4e7e6" status="active"
+               password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
+               realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+               username="verdi" creator="admin" lastModifier="admin"
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"
+               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Giuseppe&quot;}],&quot;schema&quot;:&quot;firstname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Verdi&quot;}],&quot;schema&quot;:&quot;surname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;verdi@syncope.org&quot;}],&quot;schema&quot;:&quot;email&quot;},{&quot;uniqueValue&quot;:{&quot;stringValue&quot;:&quot;Giuseppe Verdi&quot;},&quot;schema&quot;:&quot;fullname&quot;},{&quot;uniqu [...]
+  <SyncopeUser mustChangePassword="0" id="b3cbc78d-32e6-4bd4-92e0-bbe07566a2ee" status="active"
+               password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
+               realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+               username="vivaldi" creator="admin" lastModifier="admin"
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"
+               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Antonio&quot;}],&quot;schema&quot;:&quot;firstname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Vivaldi&quot;}],&quot;schema&quot;:&quot;surname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;vivaldi@syncope.org&quot;}],&quot;schema&quot;:&quot;email&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;F&quot;}],&quot;schema&quot;:&quot;ctype&quot;},{&quot;uniqueValue&quot;:{&q [...]
+  <SyncopeUser mustChangePassword="0" id="c9b2dec2-00a7-4855-97c0-d854842b4b24" status="active"
+               password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
+               realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+               username="bellini" creator="admin" lastModifier="admin"
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"
+               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Vincenzo&quot;}],&quot;schema&quot;:&quot;firstname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Bellini&quot;}],&quot;schema&quot;:&quot;surname&quot;},{&quot;values&quot;:[{&quot;dateValue&quot;:1245794400000}],&quot;schema&quot;:&quot;loginDate&quot;},{&quot;values&quot;:[{&quot;booleanValue&quot;:true}],&quot;schema&quot;:&quot;cool&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot; [...]
+  <SyncopeUser_SyncopeRole user_id="c9b2dec2-00a7-4855-97c0-d854842b4b24" role_id="User reviewer"/>
+  <SyncopeUser_SyncopeRole user_id="c9b2dec2-00a7-4855-97c0-d854842b4b24" role_id="User manager"/>
+  <SyncopeUser mustChangePassword="0" id="823074dc-d280-436d-a7dd-07399fae48ec" status="active"
+               password="5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8" cipherAlgorithm="SHA1"
+               realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+               username="puccini" creator="admin" lastModifier="admin" 
+               creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00" suspended="0"
+               plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Giacomo&quot;}],&quot;schema&quot;:&quot;firstname&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;Puccini&quot;}],&quot;schema&quot;:&quot;surname&quot;},{&quot;uniqueValue&quot;:{&quot;stringValue&quot;:&quot;Giacomo Puccini&quot;},&quot;schema&quot;:&quot;fullname&quot;},{&quot;uniqueValue&quot;:{&quot;stringValue&quot;:&quot;puccini@apache.org&quot;},&quot;schema&quot;:&quot;userId&quot;}]"/>
+  <SyncopeUser_SyncopeRole user_id="823074dc-d280-436d-a7dd-07399fae48ec" role_id="Search for realm evenTwo"/>
+  <SyncopeUser_SyncopeRole user_id="823074dc-d280-436d-a7dd-07399fae48ec" role_id="Connector and Resource for realm evenTwo"/>
+  
+  <SyncopeGroup id="37d15e4c-cdc1-460b-a591-8505c8133806" name="root"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"
+                plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;niceIcon&quot;}],&quot;schema&quot;:&quot;icon&quot;},{&quot;values&quot;:[{&quot;booleanValue&quot;:true}],&quot;schema&quot;:&quot;show&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;sx&quot;}],&quot;schema&quot;:&quot;rderived_sx&quot;},{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;dx&quot;}],&quot;schema&quot;:&quot;rderived_dx&quot;}]"/>
+  <SyncopeGroup id="b1f7c12d-ec83-441f-a50e-1691daaedf3b" name="child"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"
+                plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;badIcon&quot;}],&quot;schema&quot;:&quot;icon&quot;}]"/>
+  <SyncopeGroup id="29f96485-729e-4d31-88a1-6fc60e4677f3" name="citizen"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeGroup id="8fb2d51e-c605-4e80-a72b-13ffecf1aa9a" name="employee"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"
+                plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;icon4&quot;}],&quot;schema&quot;:&quot;icon&quot;}]"/>
+  <SyncopeGroup id="a3c1a693-a6be-483f-a2b3-5cfec146f4bf" name="secretary"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeGroup id="ebf97068-aa4b-4a85-9f01-680e8c4cf227" name="director"
+                userOwner_id="823074dc-d280-436d-a7dd-07399fae48ec"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"
+                plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;icon6&quot;}],&quot;schema&quot;:&quot;icon&quot;}]"/>
+  <SyncopeGroup id="bf825fe1-7320-4a54-bd64-143b5c18ab97" name="managingDirector"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeGroup id="f779c0d4-633b-4be5-8f57-32eb478a3ca5" name="otherchild"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeGroup id="0cbcabd2-4410-4b6b-8f05-a052b451d18f" name="groupForWorkflowApproval"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeGroup id="b8d38784-57e7-4595-859a-076222644b55" name="managingConsultant"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeGroup id="268fed79-f440-4390-9435-b273768eb5d6" name="groupForWorkflowOptIn"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <SyncopeGroup id="0626100b-a4ba-4e00-9971-86fad52a6216" name="aGroupForPropagation"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"
+                plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;r12&quot;}],&quot;schema&quot;:&quot;title&quot;}]"/>
+  <SyncopeGroup_AnyTypeClass group_id="0626100b-a4ba-4e00-9971-86fad52a6216" anyTypeClass_id="csv"/>  
+  <SyncopeGroup id="ba9ed509-b1f5-48ab-a334-c8530a6422dc" name="bGroupForPropagation"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"
+                plainAttrs="[{&quot;values&quot;:[{&quot;stringValue&quot;:&quot;r13&quot;}],&quot;schema&quot;:&quot;title&quot;}]"/>
+  <SyncopeGroup_AnyTypeClass group_id="ba9ed509-b1f5-48ab-a334-c8530a6422dc" anyTypeClass_id="csv"/>  
+  <SyncopeGroup id="ece66293-8f31-4a84-8e8d-23da36e70846" name="artDirector"
+                realm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>  
+  <SyncopeGroup id="034740a9-fa10-453b-af37-dc7897e98fb1" name="additional"
+                realm_id="c5b75db1-fce7-470f-b780-3b9934d82a9d"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  <TypeExtension id="84c1490c-a1d9-4b91-859c-fafbb0113a85"
+                 group_id="034740a9-fa10-453b-af37-dc7897e98fb1" anyType_id="USER"/>
+  <TypeExtension_AnyTypeClass typeExtension_id="84c1490c-a1d9-4b91-859c-fafbb0113a85" anyTypeClass_id="csv"/>
+  <TypeExtension_AnyTypeClass typeExtension_id="84c1490c-a1d9-4b91-859c-fafbb0113a85" anyTypeClass_id="other"/>
+  <SyncopeGroup id="e7ff94e8-19c9-4f0a-b8b7-28327edbf6ed" name="fake"
+                realm_id="722f3d84-9c2b-4525-8f6e-e4b82c55a36c"
+                creator="admin" lastModifier="admin" 
+                creationDate="2010-10-20 11:00:00" lastChangeDate="2010-10-20 11:00:00"/>
+  
+  <URelationship id="ca20ffca-1305-442f-be9a-3723a0cd88ca"
+                 user_id="c9b2dec2-00a7-4855-97c0-d854842b4b24"
+                 anyObject_id="fc6dbc3a-6c07-4965-8781-921e7401a4a5" type_id="neighborhood"/>
+
+  <UMembership id="3d5e91f6-305e-45f9-ad30-4897d3d43bd9"
+               user_id="1417acbe-cbf6-4277-9372-e75e04f97000" group_id="37d15e4c-cdc1-460b-a591-8505c8133806"/>
+  <UMembership id="d53f7657-2b22-4e10-a2cd-c3379a4d1a31"
+               user_id="74cd8ece-715a-44a4-a736-e17b46c4e7e6" group_id="37d15e4c-cdc1-460b-a591-8505c8133806"/>
+  <UMembership id="8e42a132-55ae-4860-bebd-2ca00ba5e959"
+               user_id="74cd8ece-715a-44a4-a736-e17b46c4e7e6" group_id="b1f7c12d-ec83-441f-a50e-1691daaedf3b"/>
+  <UMembership id="40e409a4-d870-4792-b820-30668f1269b9"
+               user_id="c9b2dec2-00a7-4855-97c0-d854842b4b24" group_id="bf825fe1-7320-4a54-bd64-143b5c18ab97"/>
+  <UMembership id="6d8a7dc0-d4bc-4b7e-b058-abcd3df28f28"
+               user_id="1417acbe-cbf6-4277-9372-e75e04f97000" group_id="f779c0d4-633b-4be5-8f57-32eb478a3ca5"/>
+  <UMembership id="34f2d776-58b1-4640-8e64-e979b4242a18"
+               user_id="74cd8ece-715a-44a4-a736-e17b46c4e7e6" group_id="29f96485-729e-4d31-88a1-6fc60e4677f3"/>
+  <UMembership id="8cfb78fc-d0e7-4f08-a0ae-d7abf3223b6f"
+               user_id="823074dc-d280-436d-a7dd-07399fae48ec" group_id="ece66293-8f31-4a84-8e8d-23da36e70846"/>
+    
+  <!-- pull policies -->
+  <PullPolicy id="66691e96-285f-4464-bc19-e68384ea4c85" description="a pull policy" conflictResolutionAction="IGNORE"/>
+  <PullPolicy id="880f8553-069b-4aed-9930-2cd53873f544" description="another pull policy" conflictResolutionAction="ALL"/>
+  <Implementation id="TestPullCorrelationRule" type="PULL_CORRELATION_RULE" engine="JAVA"
+                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultPullCorrelationRuleConf","name":"org.apache.syncope.common.lib.policy.DefaultPullCorrelationRuleConf","schemas":["username","firstname"]}'/>
+  <PullCorrelationRuleEntity id="10e3d196-7486-4c88-aefd-59e40d93a0c1" pullPolicy_id="880f8553-069b-4aed-9930-2cd53873f544" 
+                             anyType_id="USER" implementation_id="TestPullCorrelationRule"/>
+  <PullPolicy id="4ad10d94-e002-4b3f-b771-16089cc71da9" description="pull policy 1" conflictResolutionAction="IGNORE"/>
+  <PullPolicy id="9454b0d7-2610-400a-be82-fc23cf553dd6" description="pull policy for java rule" conflictResolutionAction="IGNORE"/>
+
+  <!-- push policies -->
+  <PushPolicy id="fb6530e5-892d-4f47-a46b-180c5b6c5c83" description="a push policy" conflictResolutionAction="IGNORE"/>
+  <Implementation id="TestPushCorrelationRule" type="PUSH_CORRELATION_RULE" engine="JAVA"
+                  body='{"@class":"org.apache.syncope.common.lib.policy.DefaultPushCorrelationRuleConf","name":"org.apache.syncope.common.lib.policy.DefaultPushCorrelationRuleConf","schemas":["email"]}'/>
+  <PushCorrelationRuleEntity id="24463935-32a0-4272-bc78-04d6d0adc69e" pushPolicy_id="fb6530e5-892d-4f47-a46b-180c5b6c5c83" 
+                             anyType_id="USER" implementation_id="TestPushCorrelationRule"/>
+  
+  <ConnInstance id="88a7a819-dab5-46b4-9b90-0b9769eabdb8" displayName="ConnInstance100"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                location="${connid.location}"
+                bundleName="net.tirasa.connid.bundles.soap"
+                connectorName="net.tirasa.connid.bundles.soap.WebServiceConnector"
+                version="${connid.soap.version}"
+                jsonConf='[{"schema":{"name":"endpoint","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["http://localhost:${cargo.servlet.port}/syncope-fit-build-tools/cxf/soap/provisioning"]},{"schema":{"name":"servicename","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false [...]
+  <ConnInstance_capabilities connInstance_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8" capability="CREATE"/>
+  <ConnInstance_capabilities connInstance_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8" capability="UPDATE"/>
+  <ConnInstance_capabilities connInstance_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8" capability="DELETE"/>
+  <ConnInstance_capabilities connInstance_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8" capability="SEARCH"/>
+
+  <ConnInstance id="5aa5b8be-7521-481a-9651-c557aea078c1" displayName="H2"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
+                bundleName="net.tirasa.connid.bundles.db.table"
+                connectorName="net.tirasa.connid.bundles.db.table.DatabaseTableConnector"
+                version="${connid.database.version}"
+                jsonConf='[{"schema":{"name":"disabledStatusValue","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"user","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["sa"]},{"schema":{"name":"keyColumn","displayName":null,"helpM [...]
+  <ConnInstance_capabilities connInstance_id="5aa5b8be-7521-481a-9651-c557aea078c1" capability="AUTHENTICATE"/>
+  <ConnInstance_capabilities connInstance_id="5aa5b8be-7521-481a-9651-c557aea078c1" capability="CREATE"/>
+  <ConnInstance_capabilities connInstance_id="5aa5b8be-7521-481a-9651-c557aea078c1" capability="UPDATE"/>
+  <ConnInstance_capabilities connInstance_id="5aa5b8be-7521-481a-9651-c557aea078c1" capability="DELETE"/>
+  <ConnInstance_capabilities connInstance_id="5aa5b8be-7521-481a-9651-c557aea078c1" capability="SEARCH"/>
+  <ConnInstance_capabilities connInstance_id="5aa5b8be-7521-481a-9651-c557aea078c1" capability="SYNC"/>
+
+  <ConnInstance id="5ffbb4ac-a8c3-4b44-b699-11b398a1ba08" displayName="ConnInstance102"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                location="${connid.location}"
+                bundleName="net.tirasa.connid.bundles.soap"
+                connectorName="net.tirasa.connid.bundles.soap.WebServiceConnector"
+                version="${connid.soap.version}"
+                connRequestTimeout="10"
+                jsonConf='[{"schema":{"name":"servicename","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["net.tirasa.connid.bundles.soap.provisioning.interfaces.Provisioning"]},{"schema":{"name":"endpoint","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":true,"values":["http:/ [...]
+  <ConnInstance_capabilities connInstance_id="5ffbb4ac-a8c3-4b44-b699-11b398a1ba08" capability="CREATE"/>
+  <ConnInstance_capabilities connInstance_id="5ffbb4ac-a8c3-4b44-b699-11b398a1ba08" capability="UPDATE"/>
+  <ConnInstance_capabilities connInstance_id="5ffbb4ac-a8c3-4b44-b699-11b398a1ba08" capability="DELETE"/>
+  <ConnInstance_capabilities connInstance_id="5ffbb4ac-a8c3-4b44-b699-11b398a1ba08" capability="SEARCH"/>
+
+  <ConnInstance id="fcf9f2b0-f7d6-42c9-84a6-61b28255a42b" displayName="ConnInstance103"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                location="${connid.location}"
+                bundleName="net.tirasa.connid.bundles.soap"
+                connectorName="net.tirasa.connid.bundles.soap.WebServiceConnector"
+                version="${connid.soap.version}"
+                jsonConf='[{"schema":{"name":"endpoint","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["http://localhost:${cargo.servlet.port}/syncope-fit-build-tools/cxf/soap/provisioning"]},{"schema":{"name":"servicename","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false [...]
+
+  <ConnInstance id="6c2acf1b-b052-46f0-8c56-7a8ad6905edf" displayName="CSVDir"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                location="${connid.location}"
+                bundleName="net.tirasa.connid.bundles.csvdir"
+                connectorName="net.tirasa.connid.bundles.csvdir.CSVDirConnector"
+                version="${connid.csvdir.version}"
+                jsonConf='[{"schema":{"name":"fields","displayName":"fields","helpMessage":"Column names separated by comma","type":"[Ljava.lang.String;","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["id","name","surname","email","password","theirgroup","membership","status","deleted"]},{"schema":{"name":"keyColumnNames","displayName":"Key column name","helpMessage":"Name of the column used to identify user uniquely","type":"[Ljava.lan [...]
+  <ConnInstance_capabilities connInstance_id="6c2acf1b-b052-46f0-8c56-7a8ad6905edf" capability="CREATE"/>
+  <ConnInstance_capabilities connInstance_id="6c2acf1b-b052-46f0-8c56-7a8ad6905edf" capability="UPDATE"/>
+  <ConnInstance_capabilities connInstance_id="6c2acf1b-b052-46f0-8c56-7a8ad6905edf" capability="DELETE"/>
+  <ConnInstance_capabilities connInstance_id="6c2acf1b-b052-46f0-8c56-7a8ad6905edf" capability="SEARCH"/>
+  <ConnInstance_capabilities connInstance_id="6c2acf1b-b052-46f0-8c56-7a8ad6905edf" capability="SYNC"/>
+    
+  <ConnInstance id="74141a3b-0762-4720-a4aa-fc3e374ef3ef"
+                bundleName="net.tirasa.connid.bundles.ldap" displayName="ApacheDS"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                location="${connid.location}"
+                connectorName="net.tirasa.connid.bundles.ldap.LdapConnector"
+                version="${connid.ldap.version}" 
+                jsonConf='[{"schema":{"name":"synchronizePasswords","displayName":"Enable Password Synchronization","helpMessage":"If true, the connector will synchronize passwords. The Password Capture Plugin needs to be installed for password synchronization to work.","type":"boolean","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"maintainLdapGroupMembership","displayName":"Maintain LDAP Group Membership" [...]
+  <ConnInstance_capabilities connInstance_id="74141a3b-0762-4720-a4aa-fc3e374ef3ef" capability="CREATE"/>
+  <ConnInstance_capabilities connInstance_id="74141a3b-0762-4720-a4aa-fc3e374ef3ef" capability="UPDATE"/>
+  <ConnInstance_capabilities connInstance_id="74141a3b-0762-4720-a4aa-fc3e374ef3ef" capability="DELETE"/>
+  <ConnInstance_capabilities connInstance_id="74141a3b-0762-4720-a4aa-fc3e374ef3ef" capability="SEARCH"/>
+  
+  <ConnInstance id="a28abd9b-9f4a-4ef6-a7a8-d19ad2a8f29d" displayName="H2-test2"
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
+                bundleName="net.tirasa.connid.bundles.db.table"
+                connectorName="net.tirasa.connid.bundles.db.table.DatabaseTableConnector"
+                version="${connid.database.version}"
+                jsonConf='[{"schema":{"name":"disabledStatusValue","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["false"]},{"schema":{"name":"user","displayName":null,"helpMessage":null,"type":"java.lang.String","required":false,"order":0,"confidential":false,"defaultValues":null},"overridable":false,"values":["sa"]},{"schema":{"name":"keyColumn","displayName":null,"helpM [...]
+  <ConnInstance_capabilities connInstance_id="a28abd9b-9f4a-4ef6-a7a8-d19ad2a8f29d" capability="CREATE"/>
+  <ConnInstance_capabilities connInstance_id="a28abd9b-9f4a-4ef6-a7a8-d19ad2a8f29d" capability="UPDATE"/>
+  <ConnInstance_capabilities connInstance_id="a28abd9b-9f4a-4ef6-a7a8-d19ad2a8f29d" capability="SEARCH"/>
+  <ConnInstance_capabilities connInstance_id="a28abd9b-9f4a-4ef6-a7a8-d19ad2a8f29d" capability="SYNC"/>
+  
+  <ConnInstance id="be24b061-019d-4e3e-baf0-0a6d0a45cb9c" bundleName="net.tirasa.connid.bundles.db.table" 
+                adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+                location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
+                connectorName="net.tirasa.connid.bundles.db.table.DatabaseTableConnector" 
+                displayName="H2-testpull" version="${connid.database.version}"
+                jsonConf='[{"schema":{"name":"changeLogColumn","displayName":"Change Log Column (Sync)","helpMessage":"=&lt;b&gt;Change Log Column&lt;/b&gt;&lt;br&gt;The change log column store the latest change time. Providing this value the Pull capabilities are activated.","type":"java.lang.String","required":false,"order":21,"confidential":false,"defaultValues":null},"overridable":false,"values":[]},{"schema":{"name":"nativeTimestamps","displayName":"Native Timestamps ","helpMessage" [...]
+  <ConnInstance_capabilities connInstance_id="be24b061-019d-4e3e-baf0-0a6d0a45cb9c" capability="CREATE"/>
+  <ConnInstance_capabilities connInstance_id="be24b061-019d-4e3e-baf0-0a6d0a45cb9c" capability="UPDATE"/>
+  <ConnInstance_capabilities connInstance_id="be24b061-019d-4e3e-baf0-0a6d0a45cb9c" capability="DELETE"/>
+  <ConnInstance_capabilities connInstance_id="be24b061-019d-4e3e-baf0-0a6d0a45cb9c" capability="SEARCH"/>
+  
+  <ConnInstance id="a6d017fd-a705-4507-bb7c-6ab6a6745997" bundleName="net.tirasa.connid.bundles.db.scriptedsql" 
+                adminRealm_id="0679e069-7355-4b20-bd11-a5a0a5453c7c"
+                location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
+                connectorName="net.tirasa.connid.bundles.db.scriptedsql.ScriptedSQLConnector"
+                displayName="Scripted SQL" version="${connid.database.version}"
+                jsonConf='[{&quot;schema&quot;:{&quot;name&quot;:&quot;updateScriptFileName&quot;,&quot;displayName&quot;:&quot;updateScriptFileName&quot;,&quot;helpMessage&quot;:&quot;updateScriptFileName&quot;,&quot;type&quot;:&quot;java.lang.String&quot;,&quot;required&quot;:false,&quot;order&quot;:0,&quot;confidential&quot;:false,&quot;defaultValues&quot;:[]},&quot;overridable&quot;:false,&quot;values&quot;:[&quot;${conf.directory}/scriptedsql/UpdateScript.groovy&quot;]},{&quot;schem [...]
+  <ConnInstance_capabilities connInstance_id="a6d017fd-a705-4507-bb7c-6ab6a6745997" capability="CREATE"/>
+  <ConnInstance_capabilities connInstance_id="a6d017fd-a705-4507-bb7c-6ab6a6745997" capability="UPDATE"/>
+  <ConnInstance_capabilities connInstance_id="a6d017fd-a705-4507-bb7c-6ab6a6745997" capability="DELETE"/>
+  <ConnInstance_capabilities connInstance_id="a6d017fd-a705-4507-bb7c-6ab6a6745997" capability="SEARCH"/>
+  <ConnInstance_capabilities connInstance_id="a6d017fd-a705-4507-bb7c-6ab6a6745997" capability="SYNC"/>
+  
+  <ConnInstance id="44c02549-19c3-483c-8025-4919c3283c37" bundlename="net.tirasa.connid.bundles.rest"
+                adminRealm_id="0679e069-7355-4b20-bd11-a5a0a5453c7c"
+                location="connid://${testconnectorserver.key}@localhost:${testconnectorserver.port}"
+                connectorname="net.tirasa.connid.bundles.rest.RESTConnector"
+                displayname="REST" version="${connid.rest.version}"
+                jsonconf="[{&quot;schema&quot;:{&quot;name&quot;:&quot;authenticateScript&quot;,&quot;displayName&quot;:&quot;authenticateScript&quot;,&quot;helpMessage&quot;:&quot;authenticateScript&quot;,&quot;type&quot;:&quot;java.lang.String&quot;,&quot;required&quot;:false,&quot;order&quot;:6,&quot;confidential&quot;:false,&quot;defaultValues&quot;:[&quot;&quot;]},&quot;overridable&quot;:false,&quot;values&quot;:[]},{&quot;schema&quot;:{&quot;name&quot;:&quot;contentType&quot;,&quot [...]
+  <ConnInstance_capabilities connInstance_id="44c02549-19c3-483c-8025-4919c3283c37" capability="AUTHENTICATE"/>
+  <ConnInstance_capabilities connInstance_id="44c02549-19c3-483c-8025-4919c3283c37" capability="SYNC"/>
+  <ConnInstance_capabilities connInstance_id="44c02549-19c3-483c-8025-4919c3283c37" capability="CREATE"/>
+  <ConnInstance_capabilities connInstance_id="44c02549-19c3-483c-8025-4919c3283c37" capability="DELETE"/>
+  <ConnInstance_capabilities connInstance_id="44c02549-19c3-483c-8025-4919c3283c37" capability="SEARCH"/>
+  <ConnInstance_capabilities connInstance_id="44c02549-19c3-483c-8025-4919c3283c37" capability="UPDATE"/>
+
+  <ExternalResource id="ws-target-resource-1" connector_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="0" overrideCapabilities="0"
+                    propagationPriority="1" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="ws-target-resource-2" connector_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" overrideCapabilities="0"
+                    createTraceLevel="FAILURES" deleteTraceLevel="NONE" updateTraceLevel="ALL" provisioningTraceLevel="ALL"
+                    pullPolicy_id="9454b0d7-2610-400a-be82-fc23cf553dd6"/>
+  <ExternalResource id="ws-target-resource-timeout" connector_id="5ffbb4ac-a8c3-4b44-b699-11b398a1ba08"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" overrideCapabilities="0"
+                    propagationPriority="1" createTraceLevel="FAILURES" deleteTraceLevel="NONE" updateTraceLevel="ALL" provisioningTraceLevel="ALL"
+                    jsonConf='[{"schema":{"name":"endpoint","displayName":null,"helpMessage":null,"type":"java.lang.String","required":true,"order":0,"confidential":false,"defaultValues":null},"overridable":true,"values":["http://localhost:${cargo.servlet.port}/syncope-fit-build-tools/services/provisioning"]}]'/>
+  <ExternalResource id="ws-target-resource-list-mappings-1" connector_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="0" overrideCapabilities="0"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="ws-target-resource-list-mappings-2" connector_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" overrideCapabilities="0"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="ws-target-resource-delete" connector_id="5ffbb4ac-a8c3-4b44-b699-11b398a1ba08"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="0" overrideCapabilities="0"
+                    propagationPriority="2" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="ws-target-resource-update" connector_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" overrideCapabilities="0"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="resource-testdb" connector_id="5aa5b8be-7521-481a-9651-c557aea078c1"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" overrideCapabilities="0"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="resource-testdb2" connector_id="a28abd9b-9f4a-4ef6-a7a8-d19ad2a8f29d"
+                    randomPwdIfNotProvided="1" enforceMandatoryCondition="1" overrideCapabilities="0"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="resource-csv" connector_id="6c2acf1b-b052-46f0-8c56-7a8ad6905edf"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="0" overrideCapabilities="0"
+                    pullPolicy_id="880f8553-069b-4aed-9930-2cd53873f544"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="ws-target-resource-update-resetsynctoken" connector_id="88a7a819-dab5-46b4-9b90-0b9769eabdb8"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" overrideCapabilities="0"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="resource-ldap" connector_id="74141a3b-0762-4720-a4aa-fc3e374ef3ef"
+                    randomPwdIfNotProvided="1" enforceMandatoryCondition="1" overrideCapabilities="0"
+                    propagationPriority="1"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <Implementation id="LDAPMembershipPropagationActions" type="PROPAGATION_ACTIONS" engine="JAVA"
+                  body="org.apache.syncope.core.provisioning.java.propagation.LDAPMembershipPropagationActions"/>
+  <ExternalResourcePropAction resource_id="resource-ldap" implementation_id="LDAPMembershipPropagationActions"/>
+  <ExternalResource id="resource-ldap-orgunit" connector_id="74141a3b-0762-4720-a4aa-fc3e374ef3ef"
+                    randomPwdIfNotProvided="1" enforceMandatoryCondition="1" overrideCapabilities="0"
+                    propagationPriority="1"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"
+                    jsonConf='[{"schema":{"name":"uidAttribute","displayName":"Uid Attribute","helpMessage":"The name of the LDAP attribute which is mapped to the Uid attribute. Default is \"entryUUID\".","type":"java.lang.String","required":false,"order":21,"confidential":false,"defaultValues":["entryUUID"]},"overridable":true,"values":["l"]},{"schema":{"name":"baseContexts","displayName":"Base Contexts","helpMessage":"One or more starting points in the LDAP tree that will be used when  [...]
+  <OrgUnit id="599a59cf-9a23-4447-9a59-cf9a2334473a" connObjectLink="syncope:fullPath2Dn(fullPath, 'ou') + ',o=isp'"
+           objectClass="organizationalUnit" resource_id="resource-ldap-orgunit" ignoreCaseMatch="0"/>
+  <OrgUnitItem id="5d0e7ad0-9026-42ad-be8a-32539389e7bd" connObjectKey="1" extAttrName="l"
+               intAttrName="fullpath" mandatoryCondition="true" purpose="BOTH"
+               orgUnit_id="599a59cf-9a23-4447-9a59-cf9a2334473a"/>
+  <OrgUnitItem id="1df556d3-bc23-48b7-a09b-fc3794a00019" connObjectKey="0" extAttrName="ou"
+               intAttrName="name" mandatoryCondition="true" purpose="BOTH"
+               orgUnit_id="599a59cf-9a23-4447-9a59-cf9a2334473a"/>
+  
+  <ExternalResource id="ws-target-resource-nopropagation" connector_id="fcf9f2b0-f7d6-42c9-84a6-61b28255a42b"
+                    randomPwdIfNotProvided="0" enforceMandatoryCondition="1" overrideCapabilities="0"
+                    createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"
+                    passwordPolicy_id="986d1236-3ac5-4a19-810c-5ab21d79cba1"/>
+  
+  <!-- The following three resources have been added to verify the issue SYNCOPE-68 -->
+  <ExternalResource id="ws-target-resource-nopropagation2" connector_id="fcf9f2b0-f7d6-42c9-84a6-61b28255a42b" 
+                    enforceMandatoryCondition="1" overrideCapabilities="0"
+                    randomPwdIfNotProvided="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="ws-target-resource-nopropagation3" connector_id="fcf9f2b0-f7d6-42c9-84a6-61b28255a42b" 
+                    enforceMandatoryCondition="1" overrideCapabilities="0"
+                    randomPwdIfNotProvided="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+  <ExternalResource id="ws-target-resource-nopropagation4" connector_id="fcf9f2b0-f7d6-42c9-84a6-61b28255a42b" 
+                    enforceMandatoryCondition="1" overrideCapabilities="0"
+                    randomPwdIfNotProvided="0" createTraceLevel="ALL" deleteTraceLevel="ALL" updateTraceLevel="ALL" provisioningTraceLevel="ALL"/>
+                    
+  <!-- External resource for issue SYNCOPE-230 -->
+  <ExternalResource id="resource-db-pull" connector_id="be24b061-019d-4e3e-baf0-0a6d0a45cb9c"
+                    randomPwdIfNotProvided="0" createTraceLevel="ALL" deleteTraceLevel="ALL" provisioningTraceLevel="ALL" updateTraceLevel="ALL"
+                    enforceMandatoryCondition="0" overrideCapabilities="0"/>
+                    
+  <!-- External resource for issue SYNCOPE-267 -->
+  <ExternalResource id="resource-db-virattr" connector_id="be24b061-019d-4e3e-baf0-0a6d0a45cb9c"
+                    randomPwdIfNotProvided="0" createTraceLevel="ALL" deleteTraceLevel="ALL" provisioningTraceLevel="ALL" updateTraceLevel="ALL"
+                    enforceMandatoryCondition="0" overrideCapabilities="0"/>
+
+  <ExternalResource id="resource-db-scripted" connector_id="a6d017fd-a705-4507-bb7c-6ab6a6745997"
+                    randomPwdIfNotProvided="0" createTraceLevel="ALL" deleteTraceLevel="ALL" provisioningTraceLevel="ALL" updateTraceLevel="ALL"
+                    enforceMandatoryCondition="0" overrideCapabilities="0"/>
+
+  <ExternalResource id="rest-target-resource" connector_id="44c02549-19c3-483c-8025-4919c3283c37"
+                    createTraceLevel="ALL" updateTraceLevel="ALL"  deleteTraceLevel="ALL" provisioningTraceLevel="ALL" 
+                    enforceMandatoryCondition="1" overrideCapabilities="0"
+                    propagationPriority="0" randomPwdIfNotProvided="0"/>
+
+  <!-- Use resource-testdb for passthrough authentication (SYNCOPE-164) -->
+  <AccountPolicy_ExternalResource accountPolicy_id="20ab5a8c-4b0c-432c-b957-f7fb9784d9f7" resource_id="resource-testdb"/>
+    
+  <SyncopeUser_ExternalResource user_id="1417acbe-cbf6-4277-9372-e75e04f97000" resource_id="resource-testdb2"/>
+  <SyncopeUser_ExternalResource user_id="b3cbc78d-32e6-4bd4-92e0-bbe07566a2ee" resource_id="ws-target-resource-delete"/>
+  <SyncopeUser_ExternalResource user_id="b3cbc78d-32e6-4bd4-92e0-bbe07566a2ee" resource_id="ws-target-resource-2"/>
+  <SyncopeUser_ExternalResource user_id="b3cbc78d-32e6-4bd4-92e0-bbe07566a2ee" resource_id="ws-target-resource-1"/>
+  <SyncopeUser_ExternalResource user_id="823074dc-d280-436d-a7dd-07399fae48ec" resource_id="resource-testdb2"/>
+  <SyncopeGroup_ExternalResource group_id="29f96485-729e-4d31-88a1-6fc60e4677f3" resource_id="ws-target-resource-list-mappings-1"/>
+  <SyncopeGroup_ExternalResource group_id="f779c0d4-633b-4be5-8f57-32eb478a3ca5" resource_id="ws-target-resource-2"/>
+  <SyncopeGroup_ExternalResource group_id="29f96485-729e-4d31-88a1-6fc60e4677f3" resource_id="ws-target-resource-list-mappings-2"/>
+  <SyncopeGroup_ExternalResource group_id="bf825fe1-7320-4a54-bd64-143b5c18ab97" resource_id="ws-target-resource-nopropagation"/>
+  <SyncopeGroup_ExternalResource group_id="b8d38784-57e7-4595-859a-076222644b55" resource_id="ws-target-resource-nopropagation3"/>
+  <SyncopeGroup_ExternalResource group_id="0626100b-a4ba-4e00-9971-86fad52a6216" resource_id="resource-csv"/>
+  <SyncopeGroup_ExternalResource group_id="ba9ed509-b1f5-48ab-a334-c8530a6422dc" resource_id="resource-csv"/>
+     
+  <Provision ignoreCaseMatch="0" id="209ea85f-f964-49c7-a498-6c9c2baa3bd8" resource_id="ws-target-resource-1" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc" provision_id="209ea85f-f964-49c7-a498-6c9c2baa3bd8"/>
+  <MappingItem id="96aad4e0-2678-4903-a52f-0a7d090a2863" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc" extAttrName="userId"
+               intAttrName="username" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="7f55b09c-b573-41dc-a9eb-ccd80bd3ea7a" extAttrName="email" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc"
+               intAttrName="email" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="a9749641-0556-49e2-a519-9bec35a4e06e" extAttrName="surname" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc"
+               intAttrName="surname" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="d118671c-2e3e-4aa3-a3dd-fde2ba4c4ded" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc"
+               extAttrName="__PASSWORD__" intAttrName="password" mandatoryCondition="true"
+               connObjectKey="0" password="1" purpose="PROPAGATION"/>
+  <MappingItem id="dca9de4f-9a5a-4280-8e9a-357e321ba7a5" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc" 
+               extAttrName="fullname" intAttrName="surname" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="471f0e2e-2bde-4442-9abf-0effb533f2ee" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc"
+               extAttrName="type" intAttrName="ctype" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="72324cda-a66c-4ffe-b6b6-1d9b6cee9bf2" mapping_id="bc0cf27b-16b7-4e83-a4b0-09af7ea4aacc"
+               extAttrName="name" intAttrName="firstname" mandatoryCondition="false"
+               connObjectKey="0" password="0" purpose="NONE"/>
+  
+  <Provision ignoreCaseMatch="0" id="41a53a00-0b35-4047-831a-d5238f74c7ba" resource_id="ws-target-resource-list-mappings-1" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="bf8afa4a-1522-44b9-91d0-c7b035e4fd99" provision_id="41a53a00-0b35-4047-831a-d5238f74c7ba"/>
+  <MappingItem id="6f8d7b42-44f4-4697-aff5-1736c4b01ee4" mapping_id="bf8afa4a-1522-44b9-91d0-c7b035e4fd99"
+               extAttrName="email" intAttrName="email" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="8515e385-3bf1-4928-adc9-489dee65829a" extAttrName="surname"
+               mapping_id="bf8afa4a-1522-44b9-91d0-c7b035e4fd99"
+               intAttrName="surname" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
+
+  <Provision ignoreCaseMatch="0" id="09a65250-d9de-44b1-9412-11ed996d356d" resource_id="ws-target-resource-list-mappings-2" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="b12c4fad-f0f1-406d-b143-f2d68ed28e3a" provision_id="09a65250-d9de-44b1-9412-11ed996d356d"/>
+  <MappingItem id="55a4cf7f-ac96-4e8b-931c-2d0eab6a6bca" mapping_id="b12c4fad-f0f1-406d-b143-f2d68ed28e3a"
+               extAttrName="userId" intAttrName="userId" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+
+  <Provision ignoreCaseMatch="0" id="3d75991b-caee-4993-8e46-afb13d1bfbd4" resource_id="ws-target-resource-2" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="240a0291-f89d-4557-a547-2a3b9aad625b" provision_id="3d75991b-caee-4993-8e46-afb13d1bfbd4"/>
+  <MappingItem id="d5c4d467-cd18-4148-8195-015808b4b3e6" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
+               extAttrName="fullname" intAttrName="fullname" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="BOTH"/>
+  <MappingItem id="370a8673-f3f7-4328-a9ce-acd946f687c5" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
+               extAttrName="__PASSWORD__" intAttrName="password" mandatoryCondition="true"
+               connObjectKey="0" password="1" purpose="BOTH"/>
+  <MappingItem id="c8d1a47a-1846-47b8-9f68-30aa21e94dcc" extAttrName="type" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
+               intAttrName="ctype" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="BOTH"/>
+  <MappingItem id="f0a06b24-7d4d-480e-8188-e53045885569" extAttrName="surname" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
+               intAttrName="surname" mandatoryCondition="type == 'F'"
+               connObjectKey="0" password="0" purpose="BOTH"/>
+  <MappingItem id="adc3c628-27b3-4740-be01-2f83c210ace9" extAttrName="name" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
+               intAttrName="virtualdata" mandatoryCondition="type == 'F'"
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="6972a78b-2570-45d9-bc0b-31d2f2f9c860" extAttrName="fullname" mapping_id="240a0291-f89d-4557-a547-2a3b9aad625b"
+               intAttrName="cn" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
+    
+  <Provision ignoreCaseMatch="0" id="9ebc3237-49fa-4dce-9a4c-3070e931812f" resource_id="ws-target-resource-update" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="c17813c0-4e90-4118-bb28-cd36ad6d5a4d" provision_id="9ebc3237-49fa-4dce-9a4c-3070e931812f"/>
+  <MappingItem id="cc973ed6-d031-4790-adab-fc059ac0c818" extAttrName="email" mapping_id="c17813c0-4e90-4118-bb28-cd36ad6d5a4d"
+               intAttrName="email" mandatoryCondition="false"
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="7a72c812-1897-4db0-bed4-4e7e8ea51afe" extAttrName="userId" mapping_id="c17813c0-4e90-4118-bb28-cd36ad6d5a4d"
+               intAttrName="userId" mandatoryCondition="false"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="946a3c7f-6359-4ab7-8a5f-adb08bdb4b5b" extAttrName="test3" mapping_id="c17813c0-4e90-4118-bb28-cd36ad6d5a4d"
+               intAttrName="fullname" mandatoryCondition="false"
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
+    
+  <Provision ignoreCaseMatch="0" id="8680bc79-dfa1-4719-9886-1d582bf1124f" resource_id="ws-target-resource-nopropagation" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="63ddd4c8-efed-4a22-a4b4-1f4e6f47c8d0" provision_id="8680bc79-dfa1-4719-9886-1d582bf1124f"/>
+  <MappingItem id="ffcfbb5e-7bbd-489a-a69e-2dd84f00731a" mapping_id="63ddd4c8-efed-4a22-a4b4-1f4e6f47c8d0" extAttrName="fullname" 
+               intAttrName="fullname" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+                     
+  <Provision ignoreCaseMatch="0" id="0bfa7c3e-2bb3-43d7-ac0e-d57cff7a18c8" resource_id="ws-target-resource-nopropagation2" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="3f636292-6edb-4d20-ab24-fe0c5fc3dec3" provision_id="0bfa7c3e-2bb3-43d7-ac0e-d57cff7a18c8"/>
+  <MappingItem id="e34928b8-ca57-4b6c-81c1-70bc87ff3fdc" mapping_id="3f636292-6edb-4d20-ab24-fe0c5fc3dec3" extAttrName="fullname" 
+               intAttrName="fullname" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+                     
+  <Provision ignoreCaseMatch="0" id="5bd76fec-f8d7-4ab9-acd7-89e099d534e8" resource_id="ws-target-resource-nopropagation3" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="c2a0cec1-32c4-4493-8f01-d1176e557fc1" provision_id="5bd76fec-f8d7-4ab9-acd7-89e099d534e8"/>
+  <MappingItem id="f3ba0859-b0f0-44a5-abfd-4a1a5ca29fbf" mapping_id="c2a0cec1-32c4-4493-8f01-d1176e557fc1" extAttrName="fullname"
+               intAttrName="fullname" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+                     
+  <Provision ignoreCaseMatch="0" id="18de6376-7051-4216-96f0-26629076abb9" resource_id="ws-target-resource-nopropagation4" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="906452d9-3eeb-4ef7-ac90-5ffc14513fbf" provision_id="18de6376-7051-4216-96f0-26629076abb9"/>
+  <MappingItem id="118" mapping_id="906452d9-3eeb-4ef7-ac90-5ffc14513fbf"
+               extAttrName="fullname" intAttrName="fullname" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+                       
+  <Provision ignoreCaseMatch="0" id="779fefb5-dd25-4078-915d-3c199ee32158" resource_id="resource-testdb" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="cb624b93-874b-40a0-8021-3b8116b781ab" provision_id="779fefb5-dd25-4078-915d-3c199ee32158"/>
+  <MappingItem id="1e0d30cd-2569-4a80-b9dc-af1467bd1c0b" mapping_id="cb624b93-874b-40a0-8021-3b8116b781ab"
+               extAttrName="ID" intAttrName="username" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="BOTH"/>
+  <MappingItem id="7fd1a178-77a1-4c4c-aca2-3c3f1834b77b" mapping_id="cb624b93-874b-40a0-8021-3b8116b781ab"
+               extAttrName="__PASSWORD__" intAttrName="password" mandatoryCondition="true"
+               connObjectKey="0" password="1" purpose="BOTH"/>
+                     
+  <Provision ignoreCaseMatch="0" id="0359084d-68fe-4bf8-b42b-2ebe4f578ae7" resource_id="resource-testdb2" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="935a0fc2-4a0b-4d82-9931-3c5ce44a33c1" provision_id="0359084d-68fe-4bf8-b42b-2ebe4f578ae7"/>
+  <MappingItem id="6d90658a-f470-4450-912d-6fe7d3bcda46" mapping_id="935a0fc2-4a0b-4d82-9931-3c5ce44a33c1" extAttrName="ID" 
+               intAttrName="username" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="2fb9eb01-50df-456e-86c1-b55f68cde2da" mapping_id="935a0fc2-4a0b-4d82-9931-3c5ce44a33c1" extAttrName="__PASSWORD__" 
+               intAttrName="password" mandatoryCondition="true"
+               connObjectKey="0" password="1" purpose="PROPAGATION"/>
+                         
+  <Provision ignoreCaseMatch="0" id="2adb6537-e207-4d9b-804f-90bf18cd6f48" resource_id="resource-csv" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Provision_AnyTypeClass provision_id="2adb6537-e207-4d9b-804f-90bf18cd6f48" anyTypeClass_id="csv"/>
+  <Provision_AnyTypeClass provision_id="2adb6537-e207-4d9b-804f-90bf18cd6f48" anyTypeClass_id="generic membership"/>
+  <Provision_AnyTypeClass provision_id="2adb6537-e207-4d9b-804f-90bf18cd6f48" anyTypeClass_id="minimal group"/>
+  <Mapping id="538c27dc-d260-4c53-9fc8-bf02ee226911" provision_id="2adb6537-e207-4d9b-804f-90bf18cd6f48"/>
+  <MappingItem id="517dc983-99a2-43c9-b4b4-78fd838e5ad1" extAttrName="id" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
+               intAttrName="username" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="BOTH"/>
+  <MappingItem id="ba6fb125-466e-4109-8e5d-133936437674" extAttrName="id" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
+               intAttrName="fullname" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="BOTH"/>
+  <MappingItem id="c426b070-0290-42be-9ee1-4046c7649635" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
+               extAttrName="__PASSWORD__" intAttrName="password" mandatoryCondition="true"
+               connObjectKey="0" password="1" purpose="BOTH"/>
+  <MappingItem id="20dbe358-5b71-4edd-8670-2bbde982e5c4" extAttrName="name" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
+               intAttrName="firstname" mandatoryCondition="false"
+               connObjectKey="0" password="0" purpose="BOTH"/>
+  <MappingItem id="4d70850e-9fc5-4e75-83ea-432fe090e1c0" extAttrName="surname" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
+               intAttrName="surname" mandatoryCondition="false"
+               connObjectKey="0" password="0" purpose="BOTH"/>
+  <MappingItem id="4b2f4292-d8ab-4948-a341-3f8c9e23e72d" extAttrName="email" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
+               intAttrName="userId" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="PULL"/>
+  <MappingItem id="20d6c914-54e7-4968-b1fc-685ae9c2c4a4" extAttrName="email" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
+               intAttrName="email" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="PULL"/>
+  <MappingItem id="09237f39-0d45-4258-a7cc-2400f7536b72" extAttrName="__NAME__" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
+               intAttrName="csvuserid" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+  <MappingItem id="63151b89-2eb3-4980-a682-0215d54ab4a2" extAttrName="theirgroup" mapping_id="538c27dc-d260-4c53-9fc8-bf02ee226911"
+               intAttrName="groups[root].rderToBePropagated" mandatoryCondition="false"
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
+                         
+  <Provision ignoreCaseMatch="0" id="1b53c74e-6a63-49ef-b2f1-96eeb7f1bbb8" resource_id="ws-target-resource-update-resetsynctoken" anyType_id="USER" objectClass="__ACCOUNT__"
+             serializedSyncToken='{"value":null}'/>
+  <Mapping id="23e20ce6-1ff9-495e-aa59-a58e5127a008" provision_id="1b53c74e-6a63-49ef-b2f1-96eeb7f1bbb8"/>
+  <MappingItem id="608f01c5-eb7c-462a-b4d6-b7c3c9632a50" mapping_id="23e20ce6-1ff9-495e-aa59-a58e5127a008"
+               extAttrName="userId" intAttrName="userId" mandatoryCondition="false"
+               connObjectKey="1" password="0" purpose="BOTH"/>
+  <MappingItem id="79ada054-5f8b-4e77-b405-bfec58b06e7b" mapping_id="23e20ce6-1ff9-495e-aa59-a58e5127a008"
+               extAttrName="__PASSWORD__" intAttrName="fullname" mandatoryCondition="false"
+               connObjectKey="0" password="1" purpose="BOTH"/>
+
+  <Provision ignoreCaseMatch="0" id="8b938d63-aa92-448c-89a8-a685fc0a67c8" resource_id="resource-ldap" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Provision_AnyTypeClass provision_id="8b938d63-aa92-448c-89a8-a685fc0a67c8" anyTypeClass_id="generic membership"/>
+  <Provision_AnyTypeClass provision_id="8b938d63-aa92-448c-89a8-a685fc0a67c8" anyTypeClass_id="minimal group"/>
+  <Mapping id="ae1c77c3-2f1d-4258-ad06-710bb09041a9" provision_id="8b938d63-aa92-448c-89a8-a685fc0a67c8"
+           connObjectLink="&apos;uid=&apos; + username + &apos;,ou=people,o=isp&apos;"/>
+  <MappingItem id="9ff7d686-452c-4cec-a475-c1137c5d88c7" connObjectKey="1" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
+               extAttrName="cn" intAttrName="username"
+               mandatoryCondition="true" purpose="BOTH"/>
+  <MappingItem id="73d97083-cfda-44e6-be62-3f9ac558b5eb" connObjectKey="0" password="1" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
+               extAttrName="__PASSWORD__" intAttrName="password"
+               mandatoryCondition="true" purpose="BOTH"/>
+  <MappingItem id="cf0a222c-36ea-41e6-987c-7908614ccd23" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
+               extAttrName="sn" intAttrName="surname"
+               mandatoryCondition="true" purpose="BOTH"/>
+  <MappingItem id="b3a12364-e471-4e37-83ad-476c33a43617" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
+               extAttrName="cn" intAttrName="fullname"
+               mandatoryCondition="true" purpose="BOTH"/>
+  <MappingItem id="aad2b7d7-3201-4bba-b496-f6587b4b7518" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
+               extAttrName="mail" intAttrName="email"
+               mandatoryCondition="false" purpose="BOTH"/>
+  <MappingItem id="81b83c98-127b-469b-a497-412ba50acbeb" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
+               extAttrName="title" intAttrName="title"
+               mandatoryCondition="false" purpose="BOTH"/>
+  <MappingItem id="318e92a1-3acb-49c5-b2fd-dba819c40ef1" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
+               extAttrName="postalAddress" intAttrName="postalAddress"
+               mandatoryCondition="false" purpose="BOTH"/>
+  <MappingItem id="78fa504f-213c-41ac-a922-7c9f98e5ce11" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
+               extAttrName="mail" intAttrName="userId"
+               mandatoryCondition="false" purpose="BOTH"/>
+  <MappingItem id="af6085cb-d0e8-47c9-b5f9-4b7d491a9750" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
+               extAttrName="registeredAddress" intAttrName="obscure"
+               mandatoryCondition="false" purpose="BOTH"/>
+  <MappingItem id="5bb62bd2-5007-4eb8-b4f9-9df8917dc767" connObjectKey="0" password="0" mapping_id="ae1c77c3-2f1d-4258-ad06-710bb09041a9"
+               extAttrName="jpegPhoto" intAttrName="photo"
+               mandatoryCondition="false" purpose="BOTH"/>
+        
+  <SyncopeSchema id="virtualReadOnly"/>
+  <VirSchema id="virtualReadOnly" READONLY="1" anyTypeClass_id="minimal user"
+             provision_id="8b938d63-aa92-448c-89a8-a685fc0a67c8" extAttrName="givenname"/>
+
+  <Provision ignoreCaseMatch="0" id="20a75199-3f2e-4b9a-9510-c68dd7fc7b3d" resource_id="resource-ldap" anyType_id="GROUP" objectClass="__GROUP__"/>
+  <Mapping id="128412c8-be4f-4d7b-8bed-5ab89134f718" provision_id="20a75199-3f2e-4b9a-9510-c68dd7fc7b3d"
+           connObjectLink="&apos;cn=&apos; + name + &apos;,ou=groups,o=isp&apos;"/>
+  <MappingItem id="a2bf43c8-74cb-4250-92cf-fb8889409ac1"
+               connObjectKey="1" password="0" mapping_id="128412c8-be4f-4d7b-8bed-5ab89134f718"
+               extAttrName="cn" intAttrName="name"
+               mandatoryCondition="true" purpose="BOTH"/>
+  <MappingItem id="da2a69bc-5ca0-4657-9a18-ec1f8c986046"
+               connObjectKey="0" password="0" mapping_id="128412c8-be4f-4d7b-8bed-5ab89134f718"
+               extAttrName="owner" intAttrName="userOwner"
+               mandatoryCondition="false" purpose="BOTH"/>
+  <MappingItem id="9dde8bd5-f158-499e-9d81-3d7fcf9ea1e8"
+               connObjectKey="0" password="0" mapping_id="128412c8-be4f-4d7b-8bed-5ab89134f718"
+               extAttrName="description" intAttrName="title"
+               mandatoryCondition="false" purpose="BOTH"/>
+  
+  <SyncopeSchema id="rvirtualdata"/>
+  <VirSchema id="rvirtualdata" READONLY="0" anyTypeClass_id="minimal group"
+             provision_id="20a75199-3f2e-4b9a-9510-c68dd7fc7b3d" extAttrName="businessCategory"/>
+
+  <Provision ignoreCaseMatch="0" id="46b54e2a-e43e-4cd7-8c13-1af1bd65c3d3" resource_id="resource-db-pull" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="cda910bd-fc28-4f63-890e-66edc62d428b" provision_id="46b54e2a-e43e-4cd7-8c13-1af1bd65c3d3"/>
+  <MappingItem id="1a345706-a498-41bb-a948-820307a4365e" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
+               extAttrName="EMAIL" intAttrName="email" 
+               mandatoryCondition="false" password="0" purpose="BOTH"/>
+  <MappingItem id="a234bde8-b431-408c-8ec9-c986c5b7f98d" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
+               extAttrName="SURNAME" intAttrName="fullname" 
+               mandatoryCondition="false" password="0" purpose="PULL"/>
+  <MappingItem id="51a856de-ae25-41cd-967a-86920c834b70" connObjectKey="1" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
+               extAttrName="ID" intAttrName="firstname" 
+               mandatoryCondition="false" password="0" purpose="BOTH"/>
+  <MappingItem id="f4e5178e-ef37-4949-933a-7ec7eaea64c6" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
+               extAttrName="SURNAME" intAttrName="surname" 
+               mandatoryCondition="false" password="0" purpose="BOTH"/>
+  <MappingItem id="3ac0ecaf-d9a1-4fc1-9ae9-84dc34576810" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
+               extAttrName="USERNAME" intAttrName="username" 
+               mandatoryCondition="false" password="0" purpose="BOTH"/>
+  <MappingItem id="e7215305-93c9-460b-b862-46f7b60de72d" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
+               extAttrName="EMAIL" intAttrName="userId" 
+               mandatoryCondition="false" password="0" purpose="PULL"/>
+  <MappingItem id="fb59d169-cf59-43f6-a517-adfd9aacc609" connObjectKey="0" mapping_id="cda910bd-fc28-4f63-890e-66edc62d428b"
+               extAttrName="MUSTCHANGEPASSWORD" intAttrName="mustChangePassword" 
+               mandatoryCondition="false" password="0" purpose="PULL"/>
+              
+  <Provision ignoreCaseMatch="0" id="6d7cb60a-c4ad-4a70-94ae-e5b88eb24930" resource_id="resource-db-virattr" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="45280585-308f-4571-9788-c7a4734b3614" provision_id="6d7cb60a-c4ad-4a70-94ae-e5b88eb24930"/>
+  <MappingItem id="6cb2f9f0-5fb4-4686-a375-31e2c34a6cd8" mapping_id="45280585-308f-4571-9788-c7a4734b3614" connObjectKey="1" password="0"
+               extAttrName="ID" intAttrName="key" 
+               mandatoryCondition="true" purpose="BOTH"/>
+                
+  <SyncopeSchema id="virtualdata"/>
+  <VirSchema id="virtualdata" READONLY="0" anyTypeClass_id="minimal user"
+             provision_id="6d7cb60a-c4ad-4a70-94ae-e5b88eb24930" extAttrName="USERNAME"/>
+  
+  <Provision ignoreCaseMatch="0" id="cfa86cbe-94b6-4712-a40a-a4861be1d425" resource_id="ws-target-resource-timeout" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="c71d690a-3dd9-48a5-b76f-32805186c4dc" provision_id="cfa86cbe-94b6-4712-a40a-a4861be1d425"/>
+  <MappingItem id="321bc904-e1fc-4a54-bf7c-74c8cbcc0815" mapping_id="c71d690a-3dd9-48a5-b76f-32805186c4dc" connObjectKey="1" password="0"
+               extAttrName="fullname" intAttrName="fullname"
+               mandatoryCondition="true" purpose="PROPAGATION"/>
+  
+  <Provision ignoreCaseMatch="0" id="ac1659dc-3ea3-45eb-8ae6-626e3d916492" resource_id="ws-target-resource-delete" anyType_id="USER" objectClass="__ACCOUNT__"/>
+  <Mapping id="72f590ae-2754-456b-aabb-eda7d8459dd3" provision_id="ac1659dc-3ea3-45eb-8ae6-626e3d916492"/>
+  <MappingItem id="4c98536f-10df-4953-b2df-59d7cd057fd2" mapping_id="72f590ae-2754-456b-aabb-eda7d8459dd3" extAttrName="userId" 
+               intAttrName="username" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="PROPAGATION"/>
+
+  <Provision ignoreCaseMatch="0" id="f1b55b66-eb13-4a93-a49c-448e93756eb6" resource_id="resource-db-scripted" anyType_id="PRINTER" objectClass="__PRINTER__"/>
+  <Mapping id="16439b5f-50c3-4604-97e9-f4004933abd8" provision_id="f1b55b66-eb13-4a93-a49c-448e93756eb6"/>
+  <MappingItem id="23aa0299-ddbb-4e59-8918-0ab2a32465fa" mapping_id="16439b5f-50c3-4604-97e9-f4004933abd8" extAttrName="ID" 
+               intAttrName="key" mandatoryCondition="true"
+               connObjectKey="1" password="0" purpose="BOTH"/>
+  <MappingItem id="3dc96af0-5d0a-4ec1-be84-244716d88401" mapping_id="16439b5f-50c3-4604-97e9-f4004933abd8" extAttrName="PRINTERNAME" 
+               intAttrName="name" mandatoryCondition="true"
+               connObjectKey="0" password="0" purpose="BOTH"/>
+  <MappingItem id="f3ef9f8b-e667-4b18-969f-ba98c3d78bc0" mapping_id="16439b5f-50c3-4604-97e9-f4004933abd8" extAttrName="LOCATION" 
+               intAttrName="location"
+               mandatoryCondition="false" connObjectKey="0" password="0" purpose="BOTH"/>
+    
+  <Provision ignoreCaseMatch="0" id="2e372858-f43c-4e1c-b728-58f43c5e1c23" objectClass="__ACCOUNT__" anyType_id="USER" resource_id="rest-target-resource"/>
+  <Mapping id="e6b64584-94a2-4890-b645-8494a2089011" provision_id="2e372858-f43c-4e1c-b728-58f43c5e1c23"/>
+  <MappingItem id="14726efb-09e1-441e-b26e-fb09e1841eb2" connObjectKey="0"
+               extAttrName="firstName" intAttrName="firstname" mandatoryCondition="true" password="0" purpose="BOTH"
+               mapping_id="e6b64584-94a2-4890-b645-8494a2089011"/>
+  <MappingItem id="4cdd1fd5-80cd-4fc1-9d1f-d580cd1fc11e" connObjectKey="1"
+               extAttrName="key" intAttrName="key" mandatoryCondition="true" password="0" purpose="BOTH"
+               mapping_id="e6b64584-94a2-4890-b645-8494a2089011"/>
+  <MappingItem id="4d7581b5-fe9b-49e6-b581-b5fe9bf9e60b" connObjectKey="0"
+               extAttrName="__PASSWORD__" intAttrName="password" mandatoryCondition="true" password="1" purpose="BOTH"
+               mapping_id="e6b64584-94a2-4890-b645-8494a2089011"/>
+  <MappingItem id="98f96cf4-fba2-4c68-b96c-f4fba2fc6834" connObjectKey="0"
+               extAttrName="username" intAttrName="username" mandatoryCondition="true" password="0" purpose="BOTH"
+               mapping_id="e6b64584-94a2-4890-b645-8494a2089011"/>
+  <MappingItem id="f3312f8f-1c94-493a-b12f-8f1c94093aa9" connObjectKey="0"
+               extAttrName="email" intAttrName="email" mandatoryCondition="true" password="0" purpose="BOTH"
+               mapping_id="e6b64584-94a2-4890-b645-8494a2089011"/>
+  <MappingItem id="ff49e982-fe60-4c1e-89e9-82fe60dc1ef9" connObjectKey="0"
+               extAttrName="surname" intAttrName="surname" mandatoryCondition="true" password="0" PURPOSE="BOTH"
+               mapping_id="e6b64584-94a2-4890-b645-8494a2089011"/>
+
+  <Implementation id="PullJobDelegate" type="TASKJOB_DELEGATE" engine="JAVA"
+                  body="org.apache.syncope.core.provisioning.java.pushpull.PullJobDelegate"/>
+  <Implementation id="PushJobDelegate" type="TASKJOB_DELEGATE" engine="JAVA"
+                  body="org.apache.syncope.core.provisioning.java.pushpull.PushJobDelegate"/>
+  <Task DTYPE="PropagationTask" id="1e697572-b896-484c-ae7f-0c8f63fcbc6c" operation="UPDATE"
+        objectClassName="__ACCOUNT__" resource_id="ws-target-resource-2" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
+        attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
+  <TaskExec id="e58ca1c7-178a-4012-8a71-8aa14eaf0655" task_id="1e697572-b896-484c-ae7f-0c8f63fcbc6c" startDate="2015-12-17 09:40:00.506" endDate="2015-12-17 09:42:00.506" status="SUCCESS"/>
+  <Task DTYPE="PropagationTask" id="b8870cfb-3c1e-4fc4-abcb-2559826232e6" operation="CREATE"
+        objectClassName="__ACCOUNT__" resource_id="ws-target-resource-2" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
+        attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
+  <Task DTYPE="PropagationTask" id="316285cc-ae52-4ea2-a33b-7355e189ac3f" operation="DELETE"
+        objectClassName="__ACCOUNT__" resource_id="ws-target-resource-2" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
+        attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"type","value":["type"]}]'/>
+  <Task DTYPE="PullTask" remediation="0" id="c41b9b71-9bfa-4f90-89f2-84787def4c5c" name="CSV (update matching; assign unmatching)" resource_id="resource-csv"
+        destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"
+        pullMode="INCREMENTAL" unmatchingRule="ASSIGN" matchingRule="UPDATE" active="1"
+        jobDelegate_id="PullJobDelegate"/>
+  <AnyTemplatePullTask id="3a6173a9-8c34-4e37-b3b1-0c2ea385fac0"
+                       pullTask_id="c41b9b71-9bfa-4f90-89f2-84787def4c5c" anyType_id="USER"
+                       template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":["csv"],"derAttrs":[{"schema":"cn","values":[""]}],"virAttrs":[],"resources":["resource-t [...]
+  <AnyTemplatePullTask id="b3772d66-ec06-4133-bf38-b3273845ac5b"
+                       pullTask_id="c41b9b71-9bfa-4f90-89f2-84787def4c5c" anyType_id="GROUP"
+                       template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"plainAttrs":[]}'/>
+  <Implementation id="TestSampleJobDelegate" type="TASKJOB_DELEGATE" engine="JAVA"
+                  body="org.apache.syncope.fit.core.reference.TestSampleJobDelegate"/>
+  <Task DTYPE="SchedTask" id="e95555d2-1b09-42c8-b25b-f4c4ec597979" name="SampleJob Task" active="1"
+        jobDelegate_id="TestSampleJobDelegate" cronExpression="0 0 0 1 * ?"/>
+  <Implementation id="ExpiredAccessTokenCleanup" type="TASKJOB_DELEGATE" engine="JAVA"
+                  body="org.apache.syncope.core.provisioning.java.job.ExpiredAccessTokenCleanup"/>
+  <Task DTYPE="SchedTask" id="89de5014-e3f5-4462-84d8-d97575740baf" name="Access Token Cleanup Task"  active="1"
+        jobDelegate_id="ExpiredAccessTokenCleanup" cronExpression="0 0/5 * * * ?"/>
+  <Task DTYPE="PropagationTask" id="d6c2d6d3-6329-44c1-9187-f1469ead1cfa" operation="UPDATE"
+        objectClassName="__ACCOUNT__" resource_id="ws-target-resource-nopropagation" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
+        attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
+  <TaskExec id="d789462f-e395-424f-bd8e-0db44a93222f" task_id="d6c2d6d3-6329-44c1-9187-f1469ead1cfa" startDate="2015-12-17 09:40:00.506" endDate="2015-12-17 09:42:00.506" status="SUCCESS"/>
+  <Task DTYPE="PullTask" remediation="0" id="83f7e85d-9774-43fe-adba-ccd856312994" name="TestDB Task" resource_id="resource-testdb"
+        destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="0" syncStatus="1" pullMode="FULL_RECONCILIATION"
+        unmatchingRule="PROVISION" matchingRule="UPDATE" active="1" jobDelegate_id="PullJobDelegate"/>
+  <AnyTemplatePullTask id="6c3f578d-327b-4a7c-8037-6f5ba24eb770" pullTask_id="83f7e85d-9774-43fe-adba-ccd856312994" anyType_id="USER"
+                       template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"relationships":[],"memberships":[],"dynMem [...]
+  <AnyTemplatePullTask id="45b61137-c7c3-49ee-86e0-9efffa75ae68" pullTask_id="83f7e85d-9774-43fe-adba-ccd856312994" anyType_id="GROUP"
+                       template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"plainAttrs":[]}'/>
+  <Task DTYPE="PullTask" remediation="0" id="81d88f73-d474-4450-9031-605daa4e313f" name="TestDB2 Task" resource_id="resource-testdb2"
+        destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="0" syncStatus="1" pullMode="FULL_RECONCILIATION"
+        unmatchingRule="PROVISION" matchingRule="UPDATE" active="1" jobDelegate_id="PullJobDelegate"/>
+  <Task DTYPE="PullTask" remediation="0" id="7c2242f4-14af-4ab5-af31-cdae23783655" name="TestDB Pull Task" resource_id="resource-db-pull"
+        destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" pullMode="FULL_RECONCILIATION" performCreate="1" performDelete="1" performUpdate="1" syncStatus="0"
+        unmatchingRule="PROVISION" matchingRule="UPDATE" active="1" jobDelegate_id="PullJobDelegate"/>
+  <Task DTYPE="PullTask" remediation="0" id="1e419ca4-ea81-4493-a14f-28b90113686d" name="LDAP Pull Task" resource_id="resource-ldap"
+        destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" pullMode="FULL_RECONCILIATION" performCreate="1" performDelete="1" performUpdate="1" syncStatus="0"
+        unmatchingRule="PROVISION" matchingRule="UPDATE" active="1" jobDelegate_id="PullJobDelegate"/>
+  <AnyTemplatePullTask id="df655a2a-40c0-43b1-a157-3f4988802f58" pullTask_id="1e419ca4-ea81-4493-a14f-28b90113686d" anyType_id="USER"
+                       template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":"&apos;/&apos; + title","status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":["minimal group"],"derAttrs":[],"virAttrs":[{"schema":"virtualReadOnly [...]
+  <AnyTemplatePullTask id="fda22ff3-98f3-42e4-a2ae-cd9a28282d57" pullTask_id="1e419ca4-ea81-4493-a14f-28b90113686d" anyType_id="GROUP"
+                       template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"plainAttrs":[{"schema":"show","values":["true"]}]}'/>
+  <Implementation id="LDAPMembershipPullActions" type="PULL_ACTIONS"  engine="JAVA"
+                  body="org.apache.syncope.core.provisioning.java.pushpull.LDAPMembershipPullActions"/>
+  <PullTaskAction task_id="1e419ca4-ea81-4493-a14f-28b90113686d" implementation_id="LDAPMembershipPullActions"/>
+  <Task DTYPE="PullTask" remediation="0" id="38abbf9e-a1a3-40a1-a15f-7d0ac02f47f1" name="VirAttrCache test" resource_id="resource-csv"
+        destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="0" performUpdate="1" performDelete="0" syncStatus="0" pullMode="FULL_RECONCILIATION"
+        unmatchingRule="PROVISION" matchingRule="UPDATE" active="1" jobDelegate_id="PullJobDelegate"/>
+  <Task DTYPE="PushTask" id="af558be4-9d2f-4359-bf85-a554e6e90be1" name="Export on resource-testdb2" resource_id="resource-testdb2"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"         
+        unmatchingRule="ASSIGN" matchingRule="IGNORE" active="1" jobDelegate_id="PushJobDelegate"/>  
+  <PushTaskAnyFilter id="1fdcff65-765f-4a6e-98a7-13ef7cca47e2" anyType_id="USER" pushTask_id="af558be4-9d2f-4359-bf85-a554e6e90be1" fiql="surname==Vivaldi"/>
+  <PushTaskAnyFilter id="3b564c51-5d64-48b3-8da5-fd4ebc10e0a8" anyType_id="GROUP" pushTask_id="af558be4-9d2f-4359-bf85-a554e6e90be1" fiql="name==_NO_ONE_"/>
+  <Task DTYPE="PushTask" id="97f327b6-2eff-4d35-85e8-d581baaab855" name="Export on resource-testdb2" resource_id="resource-testdb2"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"         
+        unmatchingRule="PROVISION" matchingRule="IGNORE" active="1" jobDelegate_id="PushJobDelegate"/>
+  <PushTaskAnyFilter id="199efd21-5e89-46ac-95de-f47e9d0569fc" anyType_id="USER" pushTask_id="97f327b6-2eff-4d35-85e8-d581baaab855" fiql="surname==Bellini"/>
+  <PushTaskAnyFilter id="7672a167-77d6-4639-8b1d-0af561293c7d" anyType_id="GROUP" pushTask_id="97f327b6-2eff-4d35-85e8-d581baaab855" fiql="name==_NO_ONE_"/>
+  <Task DTYPE="PushTask" id="03aa2a04-4881-4573-9117-753f81b04865" name="Export on resource-testdb2" resource_id="resource-testdb2"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"        
+        unmatchingRule="UNLINK" matchingRule="IGNORE" active="1" jobDelegate_id="PushJobDelegate"/>
+  <PushTaskAnyFilter id="39a11ba6-397a-4c94-8bfe-1f4f757d6501" anyType_id="USER" pushTask_id="03aa2a04-4881-4573-9117-753f81b04865" fiql="surname==Puccini"/>
+  <PushTaskAnyFilter id="5bd7501e-8a18-4fbd-a3fe-a1e731ba95db" anyType_id="GROUP" pushTask_id="03aa2a04-4881-4573-9117-753f81b04865" fiql="name==_NO_ONE_"/>
+  <Task DTYPE="PushTask" id="5e5f7c7e-9de7-4c6a-99f1-4df1af959807" name="Export on resource-testdb2" resource_id="resource-testdb2"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"         
+        unmatchingRule="IGNORE" matchingRule="IGNORE" active="1" jobDelegate_id="PushJobDelegate"/>
+  <PushTaskAnyFilter id="0d0371a3-5772-4b4c-ad14-139adf1d346a" anyType_id="USER" pushTask_id="5e5f7c7e-9de7-4c6a-99f1-4df1af959807" fiql="surname==Verdi"/>
+  <PushTaskAnyFilter id="2e7488ae-a2fc-4657-a93b-159b8433c0e7" anyType_id="GROUP" pushTask_id="5e5f7c7e-9de7-4c6a-99f1-4df1af959807" fiql="name==_NO_ONE_"/>
+  <Task DTYPE="PushTask" id="0bc11a19-6454-45c2-a4e3-ceef84e5d79b" name="Export on resource-testdb2" resource_id="resource-testdb2"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"        
+        unmatchingRule="ASSIGN" matchingRule="UPDATE" active="1" jobDelegate_id="PushJobDelegate"/>
+  <PushTaskAnyFilter id="41bf22fe-a014-41af-9a75-402b987eb433" anyType_id="USER" pushTask_id="0bc11a19-6454-45c2-a4e3-ceef84e5d79b" fiql="username==_NO_ONE_"/>
+  <PushTaskAnyFilter id="fa983fde-795e-4c89-a6f7-1ccd80a8adeb" anyType_id="GROUP" pushTask_id="0bc11a19-6454-45c2-a4e3-ceef84e5d79b" fiql="name==_NO_ONE_"/>
+  <Task DTYPE="PushTask" id="ec674143-480a-4816-98ad-b61fa090821e" name="Export on resource-testdb2" resource_id="resource-testdb2"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"        
+        unmatchingRule="IGNORE" matchingRule="DEPROVISION" active="1" jobDelegate_id="PushJobDelegate"/>
+  <PushTaskAnyFilter id="e238a6dc-0b04-46cf-9bfa-be68bd9f2da0" anyType_id="USER" pushTask_id="ec674143-480a-4816-98ad-b61fa090821e" fiql="surname==Verdi"/>
+  <PushTaskAnyFilter id="0eaa643e-0add-4c46-8273-539f9d6abec5" anyType_id="GROUP" pushTask_id="ec674143-480a-4816-98ad-b61fa090821e" fiql="name==_NO_ONE_"/>
+  <Task DTYPE="PushTask" id="c46edc3a-a18b-4af2-b707-f4a415507496" name="Export on resource-testdb2" resource_id="resource-testdb2"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"        
+        unmatchingRule="IGNORE" matchingRule="UNASSIGN" active="1" jobDelegate_id="PushJobDelegate"/>
+  <PushTaskAnyFilter id="335b4f11-589a-44c5-80b0-ba94892f0c62" anyType_id="USER" pushTask_id="c46edc3a-a18b-4af2-b707-f4a415507496" fiql="surname==Rossini"/>
+  <PushTaskAnyFilter id="b32eecc2-aa4f-43c6-a501-a692c3e93113" anyType_id="GROUP" pushTask_id="c46edc3a-a18b-4af2-b707-f4a415507496" fiql="name==_NO_ONE_"/>
+  <Task DTYPE="PushTask" id="51318433-cce4-4f71-8f45-9534b6c9c819" name="Export on resource-testdb2" resource_id="resource-testdb2"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"        
+        unmatchingRule="IGNORE" matchingRule="LINK" active="1" jobDelegate_id="PushJobDelegate"/>
+  <PushTaskAnyFilter id="9f974a0d-87d8-4cae-9ea9-1fc245bc1dbf" anyType_id="USER" pushTask_id="51318433-cce4-4f71-8f45-9534b6c9c819" fiql="surname==Verdi"/>
+  <PushTaskAnyFilter id="0dc46ba4-1270-4fa9-b3e1-79f940d4308f" anyType_id="GROUP" pushTask_id="51318433-cce4-4f71-8f45-9534b6c9c819" fiql="name==_NO_ONE_"/>
+  <Task DTYPE="PushTask" id="24b1be9c-7e3b-443a-86c9-798ebce5eaf2" name="Export on resource-testdb2" resource_id="resource-testdb2"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"        
+        unmatchingRule="IGNORE" matchingRule="UNLINK" active="1" jobDelegate_id="PushJobDelegate"/>
+  <PushTaskAnyFilter id="3aa3b0b8-7469-4859-89d5-476ae5915101" anyType_id="USER" pushTask_id="24b1be9c-7e3b-443a-86c9-798ebce5eaf2" fiql="surname==Verdi"/>
+  <PushTaskAnyFilter id="f054810e-6842-4017-8f60-5b4031fa2c72" anyType_id="GROUP" pushTask_id="24b1be9c-7e3b-443a-86c9-798ebce5eaf2" fiql="name==_NO_ONE_"/>
+  <Task DTYPE="PushTask" id="375c7b7f-9e3a-4833-88c9-b7787b0a69f2" name="Export on resource-testdb2" resource_id="resource-testdb2"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"        
+        unmatchingRule="IGNORE" matchingRule="UPDATE"  active="1" jobDelegate_id="PushJobDelegate"/>
+  <PushTaskAnyFilter id="95f047fc-1a8a-45f4-b56c-6e04d8ca5567" anyType_id="USER" pushTask_id="375c7b7f-9e3a-4833-88c9-b7787b0a69f2" fiql="surname==Verdi"/>
+  <PushTaskAnyFilter id="013a4298-4b14-4f8b-9f59-191c2d53dbd8" anyType_id="GROUP" pushTask_id="375c7b7f-9e3a-4833-88c9-b7787b0a69f2" fiql="name==_NO_ONE_"/>
+  <Task DTYPE="PushTask" id="fd905ba5-9d56-4f51-83e2-859096a67b75" name="Export on resource-ldap" resource_id="resource-ldap"
+        sourceRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
+        performCreate="1" performUpdate="1" performDelete="1" syncStatus="1"        
+        unmatchingRule="ASSIGN" matchingRule="UNLINK" active="1" jobDelegate_id="PushJobDelegate"/>
+  <PushTaskAnyFilter id="30842acc-f2dd-4d47-b359-20db06c30803" anyType_id="USER" pushTask_id="fd905ba5-9d56-4f51-83e2-859096a67b75" fiql="username==_NO_ONE_"/>
+  <PushTaskAnyFilter id="9e4c0233-440e-4b5b-9563-11ec0f55a334" anyType_id="GROUP" pushTask_id="fd905ba5-9d56-4f51-83e2-859096a67b75" fiql="name==citizen"/>
+  <Task DTYPE="PullTask" remediation="0" id="986867e2-993b-430e-8feb-aa9abb4c1dcd" name="CSV Task (update matching; provision unmatching)" resource_id="resource-csv"
+        destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" pullMode="INCREMENTAL"
+        unmatchingRule="PROVISION" matchingRule="UPDATE" active="1" jobDelegate_id="PullJobDelegate"/>
+  <AnyTemplatePullTask id="8bc41ba1-cc1d-4ee0-bb43-61cd148b414f" pullTask_id="986867e2-993b-430e-8feb-aa9abb4c1dcd" anyType_id="USER"
+                       template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":["resource-testdb"],"roles":[],"dynRoles":[]," [...]
+  <AnyTemplatePullTask id="9af0e343-8a37-42d2-9bc7-6e2e3b103219" pullTask_id="986867e2-993b-430e-8feb-aa9abb4c1dcd" anyType_id="GROUP"
+                       template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":null,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"plainAttrs":[]}'/>
+  <Task DTYPE="PullTask" remediation="0" id="feae4e57-15ca-40d9-b973-8b9015efca49" name="CSV (unlink matching; ignore unmatching)" resource_id="resource-csv"
+        destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" pullMode="FULL_RECONCILIATION"
+        unmatchingRule="IGNORE" matchingRule="UNLINK" active="1" jobDelegate_id="PullJobDelegate"/>
+  <Task DTYPE="PullTask" remediation="0" id="55d5e74b-497e-4bc0-9156-73abef4b9adc" name="CSV (ignore matching; assign unmatching)" resource_id="resource-csv"
+        destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" pullMode="FULL_RECONCILIATION"
+        unmatchingRule="ASSIGN" matchingRule="IGNORE" active="1" jobDelegate_id="PullJobDelegate"/>
+  <Task DTYPE="PropagationTask" id="0f618183-17ce-48bc-80bc-cc535f38983a" operation="CREATE"
+        objectClassName="__ACCOUNT__" resource_id="resource-testdb" anyTypeKind="USER" entityKey="1417acbe-cbf6-4277-9372-e75e04f97000"
+        attributes='[{"name":"__PASSWORD__","value":[{"readOnly":false,"disposed":false,"encryptedBytes":"m9nh2US0Sa6m+cXccCq0Xw==","base64SHA1Hash":"GFJ69qfjxEOdrmt+9q+0Cw2uz60="}]},{"name":"__NAME__","value":["userId"],"nameValue":"userId"},{"name":"fullname","value":["fullname"]},{"name":"type","value":["type"]}]'/>
+  <Task DTYPE="PullTask" remediation="0" id="30cfd653-257b-495f-8665-281281dbcb3d" name="Scripted SQL" resource_id="resource-db-scripted"
+        destinationRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28" performCreate="1" performUpdate="1" performDelete="0" syncStatus="0" pullMode="INCREMENTAL"
+        unmatchingRule="PROVISION" matchingRule="UPDATE" active="1" jobDelegate_id="PullJobDelegate"/>
+  <Implementation id="ExpiredBatchCleanup" type="TASKJOB_DELEGATE" engine="JAVA"
+                  body="org.apache.syncope.core.provisioning.java.job.ExpiredBatchCleanup"/>
+  <Task DTYPE="SchedTask" id="8ea0ea51-ce08-4fe3-a0c8-c281b31b5893" name="Expired Batch Operations Cleanup Task"  active="1"
+        jobDelegate_id="ExpiredBatchCleanup" cronExpression="0 0/5 * * * ?"/>
+
+  <MailTemplate id="requestPasswordReset"
+                textTemplate="Hi,
+a password reset was request for ${user.getUsername()}.
+
+In order to complete this request, you need to visit this link:
+
+http://localhost:9080/syncope-enduser/app/#!/confirmpasswordreset?token=${input.get(0).replaceAll(' ', '%20')}
+
+If you did not request this reset, just ignore the present e-mail.
+
+Best regards."
+                htmlTemplate="&lt;html&gt;
+&lt;body&gt;
+&lt;p&gt;Hi,
+a password reset was request for ${user.getUsername()}.&lt;/p&gt;
+
+&lt;p&gt;In order to complete this request, you need to visit this 
+&lt;a href=&quot;http://localhost:9080/syncope-enduser/app/#!/confirmpasswordreset?token=${input.get(0).replaceAll(' ', '%20')}&quot;&gt;link&lt;/a&gt;&lt;/p&gt;.
+
+&lt;p&gt;If you did not request this reset, just ignore the present e-mail.&lt;/p&gt;
+
+&lt;p&gt;Best regards.&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;"/>
+  <MailTemplate id="confirmPasswordReset"
+                textTemplate="Hi,
+we are happy to inform you that the password request was successfully executed for your account.
+
+Best regards."
+                htmlTemplate="&lt;html&gt;
+&lt;body&gt;
+&lt;p&gt;Hi,&lt;br/&gt;
+we are happy to inform you that the password request was successfully executed for your account.&lt;/p&gt;
+
+&lt;p&gt;Best regards.&lt;/p&gt;
+&lt;/body&gt;
+&lt;/html&gt;"/>
+  <MailTemplate id="test"/>
+  <MailTemplate id="optin"
+                textTemplate="Hi ${user.getPlainAttr(&quot;firstname&quot;).get().values[0]} ${user.getPlainAttr(&quot;surname&quot;).get().values[0]}, welcome to Syncope!
+
+Your username is ${user.username}.
+Your email address is ${user.getPlainAttr(&quot;email&quot;).get().values[0]}.
+Your email address inside a link: http://localhost/?email=${user.getPlainAttr(&quot;email&quot;).get().values[0].replace('@', '%40')}
+
+This message was sent to the following recipients:&#10;
+$$ for (recipient: recipients) {&#10;
+  * ${recipient.getPlainAttr(&quot;email&quot;).get().values[0]}&#10;
+$$ }&#10;
+&#10;
+because one of the following events occurred:&#10;
+$$ for (event: events) {&#10;
+  * ${event}&#10;
+$$ }&#10;
+&#10;
+$$ if (!empty(user.memberships)) {&#10;
+You have been provided with the following groups:&#10;
+$$ for(membership : user.memberships) {&#10;
+  * ${membership.groupName}&#10;
+$$ }&#10;
+$$ }&#10;"
+                htmlTemplate="&lt;html&gt;
+&lt;body&gt;
+&lt;h3&gt;Hi ${user.getPlainAttr(&quot;firstname&quot;).get().values[0]} ${user.getPlainAttr(&quot;surname&quot;).get().values[0]}, welcome to Syncope!&lt;/h3&gt;
+
+&lt;p&gt;
+   Your username is ${user.username}.&lt;br/&gt;
+   Your email address is ${user.getPlainAttr(&quot;email&quot;).get().values[0]}.
+   Your email address inside a &lt;a href=&quot;http://localhost/?email=${user.getPlainAttr(&quot;email&quot;).get().values[0].replace('@', '%40')}&quot;&gt;link&lt;/a&gt;.
+&lt;/p&gt;
+
+&lt;p&gt;
+    This message was sent to the following recipients:
+&lt;ul&gt;&#10;
+$$ for (recipient: recipients) {&#10;Na
+  &lt;li&gt;${recipient.getPlainAttr(&quot;email&quot;).get().values[0]}&lt;/li&gt;&#10;
+$$ }&#10;
+&lt;/ul&gt;&#10;
+
+because one of the following events occurred:
+&lt;ul&gt;&#10;
+$$ for (event: events) {&#10;
+  &lt;li&gt;${event}&lt;/li&gt;&#10;
+$$ }&#10;
+&lt;/ul&gt;&#10;
+&lt;/p&gt;
+&#10;
+$$ if (!empty(user.memberships)) {&#10;
+You have been provided with the following groups:&#10;
+&lt;ul&gt;&#10;
+$$ for(membership : user.memberships) {&#10;
+  &lt;li&gt;${membership.groupName}&lt;/li&gt;&#10;
+$$ }&#10;
+&lt;/ul&gt;&#10;
+$$ }&#10;
+&lt;/body&gt;
+&lt;/html&gt;"/>
+
+  <Notification id="e00945b5-1184-4d43-8e45-4318a8dcdfd4" active="1" recipientAttrName="email" selfAsRecipient="1" 
+                sender="admin@syncope.apache.org" subject="Password Reset request" template_id="requestPasswordReset" 
+                traceLevel="FAILURES"/> 
+  <AnyAbout id="a328f2e6-25e9-4cc1-badf-7425d7be4b39" anyType_id="USER" notification_id="e00945b5-1184-4d43-8e45-4318a8dcdfd4" filter="token!=$null"/>
+  <Notification_events notification_id="e00945b5-1184-4d43-8e45-4318a8dcdfd4" event="[CUSTOM]:[]:[]:[requestPasswordReset]:[SUCCESS]"/>
+  <Task DTYPE="NotificationTask" id="e1e520f0-2cbd-4e11-9a89-ea58a0f957e7" notification_id="e00945b5-1184-4d43-8e45-4318a8dcdfd4"
+        sender="admin@prova.org" subject="Notification for SYNCOPE-81" executed="0"
+        textBody="NOTIFICATION-81" htmlBody="NOTIFICATION-81" traceLevel="ALL"/>
+  <NotificationTask_recipients notificationTask_id="e1e520f0-2cbd-4e11-9a89-ea58a0f957e7" address="recipient@prova.org"/>  
+  
+  <Notification id="bef0c250-e8a7-4848-bb63-2564fc409ce2" active="1" recipientAttrName="email" selfAsRecipient="1" 
+                sender="admin@syncope.apache.org" subject="Password Reset successful" template_id="confirmPasswordReset" 
+                traceLevel="FAILURES"/> 
+  <Notification_events notification_id="bef0c250-e8a7-4848-bb63-2564fc409ce2" event="[CUSTOM]:[]:[]:[confirmPasswordReset]:[SUCCESS]"/>
+
+  <Notification id="9e2b911c-25de-4c77-bcea-b86ed9451050" sender="test@syncope.apache.org" subject="Test subject" template_id="test" selfAsRecipient="0" 
+                traceLevel="FAILURES"
+                recipientsFIQL="$groups==7"
+                recipientAttrName="email" active="1"/>
+  <AnyAbout id="2e2ee845-2abf-43c6-b543-49243a84e2f1" anyType_id="USER" notification_id="9e2b911c-25de-4c77-bcea-b86ed9451050" filter="fullname==*o*;fullname==*i*"/>
+  <Notification_events notification_id="9e2b911c-25de-4c77-bcea-b86ed9451050" event="[CUSTOM]:[]:[]:[unexisting1]:[FAILURE]"/>
+  <Notification_events notification_id="9e2b911c-25de-4c77-bcea-b86ed9451050" event="[CUSTOM]:[]:[]:[unexisting2]:[SUCCESS]"/>
+
+  <ReportTemplate id="empty"/>  
+  <ReportTemplate id="sample"
+                  htmlTemplate="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;
+&lt;xsl:stylesheet xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&#10;
+                version=&quot;1.0&quot;&gt;&#10;
+&#10;
+  &lt;xsl:param name=&quot;status&quot;/&gt;&#10;
+  &lt;xsl:param name=&quot;message&quot;/&gt;&#10;
+  &lt;xsl:param name=&quot;start&quot;/&gt;&#10;
+  &lt;xsl:param name=&quot;end&quot;/&gt;&#10;
+  &#10;
+  &lt;xsl:template match=&quot;/&quot;&gt;&#10;
+    &lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot; xml:lang=&quot;en&quot; lang=&quot;en&quot;&gt;&#10;
+      &lt;head&gt;&#10;
+        &lt;meta http-equiv=&quot;content-type&quot; content=&quot;text/html; charset=utf-8&quot; /&gt;&#10;
+        &lt;title&gt;Apache Syncope Report - &lt;xsl:value-of select=&quot;report/@name&quot;/&gt;&lt;/title&gt;&#10;
+      &lt;/head&gt;&#10;
+      &lt;body&gt;&#10;
+        &lt;table style=&quot;border: 1px solid black;&quot;&gt;&#10;
+          &lt;tr&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;h1&gt;Report Name:&lt;/h1&gt;&#10;
+            &lt;/td&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;h1&gt;&#10;
+                &lt;xsl:value-of select=&quot;report/@name&quot;/&gt;&#10;
+              &lt;/h1&gt;&#10;
+            &lt;/td&gt;&#10;
+          &lt;/tr&gt;&#10;
+          &lt;tr&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;h2&gt;Start Date:&lt;/h2&gt;&#10;
+            &lt;/td&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;h2&gt;&#10;
+                &lt;xsl:value-of select=&quot;$start&quot;/&gt;&#10;
+              &lt;/h2&gt;&#10;
+            &lt;/td&gt;&#10;
+          &lt;/tr&gt;&#10;
+          &lt;tr&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;h2&gt;End Date:&lt;/h2&gt;&#10;
+            &lt;/td&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;h2&gt;&#10;
+                &lt;xsl:value-of select=&quot;$end&quot;/&gt;&#10;
+              &lt;/h2&gt;&#10;
+            &lt;/td&gt;&#10;
+          &lt;/tr&gt;&#10;
+        &lt;/table&gt;&#10;
+&#10;
+        &lt;xsl:apply-templates/&gt;&#10;
+      &lt;/body&gt;&#10;
+    &lt;/html&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+&#10;
+  &lt;xsl:template match=&quot;reportlet[@class='org.apache.syncope.core.provisioning.java.job.report.StaticReportlet']&quot;&gt;&#10;
+    &lt;h2&gt;Reportlet: &#10;
+      &lt;xsl:value-of select=&quot;@name&quot;/&gt;&#10;
+    &lt;/h2&gt;&#10;
+        &#10;
+    &lt;xsl:if test=&quot;string-length(string/text()) &amp;gt; 0&quot;&gt;&#10;
+      &lt;p&gt;String value:                 &#10;
+        &lt;xsl:value-of select=&quot;string/text()&quot;/&gt;&#10;
+      &lt;/p&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(long/text()) &amp;gt; 0&quot;&gt;&#10;
+      &lt;p&gt;Long value: &#10;
+        &lt;xsl:value-of select=&quot;long/text()&quot;/&gt;&#10;
+      &lt;/p&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(double/text()) &amp;gt; 0&quot;&gt;&#10;
+      &lt;p&gt;Double value: &#10;
+        &lt;xsl:value-of select=&quot;double/text()&quot;/&gt;&#10;
+      &lt;/p&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(date/text()) &amp;gt; 0&quot;&gt;&#10;
+      &lt;p&gt;Date value: &#10;
+        &lt;xsl:value-of select=&quot;date/text()&quot;/&gt;&#10;
+      &lt;/p&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(enum/text()) &amp;gt; 0&quot;&gt;&#10;
+      &lt;p&gt;Enum value: &#10;
+        &lt;xsl:value-of select=&quot;enum/text()&quot;/&gt;&#10;
+      &lt;/p&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(list) &amp;gt; 0&quot;&gt;&#10;
+      &lt;p&gt;List values:&lt;/p&gt;&#10;
+            &#10;
+      &lt;ul&gt;&#10;
+        &lt;xsl:for-each select=&quot;list/string&quot;&gt;&#10;
+          &lt;xsl:if test=&quot;string-length(string/text()) &amp;gt; 0&quot;&gt;&#10;
+            &lt;li&gt;&#10;
+              &lt;xsl:value-of select=&quot;text()&quot;/&gt;&#10;
+            &lt;/li&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+        &lt;/xsl:for-each&gt;&#10;
+      &lt;/ul&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+  &#10;
+  &lt;xsl:template match=&quot;reportlet[@class='org.apache.syncope.core.provisioning.java.job.report.UserReportlet']&quot;&gt;&#10;
+    &#10;
+    &lt;h3&gt;Reportlet: &lt;xsl:value-of select=&quot;@name&quot;/&gt;&lt;/h3&gt;&#10;
+    &#10;
+    &lt;xsl:for-each select=&quot;user&quot;&gt;&#10;
+      &lt;h4&gt;User &lt;xsl:value-of select=&quot;@username&quot;/&gt;&lt;/h4&gt;&#10;
+      &#10;
+      &lt;table style=&quot;border: 1px solid black;&quot;&gt;&#10;
+        &lt;tr&gt;&#10;
+          &lt;td&gt;Status:&lt;/td&gt;&#10;
+          &lt;td&gt;&#10;
+            &lt;xsl:value-of select=&quot;@status&quot;/&gt;&#10;
+          &lt;/td&gt;&#10;
+        &lt;/tr&gt;&#10;
+        &lt;xsl:if test=&quot;string-length(@creationDate) &amp;gt; 0&quot;&gt;&#10;
+          &lt;tr&gt;&#10;
+            &lt;td&gt;Creation Date:&lt;/td&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;xsl:value-of select=&quot;@creationDate&quot;/&gt;&#10;
+            &lt;/td&gt;&#10;
+          &lt;/tr&gt;&#10;
+        &lt;/xsl:if&gt;&#10;
+        &lt;xsl:if test=&quot;string-length(@lastLoginDate) &amp;gt; 0&quot;&gt;&#10;
+          &lt;tr&gt;&#10;
+            &lt;td&gt;Last Login Date:&lt;/td&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;xsl:value-of select=&quot;@lastLoginDate&quot;/&gt;&#10;
+            &lt;/td&gt;&#10;
+          &lt;/tr&gt;&#10;
+        &lt;/xsl:if&gt;&#10;
+        &lt;xsl:if test=&quot;string-length(@changePwdDate) &amp;gt; 0&quot;&gt;&#10;
+          &lt;tr&gt;&#10;
+            &lt;td&gt;Change Password Date:&lt;/td&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;xsl:value-of select=&quot;@changePwdDate&quot;/&gt;&#10;
+            &lt;/td&gt;&#10;
+          &lt;/tr&gt;&#10;
+        &lt;/xsl:if&gt;&#10;
+        &lt;xsl:if test=&quot;string-length(@passwordHistorySize) &amp;gt; 0&quot;&gt;&#10;
+          &lt;tr&gt;&#10;
+            &lt;td&gt;Password History Size:&lt;/td&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;xsl:value-of select=&quot;@passwordHistorySize&quot;/&gt;&#10;
+            &lt;/td&gt;&#10;
+          &lt;/tr&gt;&#10;
+        &lt;/xsl:if&gt;&#10;
+        &lt;xsl:if test=&quot;string-length(@failedLoginCount) &amp;gt; 0&quot;&gt;&#10;
+          &lt;tr&gt;&#10;
+            &lt;td&gt;Number of Failed Login Attempts:&lt;/td&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;xsl:value-of select=&quot;@failedLoginCount&quot;/&gt;&#10;
+            &lt;/td&gt;&#10;
+          &lt;/tr&gt;&#10;
+        &lt;/xsl:if&gt;&#10;
+      &lt;/table&gt;&#10;
+&#10;
+      &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+        &lt;xsl:with-param name=&quot;label&quot;&gt;Attributes&lt;/xsl:with-param&gt;&#10;
+        &lt;xsl:with-param name=&quot;node&quot; select=&quot;attributes/attribute&quot;/&gt;&#10;
+      &lt;/xsl:call-template&gt;&#10;
+&#10;
+      &lt;!--&lt;xsl:if test=&quot;string-length(derivedAttributes/derivedAttribute) &amp;gt; 0&quot;&gt;--&gt;&#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(derivedAttributes/derivedAttribute) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+            &lt;xsl:with-param name=&quot;label&quot;&gt;Derived Attributes&lt;/xsl:with-param&gt;&#10;
+            &lt;xsl:with-param name=&quot;node&quot; select=&quot;derivedAttributes/derivedAttribute&quot;/&gt;&#10;
+          &lt;/xsl:call-template&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;h5&gt;THIS USER HASN'T DERIVED ATTRIBUTES&lt;/h5&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &lt;!--&lt;/xsl:if&gt;--&gt;&#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(virtualAttributes/virtualAttribute) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+            &lt;xsl:with-param name=&quot;label&quot;&gt;Virtual Attributes&lt;/xsl:with-param&gt;&#10;
+            &lt;xsl:with-param name=&quot;node&quot; select=&quot;virtualAttributes/virtualAttribute&quot;/&gt;&#10;
+          &lt;/xsl:call-template&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;h5&gt;THIS USER HASN'T VIRTUAL ATTRIBUTES&lt;/h5&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(memberships/membership) &amp;gt; 0&quot;&gt;&#10;
+          &lt;h4&gt;Memberships&lt;/h4&gt;&#10;
+          &lt;xsl:for-each select=&quot;memberships/membership&quot;&gt;&#10;
+            &lt;h5&gt;Group: &lt;xsl:value-of select=&quot;@groupName&quot;/&gt;(&lt;xsl:value-of select=&quot;@groupId&quot;/&gt;)&lt;/h5&gt;&#10;
+            &lt;blockquote&gt;&#10;
+              &lt;xsl:choose&gt;&#10;
+                &lt;xsl:when test=&quot;string-length(attributes/attribute) &amp;gt; 0&quot;&gt;&#10;
+                  &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+                    &lt;xsl:with-param name=&quot;label&quot;&gt;Attributes&lt;/xsl:with-param&gt;&#10;
+                    &lt;xsl:with-param name=&quot;node&quot; select=&quot;attributes/attribute&quot;/&gt;&#10;
+                  &lt;/xsl:call-template&gt;&#10;
+                &lt;/xsl:when&gt;&#10;
+                &lt;xsl:otherwise&gt;&#10;
+                  &lt;h5&gt;THIS GROUP HASN'T ATTRIBUTES&lt;/h5&gt;&#10;
+                &lt;/xsl:otherwise&gt;&#10;
+              &lt;/xsl:choose&gt;&#10;
+              &lt;xsl:choose&gt;&#10;
+                &lt;xsl:when test=&quot;string-length(derivedAttributes/derivedAttribute) &amp;gt; 0&quot;&gt;&#10;
+                  &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+                    &lt;xsl:with-param name=&quot;label&quot;&gt;Derived Attributes&lt;/xsl:with-param&gt;&#10;
+                    &lt;xsl:with-param name=&quot;node&quot; select=&quot;derivedAttributes/derivedAttribute&quot;/&gt;&#10;
+                  &lt;/xsl:call-template&gt;&#10;
+                &lt;/xsl:when&gt;&#10;
+                &lt;xsl:otherwise&gt;&#10;
+                  &lt;h5&gt;THIS GROUP HASN'T DERIVED ATTRIBUTES&lt;/h5&gt;&#10;
+                &lt;/xsl:otherwise&gt;&#10;
+              &lt;/xsl:choose&gt;&#10;
+              &lt;xsl:choose&gt;&#10;
+                &lt;xsl:when test=&quot;string-length(virtualAttributes/virtualAttribute) &amp;gt; 0&quot;&gt;&#10;
+                  &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+                    &lt;xsl:with-param name=&quot;label&quot;&gt;Virtual Attributes&lt;/xsl:with-param&gt;&#10;
+                    &lt;xsl:with-param name=&quot;node&quot; select=&quot;virtualAttributes/virtualAttribute&quot;/&gt;&#10;
+                  &lt;/xsl:call-template&gt;&#10;
+                &lt;/xsl:when&gt;&#10;
+                &lt;xsl:otherwise&gt;&#10;
+                  &lt;h5&gt;THIS GROUP HASN'T VIRTUAL ATTRIBUTES&lt;/h5&gt;&#10;
+                &lt;/xsl:otherwise&gt;&#10;
+              &lt;/xsl:choose&gt;&#10;
+              &lt;xsl:call-template name=&quot;groupResources&quot;&gt;&#10;
+                &lt;xsl:with-param name=&quot;node&quot; select=&quot;resources/resource&quot;/&gt;&#10;
+              &lt;/xsl:call-template&gt;&#10;
+            &lt;/blockquote&gt;&#10;
+          &lt;/xsl:for-each&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;h5&gt;THIS USER ISN'T ASSIGNED TO A GROUP&lt;/h5&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &lt;xsl:if test=&quot;string-length(resources) &amp;gt; 0&quot;&gt;&#10;
+        &lt;xsl:call-template name=&quot;resources&quot;&gt;&#10;
+          &lt;xsl:with-param name=&quot;node&quot; select=&quot;resources/resource&quot;/&gt;&#10;
+        &lt;/xsl:call-template&gt;&#10;
+      &lt;/xsl:if&gt;&#10;
+      &lt;hr/&gt;&#10;
+    &lt;/xsl:for-each&gt;&#10;
+       &#10;
+  &lt;/xsl:template&gt;&#10;
+&#10;
+  &lt;xsl:template match=&quot;reportlet[@class='org.apache.syncope.core.provisioning.java.job.report.GroupReportlet']&quot;&gt;&#10;
+    &lt;h2&gt;Reportlet: &lt;xsl:value-of select=&quot;@name&quot;/&gt;&lt;/h2&gt;&#10;
+    &lt;xsl:for-each select=&quot;group&quot;&gt;&#10;
+      &lt;h3&gt;Group &lt;xsl:value-of select=&quot;@name&quot;/&gt;&lt;/h3&gt;&#10;
+      &#10;
+      &lt;table style=&quot;border: 1px solid black;&quot;&gt;&#10;
+        &lt;tr&gt;&#10;
+          &lt;td&gt;Id:&lt;/td&gt;&#10;
+          &lt;td&gt;&#10;
+            &lt;xsl:value-of select=&quot;@id&quot;/&gt;&#10;
+          &lt;/td&gt;&#10;
+        &lt;/tr&gt;&#10;
+        &lt;xsl:if test=&quot;@groupOwner != 'null'&quot;&gt; &lt;!--!= null test=&quot;not(USER/FIRSTNAME)&quot; --&gt;&#10;
+          &lt;tr&gt;&#10;
+            &lt;td&gt;Group Owner:&lt;/td&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;xsl:value-of select=&quot;@groupOwner&quot;/&gt;&#10;
+            &lt;/td&gt;&#10;
+          &lt;/tr&gt;&#10;
+        &lt;/xsl:if&gt;&#10;
+        &lt;xsl:if test=&quot;@userOwner != 'null'&quot;&gt;&#10;
+          &lt;tr&gt;&#10;
+            &lt;td&gt;User Owner:&lt;/td&gt;&#10;
+            &lt;td&gt;&#10;
+              &lt;xsl:value-of select=&quot;@userOwner&quot;/&gt;&#10;
+            &lt;/td&gt;&#10;
+          &lt;/tr&gt;&#10;
+        &lt;/xsl:if&gt;&#10;
+        &#10;
+      &lt;/table&gt;&#10;
+&#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(attributes/attribute) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+            &lt;xsl:with-param name=&quot;label&quot;&gt;Attributes&lt;/xsl:with-param&gt;&#10;
+            &lt;xsl:with-param name=&quot;node&quot; select=&quot;attributes/attribute&quot;/&gt;&#10;
+          &lt;/xsl:call-template&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;h5&gt;THIS GROUP HASN'T ANY ATTRIBUTE&lt;/h5&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+&#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(derivedAttributes/derivedAttribute) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+            &lt;xsl:with-param name=&quot;label&quot;&gt;Derived Attributes&lt;/xsl:with-param&gt;&#10;
+            &lt;xsl:with-param name=&quot;node&quot; select=&quot;derivedAttributes/derivedAttribute&quot;/&gt;&#10;
+          &lt;/xsl:call-template&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;h5&gt;THIS GROUP HASN'T ANY DERIVED ATTRIBUTE&lt;/h5&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &lt;!--&lt;/xsl:if&gt;--&gt;&#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(virtualAttributes/virtualAttribute) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+            &lt;xsl:with-param name=&quot;label&quot;&gt;Virtual Attributes&lt;/xsl:with-param&gt;&#10;
+            &lt;xsl:with-param name=&quot;node&quot; select=&quot;virtualAttributes/virtualAttribute&quot;/&gt;&#10;
+          &lt;/xsl:call-template&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;h5&gt;THIS GROUP HASN'T ANY VIRTUAL ATTRIBUTE&lt;/h5&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;users/user&quot;&gt;&#10;
+          &lt;h4&gt;Users&lt;/h4&gt;&#10;
+          &lt;xsl:for-each select=&quot;users/user&quot;&gt;&#10;
+            &lt;h5&gt;User: &lt;xsl:value-of select=&quot;@userUsername&quot;/&gt; (Id: &lt;xsl:value-of select=&quot;@userId&quot;/&gt;)&lt;/h5&gt;&#10;
+          &lt;/xsl:for-each&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;h5&gt;THIS GROUP HASN'T ANY USER ASSIGNED TO&lt;/h5&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &#10;
+      &lt;xsl:call-template name=&quot;groupResources&quot;&gt;&#10;
+        &lt;xsl:with-param name=&quot;node&quot; select=&quot;resources/resource&quot;/&gt;&#10;
+      &lt;/xsl:call-template&gt;&#10;
+      &lt;hr/&gt;&#10;
+      &#10;
+    &lt;/xsl:for-each&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+  &#10;
+  &lt;xsl:template name=&quot;attributes&quot;&gt;&#10;
+    &lt;xsl:param name=&quot;label&quot;/&gt;&#10;
+    &lt;xsl:param name=&quot;node&quot;/&gt;&#10;
+&#10;
+    &lt;h4&gt;&#10;
+      &lt;xsl:value-of select=&quot;$label&quot;/&gt;&#10;
+    &lt;/h4&gt;&#10;
+    &#10;
+    &lt;table&gt;&#10;
+      &lt;thead&gt;&#10;
+        &lt;tr&gt;&#10;
+          &lt;th&gt;Schema name&lt;/th&gt;&#10;
+          &lt;th&gt;Value(s)&lt;/th&gt;&#10;
+        &lt;/tr&gt;&#10;
+      &lt;/thead&gt;&#10;
+      &lt;tbody&gt;&#10;
+        &lt;xsl:for-each select=&quot;$node&quot;&gt;&#10;
+          &lt;xsl:if test=&quot;string-length(value/text()) &amp;gt; 0&quot;&gt;&#10;
+            &lt;tr&gt;&#10;
+              &lt;td&gt;&#10;
+                &lt;xsl:value-of select=&quot;@name&quot;/&gt;&#10;
+              &lt;/td&gt;&#10;
+              &lt;td&gt;&#10;
+                &lt;ul&gt;&#10;
+                  &lt;xsl:for-each select=&quot;value&quot;&gt;&#10;
+                    &lt;li&gt;&#10;
+                      &lt;xsl:value-of select=&quot;text()&quot;/&gt;&#10;
+                    &lt;/li&gt;&#10;
+                  &lt;/xsl:for-each&gt;&#10;
+                &lt;/ul&gt;&#10;
+              &lt;/td&gt;&#10;
+            &lt;/tr&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+        &lt;/xsl:for-each&gt;&#10;
+      &lt;/tbody&gt;&#10;
+    &lt;/table&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+&#10;
+  &lt;xsl:template name=&quot;resources&quot;&gt;&#10;
+    &lt;xsl:param name=&quot;node&quot;/&gt;&#10;
+    &#10;
+    &lt;h4&gt;Resources&lt;/h4&gt;&#10;
+    &lt;ul&gt;&#10;
+      &lt;xsl:for-each select=&quot;$node&quot;&gt;&#10;
+        &lt;li&gt;&#10;
+          &lt;xsl:value-of select=&quot;@name&quot;/&gt;&#10;
+        &lt;/li&gt;&#10;
+      &lt;/xsl:for-each&gt;&#10;
+    &lt;/ul&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+  &#10;
+  &lt;xsl:template name=&quot;groupResources&quot;&gt;&#10;
+    &lt;xsl:param name=&quot;node&quot;/&gt;&#10;
+    &#10;
+    &lt;h4&gt;Group Resources&lt;/h4&gt;&#10;
+    &lt;ul&gt;&#10;
+      &lt;xsl:for-each select=&quot;$node&quot;&gt;&#10;
+        &lt;li&gt;&#10;
+          &lt;xsl:value-of select=&quot;@name&quot;/&gt;&#10;
+        &lt;/li&gt;&#10;
+      &lt;/xsl:for-each&gt;&#10;
+    &lt;/ul&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+&lt;/xsl:stylesheet&gt;&#10;"
+                  csvTemplate="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;
+&lt;xsl:stylesheet xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&#10;
+                version=&quot;1.0&quot;&gt;&#10;
+ &#10;
+  &lt;xsl:param name=&quot;status&quot;/&gt;&#10;
+  &lt;xsl:param name=&quot;message&quot;/&gt;&#10;
+  &lt;xsl:param name=&quot;start&quot;/&gt;&#10;
+  &lt;xsl:param name=&quot;end&quot;/&gt;&#10;
+    &#10;
+  &lt;xsl:template match=&quot;/&quot;&gt;&#10;
+    &lt;xsl:apply-templates/&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+&#10;
+  &lt;xsl:variable name=&quot;delimiter&quot; select=&quot;';'&quot;/&gt;&#10;
+   &#10;
+  &lt;xsl:template match=&quot;reportlet[@class='org.apache.syncope.core.provisioning.java.job.report.StaticReportlet']&quot;&gt;&#10;
+    &lt;xsl:call-template name=&quot;header&quot;&gt;&#10;
+      &lt;xsl:with-param name=&quot;node&quot; select=&quot;configurations/staticAttributes&quot;/&gt;&#10;
+    &lt;/xsl:call-template&gt;&#10;
+    &#10;
+    &lt;xsl:call-template name=&quot;staticAttributes&quot;&gt;&#10;
+      &lt;xsl:with-param name=&quot;header&quot; select=&quot;configurations/staticAttributes&quot;/&gt;&#10;
+    &lt;/xsl:call-template&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+  &#10;
+  &lt;xsl:template name=&quot;header&quot;&gt;&#10;
+    &lt;xsl:param name=&quot;node&quot;/&gt;  &#10;
+    &lt;xsl:for-each select=&quot;$node/*&quot;&gt;&#10;
+      &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+      &lt;xsl:value-of select=&quot;text()&quot;/&gt;&#10;
+      &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt; &#10;
+      &lt;xsl:if test=&quot;position() != last()&quot;&gt;&#10;
+        &lt;xsl:value-of select=&quot;$delimiter&quot;/&gt;&#10;
+      &lt;/xsl:if&gt;&#10;
+    &lt;/xsl:for-each&gt;&#10;
+    &lt;xsl:text&gt;&amp;#10;&lt;/xsl:text&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+    &#10;
+  &lt;xsl:template name=&quot;staticAttributes&quot;&gt;&#10;
+    &lt;xsl:param name=&quot;header&quot;/&gt;&#10;
+    &#10;
+    &lt;xsl:variable name=&quot;attrs&quot; select=&quot;.&quot;/&gt;&#10;
+    &lt;xsl:for-each select=&quot;$header/*&quot;&gt;&#10;
+      &lt;xsl:variable name=&quot;nameAttr&quot; select=&quot;text()&quot;/&gt; &#10;
+      &lt;xsl:if test=&quot;string-length($attrs/*[name(.)=$nameAttr]/text()) &amp;gt; 0 &#10;
+                      and count($attrs/*[name(.)=$nameAttr]/*/node()) = 0&quot;&gt;&#10;
+        &lt;xsl:variable name=&quot;value&quot; select=&quot;$attrs/*[name(.)=$nameAttr]/text()&quot;/&gt;&#10;
+        &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;xsl:value-of select=&quot;$value&quot;/&gt;&#10;
+        &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+      &lt;/xsl:if&gt;&#10;
+      &#10;
+      &lt;xsl:if test=&quot;string-length($attrs/*[name(.)=$nameAttr]/*/text()) &amp;gt; 0 &#10;
+                      and count($attrs/*[name(.)=$nameAttr]/*/node()) &amp;gt; 0&quot;&gt;&#10;
+        &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;xsl:for-each select=&quot;$attrs/*[name(.)=$nameAttr]/*&quot;&gt;&#10;
+          &lt;xsl:variable name=&quot;value&quot; select=&quot;text()&quot;/&gt;&#10;
+          &lt;xsl:text&gt;&lt;/xsl:text&gt;&#10;
+          &lt;xsl:value-of select=&quot;$value&quot;/&gt;&#10;
+          &lt;xsl:if test=&quot;position() != last()&quot;&gt;&#10;
+            &lt;xsl:value-of select=&quot;$delimiter&quot;/&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+        &lt;/xsl:for-each&gt;&#10;
+        &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+      &lt;/xsl:if&gt;&#10;
+      &#10;
+      &lt;xsl:if test=&quot;position() != last()&quot;&gt;&#10;
+        &lt;xsl:value-of select=&quot;$delimiter&quot;/&gt;&#10;
+      &lt;/xsl:if&gt;&#10;
+    &#10;
+    &lt;/xsl:for-each&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+  &#10;
+  &lt;xsl:template match=&quot;reportlet[@class='org.apache.syncope.core.provisioning.java.job.report.UserReportlet']&quot;&gt;&#10;
+    &#10;
+    &lt;xsl:call-template name=&quot;header&quot;&gt;&#10;
+      &lt;xsl:with-param name=&quot;node&quot; select=&quot;configurations/userAttributes&quot;/&gt;&#10;
+    &lt;/xsl:call-template&gt;&#10;
+    &lt;xsl:for-each select=&quot;user&quot;&gt;&#10;
+      &lt;xsl:call-template name=&quot;userAttributes&quot;&gt;&#10;
+        &lt;xsl:with-param name=&quot;header&quot; select=&quot;../configurations/userAttributes&quot;/&gt;&#10;
+      &lt;/xsl:call-template&gt;&#10;
+      &lt;xsl:text&gt;&amp;#10;&lt;/xsl:text&gt;&#10;
+    &lt;/xsl:for-each&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+    &#10;
+  &lt;xsl:template name=&quot;userAttributes&quot;&gt;&#10;
+    &lt;xsl:param name=&quot;header&quot;/&gt;&#10;
+  &#10;
+    &lt;xsl:variable name=&quot;attrs&quot; select=&quot;.&quot;/&gt;&#10;
+    &lt;xsl:for-each select=&quot;$header/*&quot;&gt;&#10;
+      &lt;xsl:variable name=&quot;nameAttr&quot; select=&quot;text()&quot;/&gt;&#10;
+      &lt;xsl:choose&gt;      &#10;
+        &lt;xsl:when test=&quot;count($attrs/@*[name()=$nameAttr]) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:variable name=&quot;userAttr&quot; select=&quot;$attrs/@*[name()=$nameAttr]&quot;/&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+          &lt;xsl:value-of select=&quot;$userAttr/.&quot;/&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:when test=&quot;string-length($attrs/*/*[@name=$nameAttr]/value/text()) &amp;gt; 0 &#10;
+                        and count($attrs/*/*[@name=$nameAttr]/node()) = 0&quot;&gt;&#10;
+          &lt;xsl:variable name=&quot;value&quot; select=&quot;$attrs/*/*[@name=$nameAttr]/value/text()&quot;/&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+          &lt;xsl:value-of select=&quot;$value&quot;/&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:when test=&quot;string-length($attrs/*/*[@name=$nameAttr]/value/text()) &amp;gt; 0 &#10;
+                        and count($attrs/*/*[@name=$nameAttr]/node()) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+          &lt;xsl:for-each select=&quot;$attrs/*/*[@name=$nameAttr]/*&quot;&gt;&#10;
+            &lt;xsl:variable name=&quot;value&quot; select=&quot;$attrs/*/*[@name=$nameAttr]/value/text()&quot;/&gt;&#10;
+            &lt;xsl:value-of select=&quot;$value&quot;/&gt;&#10;
+            &lt;xsl:if test=&quot;position() != last()&quot;&gt;&#10;
+              &lt;xsl:value-of select=&quot;$delimiter&quot;/&gt;&#10;
+            &lt;/xsl:if&gt;&#10;
+          &lt;/xsl:for-each&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:when test=&quot;name($attrs/*[name(.)=$nameAttr]/*[name(.)='membership']) &#10;
+                        and count($attrs/*[name(.)=$nameAttr]/node()) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;       &#10;
+          &lt;xsl:variable name=&quot;value&quot; select=&quot;@groupName&quot;/&gt;&#10;
+          &lt;xsl:for-each select=&quot;$attrs/*/membership&quot;&gt;&#10;
+            &lt;xsl:variable name=&quot;value&quot; select=&quot;@groupName&quot;/&gt;&#10;
+            &lt;xsl:value-of select=&quot;$value&quot;/&gt;&#10;
+            &lt;xsl:if test=&quot;position() != last()&quot;&gt;&#10;
+              &lt;xsl:value-of select=&quot;$delimiter&quot;/&gt;&#10;
+            &lt;/xsl:if&gt;&#10;
+          &lt;/xsl:for-each&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:when test=&quot;name($attrs/*[name(.)=$nameAttr]/*[name(.)='resource']) &#10;
+                        and count($attrs/*[name(.)=$nameAttr]/node()) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+          &lt;xsl:variable name=&quot;value&quot; select=&quot;@name&quot;/&gt;&#10;
+          &lt;xsl:for-each select=&quot;$attrs/*/resource&quot;&gt;&#10;
+            &lt;xsl:variable name=&quot;value&quot; select=&quot;@name&quot;/&gt;&#10;
+            &lt;xsl:value-of select=&quot;$value&quot;/&gt;&#10;
+            &lt;xsl:if test=&quot;position() != last()&quot;&gt;&#10;
+              &lt;xsl:value-of select=&quot;$delimiter&quot;/&gt;&#10;
+            &lt;/xsl:if&gt;&#10;
+          &lt;/xsl:for-each&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;xsl:text&gt;&quot;&quot;&lt;/xsl:text&gt; &#10;
+        &lt;/xsl:otherwise&gt;  &#10;
+      &lt;/xsl:choose&gt;&#10;
+      &lt;xsl:if test=&quot;position() != last()&quot;&gt;&#10;
+        &lt;xsl:value-of select=&quot;$delimiter&quot;/&gt;&#10;
+      &lt;/xsl:if&gt;  &#10;
+    &lt;/xsl:for-each&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+  &#10;
+  &lt;xsl:template match=&quot;reportlet[@class='org.apache.syncope.core.provisioning.java.job.report.GroupReportlet']&quot;&gt;&#10;
+    &#10;
+    &lt;xsl:call-template name=&quot;header&quot;&gt;&#10;
+      &lt;xsl:with-param name=&quot;node&quot; select=&quot;configurations/groupAttributes&quot;/&gt;&#10;
+    &lt;/xsl:call-template&gt;&#10;
+    &lt;xsl:for-each select=&quot;group&quot;&gt;&#10;
+      &lt;xsl:call-template name=&quot;groupAttributes&quot;&gt;&#10;
+        &lt;xsl:with-param name=&quot;header&quot; select=&quot;../configurations/groupAttributes&quot;/&gt;&#10;
+        &lt;xsl:with-param name=&quot;attrs&quot; select=&quot;.&quot;/&gt;&#10;
+      &lt;/xsl:call-template&gt;&#10;
+      &lt;xsl:text&gt;&amp;#10;&lt;/xsl:text&gt;&#10;
+    &lt;/xsl:for-each&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+    &#10;
+  &lt;xsl:template name=&quot;groupAttributes&quot;&gt;&#10;
+    &lt;xsl:param name=&quot;header&quot;/&gt;&#10;
+    &lt;xsl:param name=&quot;attrs&quot;/&gt;&#10;
+    &#10;
+    &lt;xsl:for-each select=&quot;$header/*&quot;&gt;&#10;
+      &lt;xsl:variable name=&quot;nameAttr&quot; select=&quot;text()&quot;/&gt;&#10;
+      &#10;
+      &lt;xsl:choose&gt; &#10;
+        &lt;xsl:when test=&quot;string-length($attrs/@*[name()=$nameAttr]) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:variable name=&quot;groupAttr&quot; select=&quot;$attrs/@*[name()=$nameAttr]&quot;/&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+          &lt;xsl:value-of select=&quot;$groupAttr/.&quot;/&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:when test=&quot;name($attrs/*[name(.)=$nameAttr]/*[name(.)='resource']) &#10;
+                        and count($attrs/*[name(.)=$nameAttr]/node()) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;       &#10;
+          &lt;xsl:for-each select=&quot;$attrs/*/resource&quot;&gt;&#10;
+            &lt;xsl:variable name=&quot;value&quot; select=&quot;@name&quot;/&gt;&#10;
+            &lt;xsl:value-of select=&quot;$value&quot;/&gt;&#10;
+            &lt;xsl:if test=&quot;position() != last()&quot;&gt;&#10;
+              &lt;xsl:value-of select=&quot;$delimiter&quot;/&gt;&#10;
+            &lt;/xsl:if&gt;&#10;
+          &lt;/xsl:for-each&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:when test=&quot;name($attrs/*[name(.)=$nameAttr]/*[name(.)='user']) &#10;
+                        and count($attrs/*[name(.)=$nameAttr]/node()) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;       &#10;
+          &lt;xsl:for-each select=&quot;$attrs/*/user&quot;&gt;&#10;
+            &lt;xsl:variable name=&quot;value&quot; select=&quot;@userUsername&quot;/&gt;&#10;
+            &lt;xsl:value-of select=&quot;$value&quot;/&gt;&#10;
+            &lt;xsl:if test=&quot;position() != last()&quot;&gt;&#10;
+              &lt;xsl:value-of select=&quot;$delimiter&quot;/&gt;&#10;
+            &lt;/xsl:if&gt;&#10;
+          &lt;/xsl:for-each&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+          &lt;xsl:if test=&quot;string-length($attrs/*/*[@name=$nameAttr]/value/text()) &amp;gt; 0&quot;&gt; &#10;
+            &lt;xsl:variable name=&quot;value&quot; select=&quot;$attrs/*/*[@name=$nameAttr]/value/text()&quot;/&gt;&#10;
+            &lt;xsl:value-of select=&quot;$value&quot;/&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+          &lt;xsl:text&gt;&quot;&lt;/xsl:text&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &lt;xsl:if test=&quot;position() != last()&quot;&gt;&#10;
+        &lt;xsl:value-of select=&quot;$delimiter&quot;/&gt;&#10;
+      &lt;/xsl:if&gt;&#10;
+    &#10;
+    &lt;/xsl:for-each&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+&lt;/xsl:stylesheet&gt;&#10;"
+                  foTemplate="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;
+&lt;xsl:stylesheet xmlns:xsl=&quot;http://www.w3.org/1999/XSL/Transform&quot;&#10;
+                xmlns:fo=&quot;http://www.w3.org/1999/XSL/Format&quot;&#10;
+                version=&quot;1.0&quot;&gt;&#10;
+&#10;
+  &lt;xsl:param name=&quot;status&quot;/&gt;&#10;
+  &lt;xsl:param name=&quot;message&quot;/&gt;&#10;
+  &lt;xsl:param name=&quot;start&quot;/&gt;&#10;
+  &lt;xsl:param name=&quot;end&quot;/&gt;&#10;
+  &#10;
+  &lt;xsl:template match=&quot;/&quot;&gt;&#10;
+    &lt;fo:root xmlns:fo=&quot;http://www.w3.org/1999/XSL/Format&quot; font-family=&quot;Helvetica&quot; font-size=&quot;10pt&quot;&gt;&#10;
+      &#10;
+      &lt;!-- defines the layout master --&gt;&#10;
+      &lt;fo:layout-master-set&gt;&#10;
+        &lt;fo:simple-page-master master-name=&quot;first&quot; page-height=&quot;29.7cm&quot; page-width=&quot;21cm&quot; &#10;
+                               margin-top=&quot;1cm&quot; margin-bottom=&quot;2cm&quot; margin-left=&quot;2.5cm&quot; margin-right=&quot;2.5cm&quot;&gt;&#10;
+          &lt;fo:region-body margin-top=&quot;1cm&quot;/&gt;&#10;
+          &lt;fo:region-before extent=&quot;1cm&quot;/&gt;&#10;
+          &lt;fo:region-after extent=&quot;1.5cm&quot;/&gt;&#10;
+        &lt;/fo:simple-page-master&gt;&#10;
+      &lt;/fo:layout-master-set&gt;&#10;
+&#10;
+      &lt;!-- starts actual layout --&gt;&#10;
+      &lt;fo:page-sequence master-reference=&quot;first&quot;&gt;&#10;
+        &#10;
+        &lt;fo:flow flow-name=&quot;xsl-region-body&quot;&gt;&#10;
+          &lt;fo:block font-size=&quot;24pt&quot; font-weight=&quot;bold&quot; text-align=&quot;center&quot; space-after=&quot;1cm&quot;&gt;&#10;
+            Apache Syncope Report - &lt;xsl:value-of select=&quot;report/@name&quot;/&gt;&#10;
+          &lt;/fo:block&gt;&#10;
+&#10;
+          &lt;fo:table table-layout=&quot;fixed&quot; border-width=&quot;0.5mm&quot; border-style=&quot;solid&quot; width=&quot;100%&quot; space-after=&quot;1cm&quot;&gt;&#10;
+            &lt;fo:table-column column-width=&quot;proportional-column-width(1)&quot;/&gt;&#10;
+            &lt;fo:table-column column-width=&quot;proportional-column-width(1)&quot;/&gt;&#10;
+            &lt;fo:table-body&gt;&#10;
+              &lt;fo:table-row&gt;&#10;
+                &lt;fo:table-cell&gt;&#10;
+                  &lt;fo:block font-size=&quot;18pt&quot; font-weight=&quot;bold&quot;&gt;Report Name:&lt;/fo:block&gt;&#10;
+                &lt;/fo:table-cell&gt;&#10;
+                &lt;fo:table-cell&gt;&#10;
+                  &lt;fo:block font-size=&quot;18pt&quot; font-weight=&quot;bold&quot;&gt;&#10;
+                    &lt;xsl:value-of select=&quot;report/@name&quot;/&gt;&#10;
+                  &lt;/fo:block&gt;&#10;
+                &lt;/fo:table-cell&gt;&#10;
+              &lt;/fo:table-row&gt;&#10;
+              &lt;fo:table-row&gt;&#10;
+                &lt;fo:table-cell&gt;&#10;
+                  &lt;fo:block font-size=&quot;18pt&quot; font-weight=&quot;bold&quot;&gt;Start Date:&lt;/fo:block&gt;&#10;
+                &lt;/fo:table-cell&gt;&#10;
+                &lt;fo:table-cell&gt;&#10;
+                  &lt;fo:block font-size=&quot;18pt&quot; font-weight=&quot;bold&quot;&gt;&#10;
+                    &lt;xsl:value-of select=&quot;$start&quot;/&gt;&#10;
+                  &lt;/fo:block&gt;&#10;
+                &lt;/fo:table-cell&gt;&#10;
+              &lt;/fo:table-row&gt;&#10;
+              &lt;fo:table-row&gt;&#10;
+                &lt;fo:table-cell&gt;&#10;
+                  &lt;fo:block font-size=&quot;18pt&quot; font-weight=&quot;bold&quot;&gt;End Date:&lt;/fo:block&gt;&#10;
+                &lt;/fo:table-cell&gt;&#10;
+                &lt;fo:table-cell&gt;&#10;
+                  &lt;fo:block font-size=&quot;18pt&quot; font-weight=&quot;bold&quot;&gt;&#10;
+                    &lt;xsl:value-of select=&quot;$end&quot;/&gt;&#10;
+                  &lt;/fo:block&gt;&#10;
+                &lt;/fo:table-cell&gt;&#10;
+              &lt;/fo:table-row&gt;&#10;
+            &lt;/fo:table-body&gt;&#10;
+          &lt;/fo:table&gt;&#10;
+&#10;
+          &lt;xsl:apply-templates/&gt;&#10;
+        &lt;/fo:flow&gt;&#10;
+      &lt;/fo:page-sequence&gt;&#10;
+    &lt;/fo:root&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+&#10;
+  &lt;xsl:template match=&quot;reportlet[@class='org.apache.syncope.core.provisioning.java.job.report.StaticReportlet']&quot;&gt;&#10;
+&#10;
+    &lt;fo:block font-size=&quot;14pt&quot; font-weight=&quot;bold&quot; space-after=&quot;0.5cm&quot;&gt;Reportlet: &#10;
+      &lt;xsl:value-of select=&quot;@name&quot;/&gt;&#10;
+    &lt;/fo:block&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(string/text()) &amp;gt; 0&quot;&gt;&#10;
+      &lt;fo:block font-size=&quot;11pt&quot;&gt;String value: &#10;
+        &lt;xsl:value-of select=&quot;string/text()&quot;/&gt;&#10;
+      &lt;/fo:block&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(long/text()) &amp;gt; 0&quot;&gt;&#10;
+      &lt;fo:block font-size=&quot;11pt&quot;&gt;Long value: &#10;
+        &lt;xsl:value-of select=&quot;long/text()&quot;/&gt;&#10;
+      &lt;/fo:block&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(double/text()) &amp;gt; 0&quot;&gt;&#10;
+      &lt;fo:block font-size=&quot;11pt&quot;&gt;Double value: &#10;
+        &lt;xsl:value-of select=&quot;double/text()&quot;/&gt;&#10;
+      &lt;/fo:block&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(date/text()) &amp;gt; 0&quot;&gt;&#10;
+      &lt;fo:block font-size=&quot;11pt&quot;&gt;Date value: &#10;
+        &lt;xsl:value-of select=&quot;date/text()&quot;/&gt;&#10;
+      &lt;/fo:block&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(enum/text()) &amp;gt; 0&quot;&gt;&#10;
+      &lt;fo:block font-size=&quot;11pt&quot;&gt;Enum value: &#10;
+        &lt;xsl:value-of select=&quot;enum/text()&quot;/&gt;&#10;
+      &lt;/fo:block&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+&#10;
+    &lt;xsl:if test=&quot;string-length(list) &amp;gt; 0&quot;&gt;&#10;
+      &lt;fo:block font-size=&quot;11pt&quot;&gt;List values:&lt;/fo:block&gt;&#10;
+            &#10;
+      &lt;fo:list-block provisional-label-separation=&quot;4mm&quot; provisional-distance-between-starts=&quot;2mm&quot;&gt;&#10;
+        &lt;xsl:for-each select=&quot;list/string&quot;&gt;&#10;
+          &lt;xsl:if test=&quot;string-length(string/text()) &amp;gt; 0&quot;&gt;&#10;
+            &lt;fo:list-item&gt;&#10;
+              &lt;fo:list-item-label end-indent=&quot;label-end()&quot;&gt;&#10;
+                &lt;fo:block&gt;&#x2022;&lt;/fo:block&gt;&#10;
+              &lt;/fo:list-item-label&gt;&#10;
+              &lt;fo:list-item-body start-indent=&quot;body-start()&quot;&gt;&#10;
+                &lt;fo:block&gt;&#10;
+                  &lt;xsl:value-of select=&quot;text()&quot;/&gt;&#10;
+                &lt;/fo:block&gt;&#10;
+              &lt;/fo:list-item-body&gt;&#10;
+            &lt;/fo:list-item&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+        &lt;/xsl:for-each&gt;&#10;
+      &lt;/fo:list-block&gt;&#10;
+    &lt;/xsl:if&gt;&#10;
+        &#10;
+  &lt;/xsl:template&gt;&#10;
+  &#10;
+  &lt;xsl:template match=&quot;reportlet[@class='org.apache.syncope.core.provisioning.java.job.report.UserReportlet']&quot;&gt;&#10;
+   &#10;
+    &lt;fo:block font-size=&quot;16pt&quot; font-weight=&quot;bold&quot; space-after=&quot;0.5cm&quot; space-before=&quot;5mm&quot;&gt;Reportlet: &lt;xsl:value-of select=&quot;@name&quot;/&gt;&lt;/fo:block&gt;&#10;
+        &#10;
+    &lt;xsl:for-each select=&quot;user&quot;&gt;&#10;
+      &lt;fo:block font-size=&quot;14pt&quot; font-weight=&quot;bold&quot; space-before=&quot;15mm&quot; space-after=&quot;5mm&quot; background-color=&quot;(#8888ff)&quot;&gt;User &lt;xsl:value-of select=&quot;@username&quot;/&gt;&lt;/fo:block&gt;&#10;
+      &lt;fo:table table-layout=&quot;fixed&quot; space-after=&quot;7mm&quot;&gt;&#10;
+        &lt;fo:table-column/&gt;&#10;
+        &lt;fo:table-column/&gt;&#10;
+        &lt;fo:table-body&gt;&#10;
+          &lt;fo:table-row background-color=&quot;(#ccccff)&quot;&gt;&#10;
+            &lt;fo:table-cell&gt;&#10;
+              &lt;fo:block&gt;Status:&lt;/fo:block&gt;&#10;
+            &lt;/fo:table-cell&gt;&#10;
+            &lt;fo:table-cell&gt;&#10;
+              &lt;fo:block font-style=&quot;italic&quot;&gt;&#10;
+                &lt;xsl:value-of select=&quot;@status&quot;/&gt;&#10;
+              &lt;/fo:block&gt;&#10;
+            &lt;/fo:table-cell&gt;&#10;
+          &lt;/fo:table-row&gt;&#10;
+          &lt;xsl:if test=&quot;string-length(@creationDate) &amp;gt; 0&quot;&gt;&#10;
+            &lt;fo:table-row background-color=&quot;(#ccccff)&quot;&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block&gt;Creation Date:&lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block font-style=&quot;italic&quot;&gt;&#10;
+                  &lt;xsl:value-of select=&quot;@creationDate&quot;/&gt;&#10;
+                &lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+            &lt;/fo:table-row&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+          &lt;xsl:if test=&quot;string-length(@lastLoginDate) &amp;gt; 0&quot;&gt;&#10;
+            &lt;fo:table-row background-color=&quot;(#ccccff)&quot;&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block&gt;Last Login Date:&lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block font-style=&quot;italic&quot;&gt;&#10;
+                  &lt;xsl:value-of select=&quot;@lastLoginDate&quot;/&gt;&#10;
+                &lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+            &lt;/fo:table-row&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+          &lt;xsl:if test=&quot;string-length(@changePwdDate) &amp;gt; 0&quot;&gt;&#10;
+            &lt;fo:table-row background-color=&quot;(#ccccff)&quot;&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block&gt;Change Password Date:&lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block font-style=&quot;italic&quot;&gt;&#10;
+                  &lt;xsl:value-of select=&quot;@changePwdDate&quot;/&gt;&#10;
+                &lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+            &lt;/fo:table-row&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+          &lt;xsl:if test=&quot;string-length(@passwordHistorySize) &amp;gt; 0&quot;&gt;&#10;
+            &lt;fo:table-row background-color=&quot;(#ccccff)&quot;&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block&gt;Password History Size:&lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block font-style=&quot;italic&quot;&gt;&#10;
+                  &lt;xsl:value-of select=&quot;@passwordHistorySize&quot;/&gt;&#10;
+                &lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+            &lt;/fo:table-row&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+          &lt;xsl:if test=&quot;string-length(@failedLoginCount) &amp;gt; 0&quot;&gt;&#10;
+            &lt;fo:table-row background-color=&quot;(#ccccff)&quot;&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block&gt;Number of Failed Login Attempts:&lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block font-style=&quot;italic&quot;&gt;&#10;
+                  &lt;xsl:value-of select=&quot;@failedLoginCount&quot;/&gt;&#10;
+                &lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+            &lt;/fo:table-row&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+        &lt;/fo:table-body&gt;&#10;
+      &lt;/fo:table&gt;&#10;
+      &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+        &lt;xsl:with-param name=&quot;label&quot;&gt;Attributes&lt;/xsl:with-param&gt;&#10;
+        &lt;xsl:with-param name=&quot;node&quot; select=&quot;attributes/attribute&quot;/&gt;&#10;
+      &lt;/xsl:call-template&gt;&#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(derivedAttributes/derivedAttribute) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+            &lt;xsl:with-param name=&quot;label&quot;&gt;Derived Attributes&lt;/xsl:with-param&gt;&#10;
+            &lt;xsl:with-param name=&quot;node&quot; select=&quot;derivedAttributes/derivedAttribute&quot;/&gt;&#10;
+          &lt;/xsl:call-template&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;fo:block color=&quot;red&quot; font-size=&quot;9pt&quot; space-after=&quot;3mm&quot;&gt;THIS USER HASN'T ANY DERIVED ATTRIBUTE&lt;/fo:block&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(virtualAttributes/virtualAttribute) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+            &lt;xsl:with-param name=&quot;label&quot;&gt;Virtual Attributes&lt;/xsl:with-param&gt;&#10;
+            &lt;xsl:with-param name=&quot;node&quot; select=&quot;virtualAttributes/virtualAttribute&quot;/&gt;&#10;
+          &lt;/xsl:call-template&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;fo:block color=&quot;red&quot; font-size=&quot;9pt&quot; space-after=&quot;3mm&quot;&gt;THIS USER HASN'T ANY VIRTUAL ATTRIBUTE&lt;/fo:block&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(memberships/membership) &amp;gt; 0&quot;&gt;&#10;
+          &lt;fo:block font-size=&quot;11pt&quot; font-weight=&quot;bold&quot;&gt;Memberships&lt;/fo:block&gt;&#10;
+          &lt;xsl:for-each select=&quot;memberships/membership&quot;&gt;&#10;
+            &lt;fo:block font-size=&quot;10pt&quot; font-weight=&quot;bold&quot; space-before=&quot;2mm&quot;&gt;Group: &lt;xsl:value-of select=&quot;@groupName&quot;/&gt;(&lt;xsl:value-of select=&quot;@groupId&quot;/&gt;)&lt;/fo:block&gt;&#10;
+            &lt;fo:block start-indent=&quot;1cm&quot; space-before=&quot;3mm&quot; space-after=&quot;0.5cm&quot;&gt;&#10;
+              &lt;xsl:choose&gt;&#10;
+                &lt;xsl:when test=&quot;string-length(attributes/attribute) &amp;gt; 0&quot;&gt;&#10;
+                  &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+                    &lt;xsl:with-param name=&quot;label&quot;&gt;Attributes&lt;/xsl:with-param&gt;&#10;
+                    &lt;xsl:with-param name=&quot;node&quot; select=&quot;attributes/attribute&quot;/&gt;&#10;
+                  &lt;/xsl:call-template&gt;&#10;
+                &lt;/xsl:when&gt;&#10;
+                &lt;xsl:otherwise&gt;&#10;
+                  &lt;fo:block color=&quot;red&quot; font-size=&quot;8pt&quot; space-after=&quot;2mm&quot;&gt;THIS GROUP HASN'T ANY ATTRIBUTE&lt;/fo:block&gt;&#10;
+                &lt;/xsl:otherwise&gt;&#10;
+              &lt;/xsl:choose&gt;&#10;
+              &lt;xsl:choose&gt;&#10;
+                &lt;xsl:when test=&quot;string-length(derivedAttributes/derivedAttribute) &amp;gt; 0&quot;&gt;&#10;
+                  &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+                    &lt;xsl:with-param name=&quot;label&quot;&gt;Derived Attributes&lt;/xsl:with-param&gt;&#10;
+                    &lt;xsl:with-param name=&quot;node&quot; select=&quot;derivedAttributes/derivedAttribute&quot;/&gt;&#10;
+                  &lt;/xsl:call-template&gt;&#10;
+                &lt;/xsl:when&gt;&#10;
+                &lt;xsl:otherwise&gt;&#10;
+                  &lt;fo:block color=&quot;red&quot; font-size=&quot;8pt&quot; space-after=&quot;2mm&quot;&gt;THIS GROUP HASN'T ANY DERIVED ATTRIBUTE&lt;/fo:block&gt;&#10;
+                &lt;/xsl:otherwise&gt;&#10;
+              &lt;/xsl:choose&gt;&#10;
+              &lt;xsl:choose&gt;&#10;
+                &lt;xsl:when test=&quot;string-length(virtualAttributes/virtualAttribute) &amp;gt; 0&quot;&gt;&#10;
+                  &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+                    &lt;xsl:with-param name=&quot;label&quot;&gt;Virtual Attributes&lt;/xsl:with-param&gt;&#10;
+                    &lt;xsl:with-param name=&quot;node&quot; select=&quot;virtualAttributes/virtualAttribute&quot;/&gt;&#10;
+                  &lt;/xsl:call-template&gt;&#10;
+                &lt;/xsl:when&gt;&#10;
+                &lt;xsl:otherwise&gt;&#10;
+                  &lt;fo:block color=&quot;red&quot; font-size=&quot;8pt&quot; space-after=&quot;2mm&quot;&gt;THIS GROUP HASN'T ANY VIRTUAL ATTRIBUTE&lt;/fo:block&gt;&#10;
+                &lt;/xsl:otherwise&gt;&#10;
+              &lt;/xsl:choose&gt;&#10;
+              &lt;!-- 'groupResources&quot; is defined in groupReportlet2fo.xsl --&gt;&#10;
+              &lt;xsl:call-template name=&quot;groupResources&quot;&gt;&#10;
+                &lt;xsl:with-param name=&quot;node&quot; select=&quot;resources/resource&quot;/&gt;&#10;
+              &lt;/xsl:call-template&gt;&#10;
+            &lt;/fo:block&gt;&#10;
+          &lt;/xsl:for-each&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;fo:block color=&quot;red&quot; font-size=&quot;9pt&quot; space-after=&quot;3mm&quot;&gt;THIS USER HASN'T BEEN ASSIGNED TO ANY GROUP&lt;/fo:block&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &lt;xsl:call-template name=&quot;resources&quot;&gt;&#10;
+        &lt;xsl:with-param name=&quot;node&quot; select=&quot;resources/resource&quot;/&gt;&#10;
+      &lt;/xsl:call-template&gt;&#10;
+    &lt;/xsl:for-each&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+  &#10;
+  &lt;xsl:template match=&quot;reportlet[@class='org.apache.syncope.core.provisioning.java.job.report.GroupReportlet']&quot;&gt;&#10;
+   &#10;
+    &lt;fo:block font-size=&quot;16pt&quot; font-weight=&quot;bold&quot; space-after=&quot;0.5cm&quot; space-before=&quot;5mm&quot;&gt;Reportlet: &lt;xsl:value-of select=&quot;@name&quot;/&gt;&lt;/fo:block&gt;&#10;
+        &#10;
+    &lt;xsl:for-each select=&quot;group&quot;&gt;&#10;
+      &lt;fo:block font-size=&quot;14pt&quot; font-weight=&quot;bold&quot; space-before=&quot;15mm&quot; space-after=&quot;5mm&quot; background-color=&quot;(#8888ff)&quot;&gt;Group &lt;xsl:value-of select=&quot;@name&quot;/&gt;&lt;/fo:block&gt;&#10;
+      &lt;fo:table table-layout=&quot;fixed&quot; space-after=&quot;7mm&quot;&gt;&#10;
+        &lt;fo:table-column/&gt;&#10;
+        &lt;fo:table-column/&gt;&#10;
+        &lt;fo:table-body&gt;&#10;
+          &lt;fo:table-row background-color=&quot;(#ccccff)&quot;&gt;&#10;
+            &lt;fo:table-cell&gt;&#10;
+              &lt;fo:block&gt;Id:&lt;/fo:block&gt;&#10;
+            &lt;/fo:table-cell&gt;&#10;
+            &lt;fo:table-cell&gt;&#10;
+              &lt;fo:block font-style=&quot;italic&quot;&gt;&#10;
+                &lt;xsl:value-of select=&quot;@id&quot;/&gt;&#10;
+              &lt;/fo:block&gt;&#10;
+            &lt;/fo:table-cell&gt;&#10;
+          &lt;/fo:table-row&gt;&#10;
+          &lt;xsl:if test=&quot;@groupOwner != 'null'&quot;&gt;&#10;
+            &lt;fo:table-row background-color=&quot;(#ccccff)&quot;&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block&gt;Group Owner:&lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block font-style=&quot;italic&quot;&gt;&#10;
+                  &lt;xsl:value-of select=&quot;@groupOwner&quot;/&gt;&#10;
+                &lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+            &lt;/fo:table-row&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+          &lt;xsl:if test=&quot;@userOwner != 'null'&quot;&gt;&#10;
+            &lt;fo:table-row background-color=&quot;(#ccccff)&quot;&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block&gt;Last Login Date:&lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block font-style=&quot;italic&quot;&gt;&#10;
+                  &lt;xsl:value-of select=&quot;@userOwner&quot;/&gt;&#10;
+                &lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+            &lt;/fo:table-row&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+        &lt;/fo:table-body&gt;&#10;
+      &lt;/fo:table&gt;&#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(attributes/attribute) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+            &lt;xsl:with-param name=&quot;label&quot;&gt;Attributes&lt;/xsl:with-param&gt;&#10;
+            &lt;xsl:with-param name=&quot;node&quot; select=&quot;attributes/attribute&quot;/&gt;&#10;
+          &lt;/xsl:call-template&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;fo:block color=&quot;red&quot; font-size=&quot;9pt&quot; space-after=&quot;3mm&quot;&gt;THIS GROUP HASN'T ANY ATTRIBUTE&lt;/fo:block&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(derivedAttributes/derivedAttribute) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+            &lt;xsl:with-param name=&quot;label&quot;&gt;Derived Attributes&lt;/xsl:with-param&gt;&#10;
+            &lt;xsl:with-param name=&quot;node&quot; select=&quot;derivedAttributes/derivedAttribute&quot;/&gt;&#10;
+          &lt;/xsl:call-template&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;fo:block color=&quot;red&quot; font-size=&quot;9pt&quot; space-after=&quot;3mm&quot;&gt;THIS GROUP HASN'T ANY DERIVED ATTRIBUTE&lt;/fo:block&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;string-length(virtualAttributes/virtualAttribute) &amp;gt; 0&quot;&gt;&#10;
+          &lt;xsl:call-template name=&quot;attributes&quot;&gt;&#10;
+            &lt;xsl:with-param name=&quot;label&quot;&gt;Virtual Attributes&lt;/xsl:with-param&gt;&#10;
+            &lt;xsl:with-param name=&quot;node&quot; select=&quot;virtualAttributes/virtualAttribute&quot;/&gt;&#10;
+          &lt;/xsl:call-template&gt;&#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;fo:block color=&quot;red&quot; font-size=&quot;9pt&quot; space-after=&quot;3mm&quot;&gt;THIS GROUP HASN'T ANY VIRTUAL ATTRIBUTE&lt;/fo:block&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &#10;
+      &lt;xsl:choose&gt;&#10;
+        &lt;xsl:when test=&quot;users/user&quot;&gt;&#10;
+          &lt;fo:block font-size=&quot;11pt&quot; font-weight=&quot;bold&quot;&gt;Users&lt;/fo:block&gt;&#10;
+          &lt;xsl:for-each select=&quot;users/user&quot;&gt;&#10;
+            &lt;fo:block background-color=&quot;(#ccccff)&quot; font-size=&quot;9pt&quot; font-weight=&quot;bold&quot; space-before=&quot;4mm&quot;&gt;User: &lt;xsl:value-of select=&quot;@userUsername&quot;/&gt; (Id: &lt;xsl:value-of select=&quot;@userId&quot;/&gt;)&lt;/fo:block&gt;&#10;
+                 &#10;
+          &lt;/xsl:for-each&gt; &#10;
+        &lt;/xsl:when&gt;&#10;
+        &lt;xsl:otherwise&gt;&#10;
+          &lt;fo:block color=&quot;red&quot; font-size=&quot;9pt&quot; space-after=&quot;3mm&quot;&gt;THIS GROUP HASN'T ANY USER ASSIGNED TO&lt;/fo:block&gt;&#10;
+        &lt;/xsl:otherwise&gt;&#10;
+      &lt;/xsl:choose&gt;&#10;
+      &lt;xsl:call-template name=&quot;groupResources&quot;&gt;&#10;
+        &lt;xsl:with-param name=&quot;node&quot; select=&quot;resources/resource&quot;/&gt;&#10;
+      &lt;/xsl:call-template&gt;&#10;
+    &lt;/xsl:for-each&gt;&#10;
+&#10;
+  &lt;/xsl:template&gt;&#10;
+  &#10;
+  &lt;xsl:template name=&quot;attributes&quot;&gt;&#10;
+    &lt;xsl:param name=&quot;label&quot;/&gt;&#10;
+    &lt;xsl:param name=&quot;node&quot;/&gt;&#10;
+    &lt;fo:block font-size=&quot;11pt&quot; font-weight=&quot;bold&quot; space-after=&quot;2mm&quot;&gt;&#10;
+      &lt;xsl:value-of select=&quot;$label&quot;/&gt;&#10;
+    &lt;/fo:block&gt;&#10;
+    &lt;fo:table table-layout=&quot;fixed&quot; space-after=&quot;7mm&quot;&gt;&#10;
+      &lt;fo:table-column/&gt;&#10;
+      &lt;fo:table-column/&gt;&#10;
+      &lt;fo:table-header&gt;&#10;
+        &lt;fo:table-row height=&quot;7mm&quot; background-color=&quot;(#ccccba)&quot;&gt;&#10;
+          &lt;fo:table-cell&gt;&#10;
+            &lt;fo:block font-weight=&quot;bold&quot;&gt;Schema name&lt;/fo:block&gt;&#10;
+          &lt;/fo:table-cell&gt;&#10;
+          &lt;fo:table-cell&gt;&#10;
+            &lt;fo:block font-weight=&quot;bold&quot;&gt;Value(s)&lt;/fo:block&gt;&#10;
+          &lt;/fo:table-cell&gt;&#10;
+        &lt;/fo:table-row&gt;&#10;
+      &lt;/fo:table-header&gt;&#10;
+      &lt;fo:table-body&gt;&#10;
+        &lt;xsl:for-each select=&quot;$node&quot;&gt;&#10;
+          &lt;xsl:if test=&quot;string-length(value/text()) &amp;gt; 0&quot;&gt;&#10;
+            &lt;fo:table-row height=&quot;4mm&quot; background-color=&quot;(#ccccff)&quot;&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;fo:block&gt;&#10;
+                  &lt;xsl:value-of select=&quot;@name&quot;/&gt;&#10;
+                &lt;/fo:block&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+              &lt;fo:table-cell&gt;&#10;
+                &lt;xsl:for-each select=&quot;value&quot;&gt;&#10;
+                  &lt;fo:block&gt;&lt;/fo:block&gt;&#10;
+                  &lt;fo:block font-style=&quot;italic&quot;&gt;&#10;
+                    &lt;xsl:value-of select=&quot;text()&quot;/&gt;&#10;
+                  &lt;/fo:block&gt;&#10;
+                &lt;/xsl:for-each&gt;&#10;
+              &lt;/fo:table-cell&gt;&#10;
+            &lt;/fo:table-row&gt;&#10;
+          &lt;/xsl:if&gt;&#10;
+          &lt;fo:table-row&gt;&#10;
+            &lt;fo:table-cell&gt;&#10;
+              &lt;fo:block&gt;&lt;/fo:block&gt;&#10;
+            &lt;/fo:table-cell&gt;&#10;
+            &lt;fo:table-cell&gt;&#10;
+              &lt;fo:block&gt;&lt;/fo:block&gt;&#10;
+            &lt;/fo:table-cell&gt;&#10;
+          &lt;/fo:table-row&gt;&#10;
+        &lt;/xsl:for-each&gt;&#10;
+      &lt;/fo:table-body&gt;&#10;
+    &lt;/fo:table&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+  &#10;
+  &lt;xsl:template name=&quot;resources&quot;&gt;&#10;
+    &lt;xsl:param name=&quot;node&quot;/&gt;&#10;
+    &lt;fo:block font-size=&quot;11pt&quot; font-weight=&quot;bold&quot; space-after=&quot;3mm&quot;&gt;Resources&lt;/fo:block&gt;&#10;
+    &lt;xsl:for-each select=&quot;$node&quot;&gt;&#10;
+      &lt;fo:block&gt;&lt;/fo:block&gt; &lt;!--            &lt;fo:block&gt;&#x2022;&lt;/fo:block&gt;--&gt;&#10;
+      &lt;fo:block background-color=&quot;(#ccccff)&quot;&gt;&#10;
+        &lt;xsl:value-of select=&quot;@name&quot;/&gt;&#10;
+      &lt;/fo:block&gt;&#10;
+    &lt;/xsl:for-each&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+&#10;
+  &lt;xsl:template name=&quot;groupResources&quot;&gt;&#10;
+    &lt;xsl:param name=&quot;node&quot;/&gt;&#10;
+    &lt;fo:block font-size=&quot;11pt&quot; font-weight=&quot;bold&quot; space-after=&quot;3mm&quot; space-before=&quot;5mm&quot;&gt;Group Resources&lt;/fo:block&gt;&#10;
+    &lt;xsl:for-each select=&quot;$node&quot;&gt;&#10;
+      &lt;fo:block&gt;&lt;/fo:block&gt; &lt;!--            &lt;fo:block&gt;&#x2022;&lt;/fo:block&gt;--&gt;&#10;
+      &lt;fo:block background-color=&quot;(#ccccff)&quot;&gt;&#10;
+        &lt;xsl:value-of select=&quot;@name&quot;/&gt;&#10;
+      &lt;/fo:block&gt;&#10;
+    &lt;/xsl:for-each&gt;&#10;
+  &lt;/xsl:template&gt;&#10;
+&#10;
+&lt;/xsl:stylesheet&gt;&#10;"/>
+  
+  <Report id="0062ea9c-924d-4ecf-9961-4492a8cc6d1b" name="test" active="1" template_id="sample"/>
+  <Implementation id="UserReportletConf" type="REPORTLET" engine="JAVA"
+                  body='{"@class":"org.apache.syncope.common.lib.report.UserReportletConf","name":"testUserReportlet","matchingCond":null,"plainAttrs":["fullname","gender"],"derAttrs":["cn"],"virAttrs":["virtualdata"],"features":["key","username","status","creationDate","lastLoginDate","changePwdDate","passwordHistorySize","failedLoginCount","memberships","resources"]}'/>
+  <ReportReportlet report_id="0062ea9c-924d-4ecf-9961-4492a8cc6d1b" implementation_id="UserReportletConf"/>
+  <ReportExec report_id="0062ea9c-924d-4ecf-9961-4492a8cc6d1b" id="c13f39c5-0d35-4bff-ba79-3cd5de940369"
+              status="SUCCESS" startDate="2012-02-26 15:40:04" endDate="2012-02-26 15:41:04"/>
+
+  <Report id="c3520ad9-179f-49e7-b315-d684d216dd97" name="reconciliation" active="1" template_id="empty"/>
+  <Implementation id="ReconciliationReportletConf" type="REPORTLET" engine="JAVA"
+                  body='{"@class":"org.apache.syncope.common.lib.report.ReconciliationReportletConf","name":"dashboardReconciliationReportlet","userMatchingCond":null,"groupMatchingCond":null,"anyObjectMatchingCond":null,"features":["key","username","groupName"]}'/>
+  <ReportReportlet report_id="c3520ad9-179f-49e7-b315-d684d216dd97" implementation_id="ReconciliationReportletConf"/>
+  
+  <SyncopeLogger logName="syncope.audit.[LOGIC]:[SyncopeLogic]:[]:[isSelfRegAllowed]:[SUCCESS]" logLevel="DEBUG" logType="AUDIT"/>
+  
+  <SecurityQuestion id="887028ea-66fc-41e7-b397-620d7ea6dfbb" content="What's your mother's maiden name?"/>
+</dataset>
diff --git a/core/persistence-jpa-pgjsonb/src/test/resources/persistenceTest.xml b/core/persistence-jpa-pgjsonb/src/test/resources/persistenceTest.xml
new file mode 100644
index 0000000..1e84aea
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/test/resources/persistenceTest.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+                           http://www.springframework.org/schema/beans/spring-beans.xsd
+                           http://www.springframework.org/schema/context
+                           http://www.springframework.org/schema/context/spring-context.xsd">
+
+  <bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
+    <property name="locations">
+      <list>
+        <value>file:${conf.directory}/persistence.properties</value>
+        <value>file:${conf.directory}/domains/*.properties</value>
+        <value>classpath:security.properties</value>
+      </list>
+    </property>
+    <property name="ignoreResourceNotFound" value="true"/>
+    <property name="ignoreUnresolvablePlaceholders" value="true"/>
+  </bean>
+  
+  <bean class="org.apache.syncope.core.spring.ApplicationContextProvider"/>
+
+  <bean id="adminUser" class="java.lang.String">
+    <constructor-arg value="${adminUser}"/>
+  </bean>
+  <bean id="anonymousUser" class="java.lang.String">
+    <constructor-arg value="${anonymousUser}"/>
+  </bean>
+  
+  <context:component-scan base-package="org.apache.syncope.core.spring.security"/>
+
+  <bean class="org.apache.syncope.core.spring.security.DefaultPasswordGenerator"/>
+
+  <import resource="persistenceContext.xml"/>
+
+</beans>
diff --git a/core/persistence-jpa-pgjsonb/src/test/resources/simplelogger.properties b/core/persistence-jpa-pgjsonb/src/test/resources/simplelogger.properties
new file mode 100644
index 0000000..929ded2
--- /dev/null
+++ b/core/persistence-jpa-pgjsonb/src/test/resources/simplelogger.properties
@@ -0,0 +1,22 @@
+# 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.
+
+# See http://www.slf4j.org/api/org/slf4j/impl/SimpleLogger.html
+# Possible values: "trace", "debug", "info", "warn", or "error"
+org.slf4j.simpleLogger.defaultLogLevel=debug
+org.slf4j.simpleLogger.log.org.springframework.jdbc.core.JdbcTemplate=error
+
diff --git a/core/pom.xml b/core/pom.xml
index 11dd2f3..dca1b46 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -79,6 +79,7 @@ under the License.
   <modules>
     <module>persistence-api</module>
     <module>persistence-jpa</module>
+    <module>persistence-jpa-pgjsonb</module>
     <module>spring</module>
     <module>provisioning-api</module>
     <module>provisioning-java</module>


Mime
View raw message