You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2015/05/25 16:50:52 UTC

[16/29] syncope git commit: [SYNCOPE-666] Initial commit, Travis CI builds disabled

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAExternalResource.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAExternalResource.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAExternalResource.java
deleted file mode 100644
index 2fa54c3..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAExternalResource.java
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import javax.persistence.Basic;
-import javax.persistence.CascadeType;
-import javax.persistence.CollectionTable;
-import javax.persistence.Column;
-import javax.persistence.ElementCollection;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.Id;
-import javax.persistence.JoinColumn;
-import javax.persistence.Lob;
-import javax.persistence.ManyToOne;
-import javax.persistence.OneToOne;
-import javax.persistence.Table;
-import javax.validation.constraints.Max;
-import javax.validation.constraints.Min;
-import javax.validation.constraints.NotNull;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.types.ConnConfProperty;
-import org.apache.syncope.common.lib.types.PropagationMode;
-import org.apache.syncope.common.lib.types.TraceLevel;
-import org.apache.syncope.core.persistence.api.entity.AccountPolicy;
-import org.apache.syncope.core.persistence.api.entity.ConnInstance;
-import org.apache.syncope.core.persistence.api.entity.ExternalResource;
-import org.apache.syncope.core.persistence.api.entity.PasswordPolicy;
-import org.apache.syncope.core.persistence.api.entity.SyncPolicy;
-import org.apache.syncope.core.persistence.api.entity.group.GMapping;
-import org.apache.syncope.core.persistence.api.entity.user.UMapping;
-import org.apache.syncope.core.persistence.jpa.validation.entity.ExternalResourceCheck;
-import org.apache.syncope.core.persistence.jpa.entity.group.JPAGMapping;
-import org.apache.syncope.core.persistence.jpa.entity.user.JPAUMapping;
-import org.apache.syncope.core.misc.serialization.POJOHelper;
-import org.identityconnectors.framework.common.objects.SyncToken;
-
-/**
- * Resource for propagation and synchronization.
- */
-@Entity
-@Table(name = JPAExternalResource.TABLE)
-@ExternalResourceCheck
-public class JPAExternalResource extends AbstractAnnotatedEntity<String> implements ExternalResource {
-
-    private static final long serialVersionUID = -6937712883512073278L;
-
-    public static final String TABLE = "ExternalResource";
-
-    /**
-     * The resource identifier is the name.
-     */
-    @Id
-    private String name;
-
-    /**
-     * Should this resource enforce the mandatory constraints?
-     */
-    @Column(nullable = false)
-    @Basic
-    @Min(0)
-    @Max(1)
-    private Integer enforceMandatoryCondition;
-
-    /**
-     * The resource type is identified by the associated connector.
-     */
-    @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.MERGE })
-    @NotNull
-    private JPAConnInstance connector;
-
-    /**
-     * Mapping for user objects.
-     */
-    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "resource")
-    private JPAUMapping umapping;
-
-    /**
-     * Mapping for group objects.
-     */
-    @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "resource")
-    private JPAGMapping rmapping;
-
-    /**
-     * Is this resource primary, for propagations?
-     */
-    @Column(nullable = false)
-    @Basic
-    @Min(0)
-    @Max(1)
-    private Integer propagationPrimary;
-
-    /**
-     * Priority index for propagation ordering.
-     */
-    @Column(nullable = false)
-    private Integer propagationPriority;
-
-    /**
-     * Generate random password for propagation, if not provided?
-     */
-    @Column(nullable = false)
-    @Basic
-    @Min(0)
-    @Max(1)
-    private Integer randomPwdIfNotProvided;
-
-    @Enumerated(EnumType.STRING)
-    @Column(nullable = false)
-    private PropagationMode propagationMode;
-
-    @Enumerated(EnumType.STRING)
-    @Column(nullable = false)
-    private TraceLevel createTraceLevel;
-
-    @Enumerated(EnumType.STRING)
-    @Column(nullable = false)
-    private TraceLevel updateTraceLevel;
-
-    @Enumerated(EnumType.STRING)
-    @Column(nullable = false)
-    private TraceLevel deleteTraceLevel;
-
-    @Enumerated(EnumType.STRING)
-    @Column(nullable = false)
-    private TraceLevel syncTraceLevel;
-
-    @ManyToOne(fetch = FetchType.EAGER)
-    private JPAPasswordPolicy passwordPolicy;
-
-    @ManyToOne(fetch = FetchType.EAGER)
-    private JPAAccountPolicy accountPolicy;
-
-    @ManyToOne(fetch = FetchType.EAGER)
-    private JPASyncPolicy syncPolicy;
-
-    /**
-     * Configuration properties that are overridden from the connector instance.
-     */
-    @Lob
-    private String jsonConf;
-
-    /**
-     * SyncToken for calling ConnId's sync() on users.
-     */
-    @Lob
-    private String userializedSyncToken;
-
-    /**
-     * SyncToken for calling ConnId's sync() on groups.
-     */
-    @Lob
-    private String rserializedSyncToken;
-
-    /**
-     * (Optional) classes for PropagationAction.
-     */
-    @ElementCollection(fetch = FetchType.EAGER)
-    @Column(name = "actionClassName")
-    @CollectionTable(name = "ExternalResource_PropActions",
-            joinColumns =
-            @JoinColumn(name = "ExternalResource_name", referencedColumnName = "name"))
-    private List<String> propagationActionsClassNames = new ArrayList<>();
-
-    /**
-     * Default constructor.
-     */
-    public JPAExternalResource() {
-        super();
-
-        enforceMandatoryCondition = getBooleanAsInteger(false);
-        propagationPrimary = 0;
-        propagationPriority = 0;
-        randomPwdIfNotProvided = 0;
-        propagationMode = PropagationMode.TWO_PHASES;
-
-        createTraceLevel = TraceLevel.FAILURES;
-        updateTraceLevel = TraceLevel.FAILURES;
-        deleteTraceLevel = TraceLevel.FAILURES;
-        syncTraceLevel = TraceLevel.FAILURES;
-    }
-
-    @Override
-    public boolean isEnforceMandatoryCondition() {
-        return isBooleanAsInteger(enforceMandatoryCondition);
-    }
-
-    @Override
-    public void setEnforceMandatoryCondition(final boolean enforceMandatoryCondition) {
-        this.enforceMandatoryCondition = getBooleanAsInteger(enforceMandatoryCondition);
-    }
-
-    @Override
-    public ConnInstance getConnector() {
-        return connector;
-    }
-
-    @Override
-    public void setConnector(final ConnInstance connector) {
-        checkType(connector, JPAConnInstance.class);
-        this.connector = (JPAConnInstance) connector;
-    }
-
-    @Override
-    public UMapping getUmapping() {
-        return umapping;
-    }
-
-    @Override
-    public void setUmapping(final UMapping umapping) {
-        checkType(umapping, JPAUMapping.class);
-        this.umapping = (JPAUMapping) umapping;
-    }
-
-    @Override
-    public GMapping getGmapping() {
-        return rmapping;
-    }
-
-    @Override
-    public void setGmapping(final GMapping gmapping) {
-        checkType(gmapping, JPAGMapping.class);
-        this.rmapping = (JPAGMapping) gmapping;
-    }
-
-    @Override
-    public boolean isPropagationPrimary() {
-        return isBooleanAsInteger(propagationPrimary);
-    }
-
-    @Override
-    public void setPropagationPrimary(final boolean propagationPrimary) {
-        this.propagationPrimary = getBooleanAsInteger(propagationPrimary);
-    }
-
-    @Override
-    public Integer getPropagationPriority() {
-        return propagationPriority;
-    }
-
-    @Override
-    public void setPropagationPriority(final Integer propagationPriority) {
-        if (propagationPriority != null) {
-            this.propagationPriority = propagationPriority;
-        }
-    }
-
-    @Override
-    public boolean isRandomPwdIfNotProvided() {
-        return isBooleanAsInteger(randomPwdIfNotProvided);
-    }
-
-    @Override
-    public void setRandomPwdIfNotProvided(final boolean randomPwdIfNotProvided) {
-        this.randomPwdIfNotProvided = getBooleanAsInteger(randomPwdIfNotProvided);
-    }
-
-    @Override
-    public PropagationMode getPropagationMode() {
-        return propagationMode;
-    }
-
-    @Override
-    public void setPropagationMode(final PropagationMode propagationMode) {
-        this.propagationMode = propagationMode;
-    }
-
-    @Override
-    public String getKey() {
-        return name;
-    }
-
-    @Override
-    public void setKey(final String name) {
-        this.name = name;
-    }
-
-    @Override
-    public TraceLevel getCreateTraceLevel() {
-        return createTraceLevel;
-    }
-
-    @Override
-    public void setCreateTraceLevel(final TraceLevel createTraceLevel) {
-        this.createTraceLevel = createTraceLevel;
-    }
-
-    @Override
-
-    public TraceLevel getDeleteTraceLevel() {
-        return deleteTraceLevel;
-    }
-
-    @Override
-    public void setDeleteTraceLevel(final TraceLevel deleteTraceLevel) {
-        this.deleteTraceLevel = deleteTraceLevel;
-    }
-
-    @Override
-    public TraceLevel getUpdateTraceLevel() {
-        return updateTraceLevel;
-    }
-
-    @Override
-    public void setUpdateTraceLevel(final TraceLevel updateTraceLevel) {
-        this.updateTraceLevel = updateTraceLevel;
-    }
-
-    @Override
-    public TraceLevel getSyncTraceLevel() {
-        return syncTraceLevel;
-    }
-
-    @Override
-    public void setSyncTraceLevel(final TraceLevel syncTraceLevel) {
-        this.syncTraceLevel = syncTraceLevel;
-    }
-
-    @Override
-    public AccountPolicy getAccountPolicy() {
-        return accountPolicy;
-    }
-
-    @Override
-    public void setAccountPolicy(final AccountPolicy accountPolicy) {
-        checkType(accountPolicy, JPAAccountPolicy.class);
-        this.accountPolicy = (JPAAccountPolicy) accountPolicy;
-    }
-
-    @Override
-    public PasswordPolicy getPasswordPolicy() {
-        return passwordPolicy;
-    }
-
-    @Override
-    public void setPasswordPolicy(final PasswordPolicy passwordPolicy) {
-        checkType(passwordPolicy, JPAPasswordPolicy.class);
-        this.passwordPolicy = (JPAPasswordPolicy) passwordPolicy;
-    }
-
-    @Override
-    public SyncPolicy getSyncPolicy() {
-        return syncPolicy;
-    }
-
-    @Override
-    public void setSyncPolicy(final SyncPolicy syncPolicy) {
-        checkType(syncPolicy, JPASyncPolicy.class);
-        this.syncPolicy = (JPASyncPolicy) syncPolicy;
-    }
-
-    @Override
-    public Set<ConnConfProperty> getConnInstanceConfiguration() {
-        Set<ConnConfProperty> configuration = new HashSet<>();
-        if (!StringUtils.isBlank(jsonConf)) {
-            CollectionUtils.addAll(configuration, POJOHelper.deserialize(jsonConf, ConnConfProperty[].class));
-        }
-
-        return configuration;
-    }
-
-    @Override
-    public void setConnInstanceConfiguration(final Set<ConnConfProperty> properties) {
-        jsonConf = POJOHelper.serialize(new HashSet<>(properties));
-    }
-
-    @Override
-    public String getSerializedUSyncToken() {
-        return userializedSyncToken;
-    }
-
-    @Override
-    public SyncToken getUsyncToken() {
-        return userializedSyncToken == null
-                ? null
-                : POJOHelper.deserialize(userializedSyncToken, SyncToken.class);
-    }
-
-    @Override
-    public void setUsyncToken(final SyncToken syncToken) {
-        this.userializedSyncToken = syncToken == null ? null : POJOHelper.serialize(syncToken);
-    }
-
-    @Override
-    public String getSerializedRSyncToken() {
-        return rserializedSyncToken;
-    }
-
-    @Override
-    public SyncToken getRsyncToken() {
-        return rserializedSyncToken == null
-                ? null
-                : POJOHelper.deserialize(rserializedSyncToken, SyncToken.class);
-    }
-
-    @Override
-    public void setRsyncToken(final SyncToken syncToken) {
-        this.rserializedSyncToken = syncToken == null ? null : POJOHelper.serialize(syncToken);
-    }
-
-    @Override
-    public List<String> getPropagationActionsClassNames() {
-        return propagationActionsClassNames;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
index 498032e..7e3d211 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 import javax.persistence.Basic;
+import javax.persistence.CascadeType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
 import javax.persistence.ElementCollection;
@@ -31,12 +32,17 @@ import javax.persistence.Enumerated;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
 import javax.persistence.JoinColumn;
+import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
 import javax.validation.constraints.NotNull;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.TraceLevel;
+import org.apache.syncope.core.persistence.api.entity.AnyAbout;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.Notification;
 import org.apache.syncope.core.persistence.jpa.validation.entity.NotificationCheck;
 
@@ -56,19 +62,18 @@ public class JPANotification extends AbstractEntity<Long> implements Notificatio
     @Column(name = "event")
     @CollectionTable(name = "Notification_events",
             joinColumns =
-            @JoinColumn(name = "Notification_id", referencedColumnName = "id"))
+            @JoinColumn(name = "notification_id", referencedColumnName = "id"))
     private List<String> events;
 
