package org.keycloak.models.cache;

import org.keycloak.models.ApplicationModel;
import org.keycloak.models.AuthenticationLinkModel;
import org.keycloak.models.AuthenticationProviderModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.PasswordPolicy;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RequiredCredentialModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.SocialLinkModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserCredentialValueModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.models.UsernameLoginFailureModel;
import org.keycloak.models.cache.entities.CachedApplicationRole;
import org.keycloak.models.cache.entities.CachedRealm;
import org.keycloak.models.cache.entities.CachedRealmRole;
import org.keycloak.models.cache.entities.CachedRole;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
import org.keycloak.models.utils.TimeBasedOTP;

import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
 * @version $Revision: 1 $
 */
public class RealmAdapter implements RealmModel {
    protected CachedRealm cached;
    protected CacheKeycloakSession cacheSession;
    protected RealmModel updated;
    protected KeycloakCache cache;
    protected volatile transient PublicKey publicKey;
    protected volatile transient PrivateKey privateKey;

    public RealmAdapter(CachedRealm cached, CacheKeycloakSession cacheSession) {
        this.cached = cached;
        this.cacheSession = cacheSession;
    }

    @Override
    public String getId() {
        if (updated != null) return updated.getId();
        return cached.getId();
    }

    @Override
    public String getName() {
        if (updated != null) return updated.getName();
        return cached.getName();
    }

    @Override
    public void setName(String name) {
        getDelegateForUpdate();
        updated.setName(name);
    }

    protected void getDelegateForUpdate() {
        if (updated == null) {
            updated = cacheSession.getDelegate().getRealm(getId());
            if (updated == null) throw new IllegalStateException("Not found in database");
        }
    }

    @Override
    public boolean isEnabled() {
        if (updated != null) return updated.isEnabled();
        return cached.isEnabled();
    }

    @Override
    public void setEnabled(boolean enabled) {
        getDelegateForUpdate();
        updated.setEnabled(enabled);
    }

    @Override
    public boolean isSslNotRequired() {
        if (updated != null) return updated.isSslNotRequired();
        return cached.isSslNotRequired();
    }

    @Override
    public void setSslNotRequired(boolean sslNotRequired) {
        getDelegateForUpdate();
        updated.setSslNotRequired(sslNotRequired);
    }

    @Override
    public boolean isRegistrationAllowed() {
        if (updated != null) return updated.isRegistrationAllowed();
        return cached.isRegistrationAllowed();
    }

    @Override
    public void setRegistrationAllowed(boolean registrationAllowed) {
        getDelegateForUpdate();
        updated.setRegistrationAllowed(registrationAllowed);
    }

    @Override
    public boolean isPasswordCredentialGrantAllowed() {
        if (updated != null) return updated.isPasswordCredentialGrantAllowed();
        return cached.isPasswordCredentialGrantAllowed();
    }

    @Override
    public void setPasswordCredentialGrantAllowed(boolean passwordCredentialGrantAllowed) {
        getDelegateForUpdate();
        updated.setPasswordCredentialGrantAllowed(passwordCredentialGrantAllowed);
    }

    @Override
    public boolean isRememberMe() {
        if (updated != null) return updated.isRememberMe();
        return cached.isRememberMe();
    }

    @Override
    public void setRememberMe(boolean rememberMe) {
        getDelegateForUpdate();
        updated.setRememberMe(rememberMe);
    }

    @Override
    public boolean isBruteForceProtected() {
        if (updated != null) return updated.isBruteForceProtected();
        return cached.isBruteForceProtected();
    }

    @Override
    public void setBruteForceProtected(boolean value) {
        getDelegateForUpdate();
        updated.setBruteForceProtected(value);
    }

    @Override
    public int getMaxFailureWaitSeconds() {
        if (updated != null) return updated.getMaxFailureWaitSeconds();
        return cached.getMaxFailureWaitSeconds();
    }

    @Override
    public void setMaxFailureWaitSeconds(int val) {
        getDelegateForUpdate();
        updated.setMaxFailureWaitSeconds(val);
    }

    @Override
    public int getWaitIncrementSeconds() {
        if (updated != null) return updated.getWaitIncrementSeconds();
        return cached.getWaitIncrementSeconds();
    }

    @Override
    public void setWaitIncrementSeconds(int val) {
        getDelegateForUpdate();
        updated.setWaitIncrementSeconds(val);
    }

    @Override
    public int getMinimumQuickLoginWaitSeconds() {
        if (updated != null) return updated.getMinimumQuickLoginWaitSeconds();
        return cached.getMinimumQuickLoginWaitSeconds();
    }