-    private String userAbout;
-
-    private String groupAbout;
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "notification")
+    private List<JPAAnyAbout> abouts;
 
     private String recipients;
 
     @ElementCollection(fetch = FetchType.EAGER)
     @CollectionTable(name = "Notification_staticRecipients",
             joinColumns =
-            @JoinColumn(name = "Notification_id", referencedColumnName = "id"))
+            @JoinColumn(name = "notification_id", referencedColumnName = "id"))
     @Column(name = "staticRecipients")
     private List<String> staticRecipients;
 
@@ -106,6 +111,7 @@ public class JPANotification extends AbstractEntity<Long> implements Notificatio
 
     public JPANotification() {
         events = new ArrayList<>();
+        abouts = new ArrayList<>();
         staticRecipients = new ArrayList<>();
         selfAsRecipient = getBooleanAsInteger(false);
         active = getBooleanAsInteger(true);
@@ -118,26 +124,6 @@ public class JPANotification extends AbstractEntity<Long> implements Notificatio
     }
 
     @Override
-    public String getUserAbout() {
-        return userAbout;
-    }
-
-    @Override
-    public void setUserAbout(final String userAbout) {
-        this.userAbout = userAbout;
-    }
-
-    @Override
-    public String getGroupAbout() {
-        return groupAbout;
-    }
-
-    @Override
-    public void setGroupAbout(final String groupAbout) {
-        this.groupAbout = groupAbout;
-    }
-
-    @Override
     public String getRecipients() {
         return recipients;
     }