    @Override
    public void setMinimumQuickLoginWaitSeconds(int val) {
        getDelegateForUpdate();
        updated.setMinimumQuickLoginWaitSeconds(val);
    }

    @Override
    public long getQuickLoginCheckMilliSeconds() {
        if (updated != null) return updated.getQuickLoginCheckMilliSeconds();
        return cached.getQuickLoginCheckMilliSeconds();
    }

    @Override
    public void setQuickLoginCheckMilliSeconds(long val) {
        getDelegateForUpdate();
        updated.setQuickLoginCheckMilliSeconds(val);
    }

    @Override
    public int getMaxDeltaTimeSeconds() {
        if (updated != null) return updated.getMaxDeltaTimeSeconds();
        return cached.getMaxDeltaTimeSeconds();
    }

    @Override
    public void setMaxDeltaTimeSeconds(int val) {
        getDelegateForUpdate();
        updated.setMaxDeltaTimeSeconds(val);
    }

    @Override
    public int getFailureFactor() {
        if (updated != null) return updated.getFailureFactor();
        return cached.getFailureFactor();
    }

    @Override
    public void setFailureFactor(int failureFactor) {
        getDelegateForUpdate();
        updated.setFailureFactor(failureFactor);
    }

    @Override
    public boolean isVerifyEmail() {
        if (updated != null) return updated.isVerifyEmail();
        return cached.isVerifyEmail();
    }

    @Override
    public void setVerifyEmail(boolean verifyEmail) {
        getDelegateForUpdate();
        updated.setVerifyEmail(verifyEmail);
    }

    @Override
    public boolean isResetPasswordAllowed() {
        if (updated != null) return updated.isResetPasswordAllowed();
        return cached.isResetPasswordAllowed();
    }

    @Override
    public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
        getDelegateForUpdate();
        updated.setResetPasswordAllowed(resetPasswordAllowed);
    }

    @Override
    public int getSsoSessionIdleTimeout() {
        if (updated != null) return updated.getSsoSessionIdleTimeout();
        return cached.getSsoSessionIdleTimeout();
    }

    @Override
    public void setSsoSessionIdleTimeout(int seconds) {
        getDelegateForUpdate();
        updated.setSsoSessionIdleTimeout(seconds);
    }

    @Override
    public int getSsoSessionMaxLifespan() {
        if (updated != null) return updated.getSsoSessionMaxLifespan();
        return cached.getSsoSessionMaxLifespan();
    }

    @Override
    public void setSsoSessionMaxLifespan(int seconds) {
        getDelegateForUpdate();
        updated.setSsoSessionMaxLifespan(seconds);
    }

    @Override
    public int getAccessTokenLifespan() {
        if (updated != null) return updated.getAccessTokenLifespan();
        return cached.getAccessTokenLifespan();
    }

    @Override
    public void setAccessTokenLifespan(int seconds) {
        getDelegateForUpdate();
        updated.setAccessTokenLifespan(seconds);
    }

    @Override
    public int getAccessCodeLifespan() {
        if (updated != null) return updated.getAccessCodeLifespan();
        return cached.getAccessCodeLifespan();
    }

    @Override
    public void setAccessCodeLifespan(int seconds) {
        getDelegateForUpdate();
        updated.setAccessCodeLifespan(seconds);
    }

    @Override
    public int getAccessCodeLifespanUserAction() {
        if (updated != null) return updated.getAccessCodeLifespanUserAction();
        return cached.getAccessCodeLifespanUserAction();
    }

    @Override
    public void setAccessCodeLifespanUserAction(int seconds) {
        getDelegateForUpdate();
        updated.setAccessCodeLifespanUserAction(seconds);
    }

    @Override
    public String getPublicKeyPem() {
        if (updated != null) return updated.getPublicKeyPem();
        return cached.getPublicKeyPem();
    }

    @Override
    public void setPublicKeyPem(String publicKeyPem) {
        getDelegateForUpdate();
        updated.setPublicKeyPem(publicKeyPem);
    }

    @Override
    public String getPrivateKeyPem() {
        if (updated != null) return updated.getPrivateKeyPem();
        return cached.getPrivateKeyPem();
    }

    @Override
    public void setPrivateKeyPem(String privateKeyPem) {
        getDelegateForUpdate();
        updated.setPrivateKeyPem(privateKeyPem);
    }

    @Override
    public PublicKey getPublicKey() {
        if (publicKey != null) return publicKey;
        publicKey = KeycloakModelUtils.getPublicKey(getPublicKeyPem());
        return publicKey;
    }

    @Override
    public void setPublicKey(PublicKey publicKey) {
        this.publicKey = publicKey;
        String publicKeyPem = KeycloakModelUtils.getPemFromKey(publicKey);
        setPublicKeyPem(publicKeyPem);
    }

    @Override
    public PrivateKey getPrivateKey() {
        if (privateKey != null) return privateKey;
        privateKey = KeycloakModelUtils.getPrivateKey(getPrivateKeyPem());
        return privateKey;
    }

    @Override
    public void setPrivateKey(PrivateKey privateKey) {
        this.privateKey = privateKey;
        String privateKeyPem = KeycloakModelUtils.getPemFromKey(privateKey);
        setPrivateKeyPem(privateKeyPem);
    }

    @Override
    public List<RequiredCredentialModel> getRequiredCredentials() {

        List<RequiredCredentialModel> copy = new LinkedList<RequiredCredentialModel>();
        if (updated != null) copy.addAll(updated.getRequiredCredentials());
        else copy.addAll(cached.getRequiredCredentials());
        return copy;
    }

    @Override
    public void addRequiredCredential(String cred) {
        getDelegateForUpdate();
        updated.addRequiredCredential(cred);
    }

    @Override
    public PasswordPolicy getPasswordPolicy() {
        if (updated != null) return updated.getPasswordPolicy();
        return cached.getPasswordPolicy();
    }

    @Override
    public void setPasswordPolicy(PasswordPolicy policy) {
        getDelegateForUpdate();
        updated.setPasswordPolicy(policy);
    }

    @Override
    public boolean validatePassword(UserModel user, String password) {
        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
            if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
                return new Pbkdf2PasswordEncoder(cred.getSalt()).verify(password, cred.getValue());

            }
        }
        return false;
    }

    @Override
    public boolean validateTOTP(UserModel user, String password, String token) {
        if (!validatePassword(user, password)) return false;
        for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
            if (cred.getType().equals(UserCredentialModel.TOTP)) {
                return new TimeBasedOTP().validate(token, cred.getValue().getBytes());
            }
        }
        return false;
    }

    @Override
    public UserModel getUser(String name) {
        return cacheSession.getUserByUsername(name, this);
    }

    @Override
    public UserModel getUserByEmail(String email) {
        return cacheSession.getUserByEmail(email, this);
    }

    @Override
    public UserModel getUserById(String id) {
        return cacheSession.getUserById(id, this);
    }

    @Override
    public UserModel addUser(String id, String username) {
        getDelegateForUpdate();
        return updated.addUser(id, username);
    }

    @Override
    public UserModel addUser(String username) {
        getDelegateForUpdate();
        return updated.addUser(username);
    }

    @Override
    public boolean removeUser(String name) {
        getDelegateForUpdate();
        return updated.removeUser(name);
    }

    @Override
    public RoleModel getRoleById(String id) {
        if (updated != null) return updated.getRoleById(id);
        if (!cached.getRolesById().contains(id)) return null;
        CachedRole cachedRole = cache.getRole(id);
        if (cachedRole == null) {
            RoleModel roleModel = cacheSession.getDelegate().getRoleById(id, this);
            if (roleModel == null) return null;
            if (roleModel.getContainer() instanceof ApplicationModel) {
                cachedRole = new CachedApplicationRole(((ApplicationModel) roleModel.getContainer()).getId(), roleModel);
                cache.addCachedRole(cachedRole);
            } else {
                cachedRole = new CachedRealmRole(roleModel);
            }
        }
        return new RoleAdapter(cachedRole, cache, cacheSession, this);
    }

    @Override
    public List<String> getDefaultRoles() {
        if (updated != null) return updated.getDefaultRoles();
        return cached.getDefaultRoles();
    }

    @Override
    public void addDefaultRole(String name) {
        getDelegateForUpdate();
        updated.addDefaultRole(name);
    }

    @Override
    public void updateDefaultRoles(String[] defaultRoles) {
        getDelegateForUpdate();
        updated.updateDefaultRoles(defaultRoles);
    }

    @Override
    public ClientModel findClient(String clientId) {
        if (updated != null) return updated.findClient(clientId);
        String appId = cached.getApplications().get(clientId);
        if (appId != null) {
            return cacheSession.getApplicationById(appId, this);
        }
        String oauth = cached.getClients().get(clientId);
        if (oauth != null) {
            return cacheSession.getOAuthClientById(oauth, this);
        }
        return null;
    }

    @Override
    public Map<String, ApplicationModel> getApplicationNameMap() {
        if (updated != null) return updated.getApplicationNameMap();
        Map<String, ApplicationModel> map = new HashMap<String, ApplicationModel>();
        for (String id : cached.getApplications().values()) {
            ApplicationModel model = cacheSession.getApplicationById(id, this);
            if (model == null) {
                throw new IllegalStateException("Cached application not found: " + id);
            }
            map.put(model.getName(), model);
        }
        return map;
    }

    @Override
    public List<ApplicationModel> getApplications() {
        if (updated != null) return updated.getApplications();
        List<ApplicationModel> apps = new LinkedList<ApplicationModel>();
        for (String id : cached.getApplications().values()) {
            ApplicationModel model = cacheSession.getApplicationById(id, this);
            if (model == null) {
                throw new IllegalStateException("Cached application not found: " + id);
            }
            apps.add(model);
        }
        return apps;

    }

    @Override
    public ApplicationModel addApplication(String name) {
        getDelegateForUpdate();
        return updated.addApplication(name);
    }

    @Override
    public ApplicationModel addApplication(String id, String name) {
        getDelegateForUpdate();
        return updated.addApplication(id, name);
    }

    @Override
    public boolean removeApplication(String id) {
        getDelegateForUpdate();
        return updated.removeApplication(id);
    }

    @Override
    public ApplicationModel getApplicationById(String id) {
        if (updated != null) return updated.getApplicationById(id);
        return cacheSession.getApplicationById(id, this);
    }

    @Override
    public ApplicationModel getApplicationByName(String name) {
        if (updated != null) return updated.getApplicationByName(name);
        String id = cached.getApplications().get(name);
        if (id == null) return null;
        return getApplicationById(id);
    }

    @Override
    public void updateRequiredCredentials(Set<String> creds) {
        getDelegateForUpdate();
        updated.updateRequiredCredentials(creds);
    }

    @Override
    public UserModel getUserBySocialLink(SocialLinkModel socialLink) {
        if (updated != null) return updated.getUserBySocialLink(socialLink);
        return cacheSession.getUserBySocialLink(socialLink, this);
    }

    @Override
    public Set<SocialLinkModel> getSocialLinks(UserModel user) {
        if (updated != null) return updated.getSocialLinks(user);
        return cacheSession.getSocialLinks(user, this);
    }

    @Override
    public SocialLinkModel getSocialLink(UserModel user, String socialProvider) {
        if (updated != null) return updated.getSocialLink(user, socialProvider);
        return cacheSession.getSocialLink(user, socialProvider, this);
    }

    @Override
    public void addSocialLink(UserModel user, SocialLinkModel socialLink) {
        getDelegateForUpdate();
        updated.addSocialLink(user, socialLink);
    }

    @Override
    public boolean removeSocialLink(UserModel user, String socialProvider) {
        getDelegateForUpdate();
        return updated.removeSocialLink(user, socialProvider);
    }

    @Override
    public AuthenticationLinkModel getAuthenticationLink(UserModel user) {
        if (updated != null) return updated.getAuthenticationLink(user);
        return cacheSession.getAuthenticationLink(user, this);
    }

    @Override
    public void setAuthenticationLink(UserModel user, AuthenticationLinkModel authenticationLink) {
        getDelegateForUpdate();
        updated.setAuthenticationLink(user, authenticationLink);
    }

    @Override
    public boolean isSocial() {
        if (updated != null) return updated.isSocial();
        return cached.isSocial();
    }

    @Override
    public void setSocial(boolean social) {
        getDelegateForUpdate();
        updated.setSocial(social);
    }

    @Override
    public boolean isUpdateProfileOnInitialSocialLogin() {
        if (updated != null) return updated.isUpdateProfileOnInitialSocialLogin();
        return cached.isUpdateProfileOnInitialSocialLogin();
    }

    @Override
    public void setUpdateProfileOnInitialSocialLogin(boolean updateProfileOnInitialSocialLogin) {
        getDelegateForUpdate();
        updated.setUpdateProfileOnInitialSocialLogin(updateProfileOnInitialSocialLogin);
    }

    @Override
    public List<UserModel> getUsers() {
        if (updated != null) return updated.getUsers();
        return cacheSession.getUsers(this);
    }

    @Override
    public List<UserModel> searchForUser(String search) {
        if (updated != null) return updated.searchForUser(search);
        return cacheSession.searchForUser(search, this);
    }

    @Override
    public List<UserModel> searchForUserByAttributes(Map<String, String> attributes) {
        if (updated != null) return updated.searchForUserByAttributes(attributes);
        return cacheSession.searchForUserByAttributes(attributes, this);
    }

    @Override
    public OAuthClientModel addOAuthClient(String name) {
        getDelegateForUpdate();
        return updated.addOAuthClient(name);
    }

    @Override
    public OAuthClientModel addOAuthClient(String id, String name) {
        getDelegateForUpdate();
        return updated.addOAuthClient(id, name);
    }

    @Override
    public OAuthClientModel getOAuthClient(String name) {
        if (updated != null) return updated.getOAuthClient(name);
        String id = cached.getClients().get(name);
        if (id == null) return null;
        return getOAuthClientById(id);
    }

    @Override
    public OAuthClientModel getOAuthClientById(String id) {
        if (updated != null) return updated.getOAuthClientById(id);
        return cacheSession.getOAuthClientById(id, this);
    }

    @Override
    public boolean removeOAuthClient(String id) {
        getDelegateForUpdate();
        return updated.removeOAuthClient(id);
    }

    @Override
    public List<OAuthClientModel> getOAuthClients() {
        if (updated != null) return updated.getOAuthClients();
        List<OAuthClientModel> clients = new LinkedList<OAuthClientModel>();
        for (String id : cached.getClients().values()) {
            OAuthClientModel model = cacheSession.getOAuthClientById(id, this);
            if (model == null) {
                throw new IllegalStateException("Cached oauth client not found: " + id);
            }
            clients.add(model);
        }
        return clients;
    }

    @Override
    public Map<String, String> getSmtpConfig() {
        if (updated != null) return updated.getSmtpConfig();
        return cached.getSmtpConfig();
    }

    @Override
    public void setSmtpConfig(Map<String, String> smtpConfig) {
        getDelegateForUpdate();
        updated.setSmtpConfig(smtpConfig);
    }

    @Override
    public Map<String, String> getSocialConfig() {
        if (updated != null) return updated.getSocialConfig();
        return cached.getSocialConfig();
    }

    @Override
    public void setSocialConfig(Map<String, String> socialConfig) {
        getDelegateForUpdate();
        updated.setSocialConfig(socialConfig);
    }

    @Override
    public Map<String, String> getLdapServerConfig() {
        if (updated != null) return updated.getLdapServerConfig();
        return cached.getLdapServerConfig();
    }

    @Override
    public void setLdapServerConfig(Map<String, String> ldapServerConfig) {
        getDelegateForUpdate();
        updated.setLdapServerConfig(ldapServerConfig);
    }

    @Override
    public List<AuthenticationProviderModel> getAuthenticationProviders() {
        if (updated != null) return updated.getAuthenticationProviders();
        return cached.getAuthenticationProviders();
    }

    @Override
    public void setAuthenticationProviders(List<AuthenticationProviderModel> authenticationProviders) {
        getDelegateForUpdate();
        updated.setAuthenticationProviders(authenticationProviders);
    }

    @Override
    public String getLoginTheme() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void setLoginTheme(String name) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public String getAccountTheme() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void setAccountTheme(String name) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public String getAdminTheme() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void setAdminTheme(String name) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public String getEmailTheme() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void setEmailTheme(String name) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public int getNotBefore() {
        return 0;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void setNotBefore(int notBefore) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public boolean removeRoleById(String id) {
        return false;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public boolean isAuditEnabled() {
        return false;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void setAuditEnabled(boolean enabled) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public long getAuditExpiration() {
        return 0;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void setAuditExpiration(long expiration) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Set<String> getAuditListeners() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void setAuditListeners(Set<String> listeners) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public ApplicationModel getMasterAdminApp() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void setMasterAdminApp(ApplicationModel app) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public UsernameLoginFailureModel getUserLoginFailure(String username) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public UsernameLoginFailureModel addUserLoginFailure(String username) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public List<UsernameLoginFailureModel> getAllUserLoginFailures() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public UserSessionModel createUserSession(UserModel user, String ipAddress) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public UserSessionModel getUserSession(String id) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public List<UserSessionModel> getUserSessions(UserModel user) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void removeUserSession(UserSessionModel session) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void removeUserSessions(UserModel user) {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void removeExpiredUserSessions() {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public ClientModel findClientById(String id) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void removeUserSessions() {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public RoleModel getRole(String name) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public RoleModel addRole(String name) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public RoleModel addRole(String id, String name) {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public boolean removeRole(RoleModel role) {
        return false;  //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public Set<RoleModel> getRoles() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

}