@@ -174,6 +160,34 @@ public class JPANotification extends AbstractEntity<Long> implements Notificatio
     }
 
     @Override
+    public boolean add(final AnyAbout about) {
+        checkType(about, JPAAnyAbout.class);
+        return this.abouts.add((JPAAnyAbout) about);
+    }
+
+    @Override
+    public boolean remove(final AnyAbout about) {
+        checkType(about, JPAAnyAbout.class);
+        return this.abouts.remove((JPAAnyAbout) about);
+    }
+
+    @Override
+    public AnyAbout getAbout(final AnyType anyType) {
+        return CollectionUtils.find(abouts, new Predicate<AnyAbout>() {
+
+            @Override
+            public boolean evaluate(final AnyAbout about) {
+                return anyType != null && anyType.equals(about.getAnyType());
+            }
+        });
+    }
+
+    @Override
+    public List<? extends AnyAbout> getAbouts() {
+        return abouts;
+    }
+
+    @Override
     public List<String> getStaticRecipients() {
         return staticRecipients;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
new file mode 100644
index 0000000..5f767e0
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
@@ -0,0 +1,276 @@
+/*
+ * 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.lang.reflect.Constructor;
+import javax.persistence.Basic;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.Id;
+import javax.persistence.Lob;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.common.lib.types.CipherAlgorithm;
+import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.jpa.attrvalue.validation.BasicValidator;
+import org.apache.syncope.core.persistence.jpa.validation.entity.PlainSchemaCheck;
+import org.apache.syncope.core.persistence.jpa.validation.entity.SchemaNameCheck;
+
+@Entity
+@Table(name = JPAPlainSchema.TABLE)
+@PlainSchemaCheck
+@SchemaNameCheck
+public class JPAPlainSchema extends AbstractEntity<String> implements PlainSchema {
+
+    private static final long serialVersionUID = -8621028596062054739L;
+
+    public static final String TABLE = "PlainSchema";
+
+    @Id
+    private String name;
+
+    @Column(nullable = false)
+    @Enumerated(EnumType.STRING)
+    private AttrSchemaType type;
+
+    @Column(nullable = false)
+    private String mandatoryCondition;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer multivalue;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer uniqueConstraint;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer readonly;
+
+    @Column(nullable = true)
+    private String conversionPattern;
+
+    @Column(nullable = true)
+    private String validatorClass;
+
+    @Column(nullable = true)
+    @Lob
+    private String enumerationValues;
+
+    @Column(nullable = true)
+    @Lob
+    private String enumerationKeys;
+
+    @Column(nullable = true)
+    private String secretKey;
+
+    @Column(nullable = true)
+    @Enumerated(EnumType.STRING)
+    private CipherAlgorithm cipherAlgorithm;
+
+    @Column(nullable = true)
+    private String mimeType;
+
+    @Transient
+    private Validator validator;
+
+    public JPAPlainSchema() {
+        super();
+
+        type = AttrSchemaType.String;
+        mandatoryCondition = Boolean.FALSE.toString();
+        multivalue = getBooleanAsInteger(false);
+        uniqueConstraint = getBooleanAsInteger(false);
+        readonly = getBooleanAsInteger(false);
+    }
+
+    @Override
+    public String getKey() {
+        return name;
+    }
+
+    @Override
+    public void setKey(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public AttrSchemaType getType() {
+        return type;
+    }
+
+    @Override
+    public void setType(final AttrSchemaType type) {
+        this.type = type;
+    }
+
+    @Override
+    public String getMandatoryCondition() {
+        return mandatoryCondition;
+    }
+
+    @Override
+    public void setMandatoryCondition(final String condition) {
+        this.mandatoryCondition = condition;
+    }
+
+    @Override
+    public boolean isMultivalue() {
+        return isBooleanAsInteger(multivalue);
+    }
+
+    @Override
+    public void setMultivalue(final boolean multivalue) {
+        this.multivalue = getBooleanAsInteger(multivalue);
+    }
+
+    @Override
+    public boolean isUniqueConstraint() {
+        return isBooleanAsInteger(uniqueConstraint);
+    }
+
+    @Override
+    public void setUniqueConstraint(final boolean uniquevalue) {
+        this.uniqueConstraint = getBooleanAsInteger(uniquevalue);
+    }
+
+    @Override
+    public boolean isReadonly() {
+        return isBooleanAsInteger(readonly);
+    }
+
+    @Override
+    public void setReadonly(final boolean readonly) {
+        this.readonly = getBooleanAsInteger(readonly);
+    }
+
+    @Override
+    public Validator getValidator() {
+        if (validator != null) {
+            return validator;
+        }
+
+        if (getValidatorClass() != null && getValidatorClass().length() > 0) {
+            try {
+                Constructor<?> validatorConstructor = Class.forName(getValidatorClass()).
+                        getConstructor(new Class<?>[] { PlainSchema.class });
+                validator = (Validator) validatorConstructor.newInstance(this);
+            } catch (Exception e) {
+                LOG.error("Could not instantiate validator of type {}, reverting to {}",
+                        getValidatorClass(), BasicValidator.class.getSimpleName(), e);
+            }
+        }
+
+        if (validator == null) {
+            validator = new BasicValidator(this);
+        }
+
+        return validator;
+    }
+
+    @Override
+    public String getValidatorClass() {
+        return validatorClass;
+    }
+
+    @Override
+    public void setValidatorClass(final String validatorClass) {
+        this.validatorClass = validatorClass;
+    }
+
+    @Override
+    public String getEnumerationValues() {
+        return enumerationValues;
+    }
+
+    @Override
+    public void setEnumerationValues(final String enumerationValues) {
+        this.enumerationValues = enumerationValues;
+    }
+
+    @Override
+    public String getEnumerationKeys() {
+        return enumerationKeys;
+    }
+
+    @Override
+    public void setEnumerationKeys(final String enumerationKeys) {
+        this.enumerationKeys = enumerationKeys;
+    }
+
+    @Override
+    public String getConversionPattern() {
+        if (!getType().isConversionPatternNeeded()) {
+            LOG.debug("Conversion pattern is not needed: {}'s type is {}", this, getType());
+        }
+
+        return conversionPattern;
+    }
+
+    @Override
+    public void setConversionPattern(final String conversionPattern) {
+        if (StringUtils.isNotBlank(conversionPattern) && !getType().isConversionPatternNeeded()) {
+            LOG.warn("Conversion pattern will be ignored: this attribute type is {}", getType());
+        }
+
+        this.conversionPattern = conversionPattern;
+    }
+
+    @Override
+    public String getSecretKey() {
+        return secretKey;
+    }
+
+    @Override
+    public void setSecretKey(final String secretKey) {
+        this.secretKey = secretKey;
+    }
+
+    @Override
+    public CipherAlgorithm getCipherAlgorithm() {
+        return cipherAlgorithm;
+    }
+
+    @Override
+    public void setCipherAlgorithm(final CipherAlgorithm cipherAlgorithm) {
+        this.cipherAlgorithm = cipherAlgorithm;
+    }
+
+    @Override
+    public String getMimeType() {
+        return mimeType;
+    }
+
+    @Override
+    public void setMimeType(final String mimeType) {
+        this.mimeType = mimeType;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
index 0360f54..4969497 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARole.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity;
 
+import org.apache.syncope.core.persistence.jpa.entity.user.JPADynRoleMembership;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -37,7 +38,7 @@ import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
-import org.apache.syncope.core.persistence.api.entity.DynRoleMembership;
+import org.apache.syncope.core.persistence.api.entity.user.DynRoleMembership;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.Role;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
new file mode 100644
index 0000000..f7cf717
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAVirSchema.java
@@ -0,0 +1,95 @@
+/*
+ * 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 javax.persistence.Basic;
+import javax.persistence.Cacheable;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import org.apache.syncope.common.lib.types.AttrSchemaType;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.jpa.validation.entity.SchemaNameCheck;
+
+@Entity
+@Table(name = JPAVirSchema.TABLE)
+@Cacheable
+@SchemaNameCheck
+public class JPAVirSchema extends AbstractEntity<String> implements VirSchema {
+
+    private static final long serialVersionUID = 3274006935328590141L;
+
+    public static final String TABLE = "VirSchema";
+
+    @Id
+    private String name;
+
+    @Basic
+    @Min(0)
+    @Max(1)
+    private Integer readonly;
+
+    public JPAVirSchema() {
+        super();
+
+        readonly = getBooleanAsInteger(false);
+    }
+
+    @Override
+    public String getKey() {
+        return name;
+    }
+
+    @Override
+    public void setKey(final String key) {
+        this.name = key;
+    }
+
+    @Override
+    public AttrSchemaType getType() {
+        return AttrSchemaType.String;
+    }
+
+    @Override
+    public String getMandatoryCondition() {
+        return Boolean.FALSE.toString().toLowerCase();
+    }
+
+    @Override
+    public boolean isMultivalue() {
+        return Boolean.TRUE;
+    }
+
+    @Override
+    public boolean isUniqueConstraint() {
+        return Boolean.FALSE;
+    }
+
+    @Override
+    public boolean isReadonly() {
+        return isBooleanAsInteger(readonly);
+    }
+
+    @Override
+    public void setReadonly(final boolean readonly) {
+        this.readonly = getBooleanAsInteger(readonly);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAttributableUtilsFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAttributableUtilsFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAttributableUtilsFactory.java
deleted file mode 100644
index e132601..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAttributableUtilsFactory.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity;
-
-import org.apache.syncope.common.lib.types.AttributableType;
-import org.apache.syncope.core.persistence.api.entity.Attributable;
-import org.apache.syncope.core.persistence.api.entity.AttributableUtils;
-import org.apache.syncope.core.persistence.api.entity.AttributableUtilsFactory;
-import org.apache.syncope.core.persistence.api.entity.conf.Conf;
-import org.apache.syncope.core.persistence.api.entity.membership.Membership;
-import org.apache.syncope.core.persistence.api.entity.group.Group;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.identityconnectors.framework.common.objects.ObjectClass;
-import org.springframework.stereotype.Component;
-
-@Component
-public class JPAttributableUtilsFactory implements AttributableUtilsFactory {
-
-    @Override
-    public AttributableUtils getInstance(final AttributableType type) {
-        return new JPAAttributableUtils(type);
-    }
-
-    @Override
-    public AttributableUtils getInstance(final String attributableType) {
-        return new JPAAttributableUtils(AttributableType.valueOf(attributableType));
-    }
-
-    @Override
-    public AttributableUtils getInstance(final ObjectClass objectClass) {
-        AttributableType type = null;
-        if (ObjectClass.ACCOUNT.equals(objectClass)) {
-            type = AttributableType.USER;
-        } else if (ObjectClass.GROUP.equals(objectClass)) {
-            type = AttributableType.GROUP;
-        }
-
-        if (type == null) {
-            throw new IllegalArgumentException("ObjectClass not supported: " + objectClass);
-        }
-
-        return new JPAAttributableUtils(type);
-    }
-
-    @Override
-    public AttributableUtils getInstance(final Attributable<?, ?, ?> attributable) {
-        AttributableType type = null;
-        if (attributable instanceof User) {
-            type = AttributableType.USER;
-        } else if (attributable instanceof Group) {
-            type = AttributableType.GROUP;
-        } else if (attributable instanceof Membership) {
-            type = AttributableType.MEMBERSHIP;
-        } else if (attributable instanceof Conf) {
-            type = AttributableType.CONFIGURATION;
-        }
-
-        if (type == null) {
-            throw new IllegalArgumentException("Attributable type not supported: " + attributable.getClass().getName());
-        }
-
-        return new JPAAttributableUtils(type);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
new file mode 100644
index 0000000..abd6676
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
@@ -0,0 +1,50 @@
+/*
+ * 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 javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.core.persistence.api.entity.anyobject.ADerAttr;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractDerAttr;
+
+@Entity
+@Table(name = JPAADerAttr.TABLE)
+public class JPAADerAttr extends AbstractDerAttr<AnyObject> implements ADerAttr {
+
+    private static final long serialVersionUID = 5828533701103533330L;
+
+    public static final String TABLE = "ADerAttr";
+
+    @ManyToOne
+    private JPAAnyObject owner;
+
+    @Override
+    public AnyObject getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final AnyObject owner) {
+        checkType(owner, JPAAnyObject.class);
+        this.owner = (JPAAnyObject) owner;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADynGroupMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADynGroupMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADynGroupMembership.java
new file mode 100644
index 0000000..c12b855
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADynGroupMembership.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.entity.anyobject;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import org.apache.syncope.core.persistence.api.entity.anyobject.ADynGroupMembership;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractDynMembership;
+import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
+
+@Entity
+@Table(name = JPAADynGroupMembership.TABLE)
+public class JPAADynGroupMembership extends AbstractDynMembership<AnyObject> implements ADynGroupMembership {
+
+    private static final long serialVersionUID = -7336814163949640354L;
+
+    public static final String TABLE = "ADynGroupMembership";
+
+    @Id
+    private Long id;
+
+    @OneToOne
+    private JPAGroup group;
+
+    @ManyToMany
+    @JoinTable(joinColumns =
+            @JoinColumn(name = "aDynGroupMembership_id"),
+            inverseJoinColumns =
+            @JoinColumn(name = "anyObject_id"))
+    private List<JPAAnyObject> anyObjects = new ArrayList<>();
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public Group getGroup() {
+        return group;
+    }
+
+    @Override
+    public void setGroup(final Group role) {
+        checkType(role, JPAGroup.class);
+        this.group = (JPAGroup) role;
+    }
+
+    @Override
+    public boolean add(final AnyObject anyObject) {
+        checkType(anyObject, JPAAnyObject.class);
+        return anyObjects.add((JPAAnyObject) anyObject);
+    }
+
+    @Override
+    public boolean remove(final AnyObject anyObject) {
+        checkType(anyObject, JPAAnyObject.class);
+        return anyObjects.remove((JPAAnyObject) anyObject);
+    }
+
+    @Override
+    public List<? extends AnyObject> getMembers() {
+        return anyObjects;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAMembership.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAMembership.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAMembership.java
new file mode 100644
index 0000000..e770e33
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAMembership.java
@@ -0,0 +1,77 @@
+/*
+ * 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 javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
+import org.apache.syncope.core.persistence.jpa.entity.group.JPAGroup;
+
+@Entity
+@Table(name = JPAAMembership.TABLE)
+public class JPAAMembership extends AbstractEntity<Long> implements AMembership {
+
+    private static final long serialVersionUID = 1503557547394601405L;
+
+    public static final String TABLE = "AMembership";
+
+    @Id
+    private Long id;
+
+    @ManyToOne
+    @Column(name = "anyObject_id")
+    private JPAAnyObject leftEnd;
+
+    @ManyToOne
+    @Column(name = "group_id")
+    private JPAGroup rightEnd;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public AnyObject getLeftEnd() {
+        return leftEnd;
+    }
+
+    @Override
+    public void setLeftEnd(final AnyObject leftEnd) {
+        checkType(leftEnd, JPAAnyObject.class);
+        this.leftEnd = (JPAAnyObject) leftEnd;
+    }
+
+    @Override
+    public JPAGroup getRightEnd() {
+        return rightEnd;
+    }
+
+    @Override
+    public void setRightEnd(final Group rightEnd) {
+        checkType(rightEnd, JPAGroup.class);
+        this.rightEnd = (JPAGroup) rightEnd;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttr.java
new file mode 100644
index 0000000..46c1680
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttr.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.entity.anyobject;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.validation.Valid;
+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.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.jpa.entity.AbstractPlainAttr;
+
+@Entity
+@Table(name = JPAAPlainAttr.TABLE)
+public class JPAAPlainAttr extends AbstractPlainAttr<AnyObject> implements APlainAttr {
+
+    private static final long serialVersionUID = 8066058729580952116L;
+
+    public static final String TABLE = "APlainAttr";
+
+    @Id
+    private Long id;
+
+    @ManyToOne(fetch = FetchType.EAGER)
+    private JPAAnyObject owner;
+
+    @OneToMany(cascade = CascadeType.MERGE, orphanRemoval = true, mappedBy = "attribute")
+    @Valid
+    private List<JPAAPlainAttrValue> values = new ArrayList<>();
+
+    @OneToOne(cascade = CascadeType.ALL, mappedBy = "attribute")
+    @Valid
+    private JPAAPlainAttrUniqueValue uniqueValue;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public AnyObject getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final AnyObject owner) {
+        checkType(owner, JPAAnyObject.class);
+        this.owner = (JPAAnyObject) owner;
+    }
+
+    @Override
+    protected boolean addForMultiValue(final PlainAttrValue attrValue) {
+        checkType(attrValue, JPAAPlainAttrValue.class);
+        return values.add((JPAAPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public boolean remove(final PlainAttrValue attrValue) {
+        checkType(attrValue, JPAAPlainAttrValue.class);
+        return values.remove((JPAAPlainAttrValue) attrValue);
+    }
+
+    @Override
+    public List<? extends APlainAttrValue> getValues() {
+        return values;
+    }
+
+    @Override
+    public APlainAttrUniqueValue getUniqueValue() {
+        return uniqueValue;
+    }
+
+    @Override
+    public void setUniqueValue(final PlainAttrUniqueValue uniqueValue) {
+        checkType(owner, JPAAPlainAttrUniqueValue.class);
+        this.uniqueValue = (JPAAPlainAttrUniqueValue) uniqueValue;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrUniqueValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrUniqueValue.java
new file mode 100644
index 0000000..25cc5eb
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrUniqueValue.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.entity.anyobject;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+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;
+import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
+
+@Entity
+@Table(name = JPAAPlainAttrUniqueValue.TABLE)
+public class JPAAPlainAttrUniqueValue extends AbstractPlainAttrValue implements APlainAttrUniqueValue {
+
+    private static final long serialVersionUID = -6412206895091662679L;
+
+    public static final String TABLE = "APlainAttrUniqueValue";
+
+    @Id
+    private Long id;
+
+    @OneToOne(optional = false)
+    private JPAAPlainAttr attribute;
+
+    @ManyToOne(optional = false)
+    @JoinColumn(name = "schema_name")
+    private JPAPlainSchema schema;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public APlainAttr getAttr() {
+        return attribute;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr attr) {
+        checkType(attr, JPAAPlainAttr.class);
+        this.attribute = (JPAAPlainAttr) attr;
+    }
+
+    @Override
+    public PlainSchema getSchema() {
+        return schema;
+    }
+
+    @Override
+    public void setSchema(final PlainSchema schema) {
+        checkType(schema, JPAPlainSchema.class);
+        this.schema = (JPAPlainSchema) schema;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
new file mode 100644
index 0000000..73c962c
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAPlainAttrValue.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.entity.anyobject;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.validation.constraints.NotNull;
+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;
+
+@Entity
+@Table(name = JPAAPlainAttrValue.TABLE)
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+public class JPAAPlainAttrValue extends AbstractPlainAttrValue implements APlainAttrValue {
+
+    private static final long serialVersionUID = -2965487882824889272L;
+
+    public static final String TABLE = "APlainAttrValue";
+
+    @Id
+    private Long id;
+
+    @ManyToOne
+    @NotNull
+    private JPAAPlainAttr attribute;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public APlainAttr getAttr() {
+        return attribute;
+    }
+
+    @Override
+    public void setAttr(final PlainAttr attr) {
+        checkType(attr, JPAAPlainAttr.class);
+        this.attribute = (JPAAPlainAttr) attr;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAARelationship.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAARelationship.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAARelationship.java
new file mode 100644
index 0000000..93a7941
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAARelationship.java
@@ -0,0 +1,76 @@
+/*
+ * 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 javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.core.persistence.api.entity.anyobject.ARelationship;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractEntity;
+
+@Entity
+@Table(name = JPAARelationship.TABLE)
+public class JPAARelationship extends AbstractEntity<Long> implements ARelationship {
+
+    private static final long serialVersionUID = 6608821135023815357L;
+
+    public static final String TABLE = "ARelationship";
+
+    @Id
+    private Long id;
+
+    @ManyToOne
+    @Column(name = "left_anyObject_id")
+    private JPAAnyObject leftEnd;
+
+    @ManyToOne
+    @Column(name = "right_anyObject_id")
+    private JPAAnyObject rightEnd;
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public AnyObject getLeftEnd() {
+        return leftEnd;
+    }
+
+    @Override
+    public void setLeftEnd(final AnyObject leftEnd) {
+        checkType(leftEnd, JPAAnyObject.class);
+        this.leftEnd = (JPAAnyObject) leftEnd;
+    }
+
+    @Override
+    public AnyObject getRightEnd() {
+        return rightEnd;
+    }
+
+    @Override
+    public void setRightEnd(final AnyObject rightEnd) {
+        checkType(rightEnd, JPAAnyObject.class);
+        this.rightEnd = (JPAAnyObject) rightEnd;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
new file mode 100644
index 0000000..7469799
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
@@ -0,0 +1,50 @@
+/*
+ * 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 javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AVirAttr;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractVirAttr;
+
+@Entity
+@Table(name = JPAAVirAttr.TABLE)
+public class JPAAVirAttr extends AbstractVirAttr<AnyObject> implements AVirAttr {
+
+    private static final long serialVersionUID = -4935990254545760827L;
+
+    public static final String TABLE = "AVirAttr";
+
+    @ManyToOne
+    private JPAAnyObject owner;
+
+    @Override
+    public AnyObject getOwner() {
+        return owner;
+    }
+
+    @Override
+    public void setOwner(final AnyObject owner) {
+        checkType(owner, JPAAnyObject.class);
+        this.owner = (JPAAnyObject) owner;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
new file mode 100644
index 0000000..6442c2d
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
@@ -0,0 +1,243 @@
+/*
+ * 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.Cacheable;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.validation.Valid;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.persistence.api.entity.anyobject.ADerAttr;
+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.ARelationship;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AVirAttr;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractAny;
+import org.apache.syncope.core.persistence.jpa.entity.JPAAnyType;
+import org.apache.syncope.core.persistence.jpa.entity.JPAAnyTypeClass;
+import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResource;
+
+@Entity
+@Table(name = JPAAnyObject.TABLE)
+@Cacheable
+public class JPAAnyObject extends AbstractAny<APlainAttr, ADerAttr, AVirAttr> implements AnyObject {
+
+    private static final long serialVersionUID = 9063766472970643492L;
+
+    public static final String TABLE = "AnyObject";
+
+    @Id
+    private Long id;
+
+    @ManyToOne(fetch = FetchType.EAGER, optional = false)
+    private JPAAnyType type;
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAAPlainAttr> plainAttrs = new ArrayList<>();
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAADerAttr> derAttrs = new ArrayList<>();
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "owner")
+    @Valid
+    private List<JPAAVirAttr> virAttrs = new ArrayList<>();
+
+    @ManyToMany(fetch = FetchType.EAGER)
+    @JoinTable(joinColumns =
+            @JoinColumn(name = "anyObject_id"),
+            inverseJoinColumns =
+            @JoinColumn(name = "resource_name"))
+    private List<JPAExternalResource> resources = new ArrayList<>();
+
+    @ManyToMany(fetch = FetchType.EAGER)
+    @JoinTable(joinColumns =
+            @JoinColumn(name = "anyObject_id"),
+            inverseJoinColumns =
+            @JoinColumn(name = "anyTypeClass_name"))
+    private List<JPAAnyTypeClass> auxClasses = new ArrayList<>();
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "leftEnd")
+    @Valid
+    private List<JPAARelationship> relationships = new ArrayList<>();
+
+    @OneToMany(cascade = CascadeType.ALL, mappedBy = "leftEnd")
+    @Valid
+    private List<JPAAMembership> memberships = new ArrayList<>();
+
+    @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
+    public AnyType getType() {
+        return type;
+    }
+
+    @Override
+    public void setType(final AnyType type) {
+        checkType(type, JPAAnyType.class);
+        this.type = (JPAAnyType) type;
+    }
+
+    @Override
+    public boolean add(final APlainAttr attr) {
+        checkType(attr, JPAAPlainAttr.class);
+        return plainAttrs.add((JPAAPlainAttr) attr);
+    }
+
+    @Override
+    public boolean remove(final APlainAttr attr) {
+        checkType(attr, JPAAPlainAttr.class);
+        return plainAttrs.remove((JPAAPlainAttr) attr);
+    }
+
+    @Override
+    public List<? extends APlainAttr> getPlainAttrs() {
+        return plainAttrs;
+    }
+
+    @Override
+    public boolean add(final ADerAttr attr) {
+        checkType(attr, JPAADerAttr.class);
+        return derAttrs.add((JPAADerAttr) attr);
+    }
+
+    @Override
+    public boolean remove(final ADerAttr attr) {
+        checkType(attr, JPAADerAttr.class);
+        return derAttrs.remove((JPAADerAttr) attr);
+    }
+
+    @Override
+    public List<? extends ADerAttr> getDerAttrs() {
+        return derAttrs;
+    }
+
+    @Override
+    public boolean add(final AVirAttr attr) {
+        checkType(attr, JPAAVirAttr.class);
+        return virAttrs.add((JPAAVirAttr) attr);
+    }
+
+    @Override
+    public boolean remove(final AVirAttr attr) {
+        checkType(attr, JPAAVirAttr.class);
+        return virAttrs.remove((JPAAVirAttr) attr);
+    }
+
+    @Override
+    public List<? extends AVirAttr> getVirAttrs() {
+        return virAttrs;
+    }
+
+    @Override
+    protected List<JPAExternalResource> internalGetResources() {
+        return resources;
+    }
+
+    @Override
+    public boolean add(final AnyTypeClass auxClass) {
+        checkType(auxClass, JPAAnyTypeClass.class);
+        return this.auxClasses.add((JPAAnyTypeClass) auxClass);
+    }
+
+    @Override
+    public boolean remove(final AnyTypeClass auxClass) {
+        checkType(auxClass, JPAAnyTypeClass.class);
+        return this.auxClasses.remove((JPAAnyTypeClass) auxClass);
+    }
+
+    @Override
+    public List<? extends AnyTypeClass> getAuxClasses() {
+        return auxClasses;
+    }
+
+    @Override
+    public boolean add(final ARelationship relationship) {
+        checkType(relationship, JPAARelationship.class);
+        return this.relationships.add((JPAARelationship) relationship);
+    }
+
+    @Override
+    public boolean remove(final ARelationship relationship) {
+        checkType(relationship, JPAARelationship.class);
+        return this.relationships.remove((JPAARelationship) relationship);
+    }
+
+    @Override
+    public ARelationship getRelationship(final AnyObject rightEnd) {
+        return CollectionUtils.find(getRelationships(), new Predicate<ARelationship>() {
+
+            @Override
+            public boolean evaluate(final ARelationship relationship) {
+                return rightEnd != null && rightEnd.equals(relationship.getRightEnd());
+            }
+        });
+    }
+
+    @Override
+    public List<? extends ARelationship> getRelationships() {
+        return relationships;
+    }
+
+    @Override
+    public boolean add(final AMembership membership) {
+        checkType(membership, JPAAMembership.class);
+        return this.memberships.add((JPAAMembership) membership);
+    }
+
+    @Override
+    public boolean remove(final AMembership membership) {
+        checkType(membership, JPAAMembership.class);
+        return this.memberships.remove((JPAAMembership) membership);
+    }
+
+    @Override
+    public AMembership getMembership(final Long groupKey) {
+        return CollectionUtils.find(getMemberships(), new Predicate<AMembership>() {
+
+            @Override
+            public boolean evaluate(final AMembership membership) {
+                return groupKey != null && groupKey.equals(membership.getRightEnd().getKey());
+            }
+        });
+    }
+
+    @Override
+    public List<? extends AMembership> getMemberships() {
+        return memberships;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttr.java
index 20e8d68..6fd6c1e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttr.java
@@ -24,20 +24,16 @@ import javax.persistence.CascadeType;
 import javax.persistence.Entity;
 import javax.persistence.FetchType;
 import javax.persistence.Id;
-import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.validation.Valid;
-import org.apache.syncope.core.persistence.api.entity.Attributable;
 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.CPlainAttrUniqueValue;
 import org.apache.syncope.core.persistence.api.entity.conf.CPlainAttrValue;
-import org.apache.syncope.core.persistence.api.entity.conf.CPlainSchema;
 import org.apache.syncope.core.persistence.api.entity.conf.Conf;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttr;
 
@@ -46,7 +42,7 @@ import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttr;
  */
 @Entity
 @Table(name = JPACPlainAttr.TABLE)
-public class JPACPlainAttr extends AbstractPlainAttr implements CPlainAttr {
+public class JPACPlainAttr extends AbstractPlainAttr<Conf> implements CPlainAttr {
 
     private static final long serialVersionUID = 8022331942314540648L;
 
@@ -65,18 +61,11 @@ public class JPACPlainAttr extends AbstractPlainAttr implements CPlainAttr {
     private JPAConf owner;
 
     /**
-     * The schema of this attribute.
-     */
-    @ManyToOne(fetch = FetchType.EAGER)
-    @JoinColumn(name = "schema_name")
-    private JPACPlainSchema schema;
-
-    /**
      * Values of this attribute (if schema is not UNIQUE).
      */
     @OneToMany(cascade = CascadeType.MERGE, orphanRemoval = true, mappedBy = "attribute")
     @Valid
-    private List<JPACPlainAttrValue> values;
+    private List<JPACPlainAttrValue> values = new ArrayList<>();
 
     /**
      * Value of this attribute (if schema is UNIQUE).
@@ -85,14 +74,6 @@ public class JPACPlainAttr extends AbstractPlainAttr implements CPlainAttr {
     @Valid
     private JPACPlainAttrUniqueValue uniqueValue;
 
-    /**
-     * Default constructor.
-     */
-    public JPACPlainAttr() {
-        super();
-        values = new ArrayList<>();
-    }
-
     @Override
     public Long getKey() {
         return id;
@@ -104,30 +85,19 @@ public class JPACPlainAttr extends AbstractPlainAttr implements CPlainAttr {
     }
 
     @Override
-    public void setOwner(final Attributable<?, ?, ?> owner) {
+    public void setOwner(final Conf owner) {
         checkType(owner, JPAConf.class);
         this.owner = (JPAConf) owner;
     }
 
     @Override
-    public CPlainSchema getSchema() {
-        return schema;
-    }
-
-    @Override
-    public void setSchema(final PlainSchema schema) {
-        checkType(schema, JPACPlainSchema.class);
-        this.schema = (JPACPlainSchema) schema;
-    }
-
-    @Override
-    protected boolean addValue(final PlainAttrValue attrValue) {
+    protected boolean addForMultiValue(final PlainAttrValue attrValue) {
         checkType(attrValue, JPACPlainAttrValue.class);
         return values.add((JPACPlainAttrValue) attrValue);
     }
 
     @Override
-    public boolean removeValue(final PlainAttrValue attrValue) {
+    public boolean remove(final PlainAttrValue attrValue) {
         checkType(attrValue, JPACPlainAttrValue.class);
         return values.remove((JPACPlainAttrValue) attrValue);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
index 097a046..4783911 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainAttrUniqueValue.java
@@ -28,8 +28,8 @@ 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.api.entity.conf.CPlainSchema;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainAttrValue;
+import org.apache.syncope.core.persistence.jpa.entity.JPAPlainSchema;
 
 @Entity
 @Table(name = JPACPlainAttrUniqueValue.TABLE)
@@ -47,7 +47,7 @@ public class JPACPlainAttrUniqueValue extends AbstractPlainAttrValue implements
 
     @ManyToOne(optional = false)
     @JoinColumn(name = "schema_name")
-    private JPACPlainSchema schema;
+    private JPAPlainSchema schema;
 
     @Override
     public Long getKey() {
@@ -66,13 +66,13 @@ public class JPACPlainAttrUniqueValue extends AbstractPlainAttrValue implements
     }
 
     @Override
-    public CPlainSchema getSchema() {
+    public PlainSchema getSchema() {
         return schema;
     }
 
     @Override
     public void setSchema(final PlainSchema schema) {
-        checkType(schema, JPACPlainSchema.class);
-        this.schema = (JPACPlainSchema) schema;
+        checkType(schema, JPAPlainSchema.class);
+        this.schema = (JPAPlainSchema) schema;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainSchema.java
deleted file mode 100644
index 590443b..0000000
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPACPlainSchema.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.persistence.jpa.entity.conf;
-
-import javax.persistence.Cacheable;
-import javax.persistence.Entity;
-import javax.persistence.Table;
-import org.apache.syncope.core.persistence.api.entity.conf.CPlainSchema;
-import org.apache.syncope.core.persistence.jpa.entity.AbstractPlainSchema;
-
-@Entity
-@Table(name = JPACPlainSchema.TABLE)
-@Cacheable
-public class JPACPlainSchema extends AbstractPlainSchema implements CPlainSchema {
-
-    private static final long serialVersionUID = 3363019039331594433L;
-
-    public static final String TABLE = "CPlainSchema";
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
index 13e529f..be3fa19 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/conf/JPAConf.java
@@ -28,16 +28,22 @@ import javax.persistence.Id;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.validation.Valid;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.DerAttr;
+import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.VirAttr;
 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.AbstractAttributable;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractAnnotatedEntity;
 
 @Entity
 @Table(name = JPAConf.TABLE)
 @Cacheable
-public class JPAConf extends AbstractAttributable<CPlainAttr, DerAttr, VirAttr> implements Conf {
+public class JPAConf extends AbstractAnnotatedEntity<Long> implements Conf {
 
     private static final long serialVersionUID = 7671699609879382195L;
 
@@ -67,50 +73,147 @@ public class JPAConf extends AbstractAttributable<CPlainAttr, DerAttr, VirAttr>
     }
 
     @Override
-    public boolean addPlainAttr(final CPlainAttr attr) {
+    public boolean add(final CPlainAttr attr) {
         checkType(attr, JPACPlainAttr.class);
         return plainAttrs.add((JPACPlainAttr) attr);
     }
 
     @Override
-    public boolean removePlainAttr(final CPlainAttr attr) {
+    public boolean remove(final CPlainAttr attr) {
         checkType(attr, JPACPlainAttr.class);
         return plainAttrs.remove((JPACPlainAttr) attr);
     }
 
     @Override
+    public CPlainAttr getPlainAttr(final String plainSchemaName) {
+        return CollectionUtils.find(plainAttrs, new Predicate<CPlainAttr>() {
+
+            @Override
+            public boolean evaluate(final CPlainAttr plainAttr) {
+                return plainAttr != null && plainAttr.getSchema() != null
+                        && plainSchemaName.equals(plainAttr.getSchema().getKey());
+            }
+        });
+    }
+
+    @Override
     public List<? extends CPlainAttr> getPlainAttrs() {
         return plainAttrs;
     }
 
     @Override
-    public boolean addDerAttr(final DerAttr attr) {
+    public boolean add(final DerAttr<?> attr) {
         return false;
     }
 
     @Override
-    public boolean removeDerAttr(final DerAttr derAttr) {
+    public boolean remove(final DerAttr<?> derAttr) {
         return false;
     }
 
     @Override
-    public List<? extends DerAttr> getDerAttrs() {
+    public DerAttr<?> getDerAttr(final String derSchemaName) {
+        return null;
+    }
+
+    @Override
+    public List<? extends DerAttr<?>> getDerAttrs() {
         return Collections.emptyList();
     }
 
     @Override
-    public boolean addVirAttr(final VirAttr attr) {
+    public boolean add(final VirAttr<?> attr) {
         return false;
     }
 
     @Override
-    public boolean removeVirAttr(final VirAttr virAttr) {
+    public boolean remove(final VirAttr<?> virAttr) {
         return false;
     }
 
     @Override
-    public List<? extends VirAttr> getVirAttrs() {
+    public VirAttr<?> getVirAttr(final String virSchemaName) {
+        return null;
+    }
+
+    @Override
+    public List<? extends VirAttr<?>> getVirAttrs() {
         return Collections.emptyList();
     }
 
+    @Override
+    public boolean add(final ExternalResource resource) {
+        return false;
+    }
+
+    @Override
+    public boolean remove(final ExternalResource resource) {
+        return false;
+    }
+
+    @Override
+    public List<String> getResourceNames() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public List<? extends ExternalResource> getResources() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public boolean add(final AnyTypeClass auxClass) {
+        return false;
+    }
+
+    @Override
+    public boolean remove(final AnyTypeClass auxClass) {
+        return false;
+    }
+
+    @Override
+    public List<? extends AnyTypeClass> getAuxClasses() {
+        return Collections.emptyList();
+    }
+
+    @Override
+    public String getWorkflowId() {
+        return null;
+    }
+
+    @Override
+    public void setWorkflowId(final String workflowId) {
+        // nothing to do
+    }
+
+    @Override
+    public String getStatus() {
+        return null;
+    }
+
+    @Override
+    public void setStatus(final String status) {
+        // nothing to do
+    }
+
+    @Override
+    public Realm getRealm() {
+        return null;
+    }
+
+    @Override
+    public void setRealm(final Realm realm) {
+        // nothing to do
+    }
+
+    @Override
+    public AnyType getType() {
+        return null;
+    }
+
+    @Override
+    public void setType(final AnyType type) {
+        // nothing to do
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/081d9a04/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
index 7a160cf..46fc1cd 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
@@ -18,23 +18,16 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.group;
 
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
 import javax.persistence.Entity;
 import javax.persistence.ManyToOne;
-import javax.persistence.OneToOne;
 import javax.persistence.Table;
-import org.apache.syncope.core.persistence.api.entity.Attributable;
-import org.apache.syncope.core.persistence.api.entity.DerSchema;
 import org.apache.syncope.core.persistence.api.entity.group.GDerAttr;
-import org.apache.syncope.core.persistence.api.entity.group.GDerAttrTemplate;
-import org.apache.syncope.core.persistence.api.entity.group.GDerSchema;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractDerAttr;
 
 @Entity
 @Table(name = JPAGDerAttr.TABLE)
-public class JPAGDerAttr extends AbstractDerAttr implements GDerAttr {
+public class JPAGDerAttr extends AbstractDerAttr<Group> implements GDerAttr {
 
     private static final long serialVersionUID = 8007080005675899946L;
 
@@ -43,40 +36,15 @@ public class JPAGDerAttr extends AbstractDerAttr implements GDerAttr {
     @ManyToOne
     private JPAGroup owner;
 
-    @Column(nullable = false)
-    @OneToOne(cascade = CascadeType.MERGE)
-    private JPAGDerAttrTemplate template;
-
     @Override
     public Group getOwner() {
         return owner;
     }
 
     @Override
-    public void setOwner(final Attributable<?, ?, ?> owner) {
+    public void setOwner(final Group owner) {
         checkType(owner, JPAGroup.class);
         this.owner = (JPAGroup) owner;
     }
 
-    @Override
-    public GDerAttrTemplate getTemplate() {
-        return template;
-    }
-
-    @Override
-    public void setTemplate(final GDerAttrTemplate template) {
-        checkType(template, JPAGDerAttrTemplate.class);
-        this.template = (JPAGDerAttrTemplate) template;
-    }
-
-    @Override
-    public GDerSchema getSchema() {
-        return template == null ? null : template.getSchema();
-    }
-
-    @Override
-    public void setSchema(final DerSchema schema) {
-        LOG.warn("This is group attribute, set template to select schema");
-    }
-
 }