/*******************************************************************************
 * Copyright (c) 2008-2011 Chair for Applied Software Engineering,
 * Technische Universitaet Muenchen.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * Otto von Wesendonk - initial API and implementation
 ******************************************************************************/
package org.eclipse.emf.emfstore.internal.server.core;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.emfstore.internal.common.APIUtil;
import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.internal.server.AdminEmfStore;
import org.eclipse.emf.emfstore.internal.server.accesscontrol.AccessControl;
import org.eclipse.emf.emfstore.internal.server.connection.xmlrpc.util.ShareProjectAdapter;
import org.eclipse.emf.emfstore.internal.server.exceptions.AccessControlException;
import org.eclipse.emf.emfstore.internal.server.exceptions.FatalESException;
import org.eclipse.emf.emfstore.internal.server.exceptions.InvalidInputException;
import org.eclipse.emf.emfstore.internal.server.exceptions.StorageException;
import org.eclipse.emf.emfstore.internal.server.model.ModelFactory;
import org.eclipse.emf.emfstore.internal.server.model.ProjectHistory;
import org.eclipse.emf.emfstore.internal.server.model.ProjectId;
import org.eclipse.emf.emfstore.internal.server.model.ProjectInfo;
import org.eclipse.emf.emfstore.internal.server.model.ServerSpace;
import org.eclipse.emf.emfstore.internal.server.model.SessionId;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACGroup;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACOrgUnit;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACOrgUnitId;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACUser;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.AccesscontrolFactory;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.roles.Role;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.roles.RolesFactory;
import org.eclipse.emf.emfstore.internal.server.model.accesscontrol.roles.RolesPackage;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESGroupImpl;
import org.eclipse.emf.emfstore.internal.server.model.impl.api.ESUserImpl;
import org.eclipse.emf.emfstore.server.auth.ESAuthorizationService;
import org.eclipse.emf.emfstore.server.auth.ESProjectAdminPrivileges;
import org.eclipse.emf.emfstore.server.exceptions.ESException;
import org.eclipse.emf.emfstore.server.model.ESGroup;
import org.eclipse.emf.emfstore.server.model.ESSessionId;
import org.eclipse.emf.emfstore.server.model.ESUser;

/**
 * Implementation of {@link AdminEmfStore} interface.
 *
 * @author wesendon
 */
// TODO: bring this interface in new subinterface structure and refactor it
public class AdminEmfStoreImpl extends AbstractEmfstoreInterface implements AdminEmfStore {

	/**
	 * Default constructor.
	 *
	 * @param serverSpace
	 *            the server space
	 * @param accessControl
	 *            the authorization control
	 * @throws FatalESException
	 *             in case of failure
	 */
	public AdminEmfStoreImpl(ServerSpace serverSpace,
		AccessControl accessControl)
			throws FatalESException {
		super(serverSpace, accessControl);
	}

	/**
	 * {@inheritDoc}
	 */
	public List<ACGroup> getGroups(SessionId sessionId) throws ESException {
		checkForNulls(sessionId);

		checkProjectAdminAccess(sessionId);

		final List<ACGroup> result = new ArrayList<ACGroup>();
		for (final ACGroup group : getGroups()) {
			// quickfix
			final ACGroup copy = ModelUtil.clone(group);
			clearMembersFromGroup(copy);
			result.add(copy);
		}
		return result;
	}

	private List<ACGroup> getGroups() {
		final List<ACGroup> groups = new ArrayList<ACGroup>();
		for (final ESGroup group : getAccessControl().getOrgUnitProviderService().getGroups()) {
			groups.add((ACGroup) ESGroupImpl.class.cast(group).toInternalAPI());
		}
		return groups;
	}

	private List<ACUser> getUsers() {
		final List<ACUser> users = new ArrayList<ACUser>();
		for (final ESUser user : getAccessControl().getOrgUnitProviderService().getUsers()) {
			users.add((ACUser) ESUserImpl.class.cast(user).toInternalAPI());
		}
		return users;
	}

	/**
	 * {@inheritDoc}
	 */
	public List<ACGroup> getGroups(SessionId sessionId, ACOrgUnitId orgUnitId) throws ESException {
		checkForNulls(sessionId, orgUnitId);
		getAccessControl().getAuthorizationService().checkProjectAdminAccess(
			sessionId.toAPI(),
			null);
		final List<ACGroup> result = new ArrayList<ACGroup>();
		final ACOrgUnit<?> orgUnit = getOrgUnit(orgUnitId);
		for (final ACGroup group : getGroups()) {
			if (group.getMembers().contains(orgUnit)) {
				// quickfix
				final ACGroup copy = ModelUtil.clone(group);
				clearMembersFromGroup(copy);
				result.add(copy);
			}
		}
		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	public ACOrgUnitId createGroup(SessionId sessionId, String name) throws ESException {

		checkForNulls(sessionId, name);
		getAccessControl().getAuthorizationService().checkProjectAdminAccess(
			sessionId.toAPI(),
			null,
			ESProjectAdminPrivileges.CreateGroup);

		if (groupExists(name)) {
			throw new InvalidInputException(Messages.AdminEmfStoreImpl_Group_Already_Exists);
		}

		final ACGroup acGroup = AccesscontrolFactory.eINSTANCE.createACGroup();
		acGroup.setName(name);
		acGroup.setDescription(StringUtils.EMPTY);
		getAccessControl().getOrgUnitProviderService().addGroup(acGroup.toAPI());
		save();
		return ModelUtil.clone(acGroup.getId());
	}

	private boolean groupExists(String name) {
		for (final ACGroup group : getGroups()) {
			if (group.getName().equals(name)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	public void removeGroup(SessionId sessionId, ACOrgUnitId user, ACOrgUnitId group) throws ESException {

		checkForNulls(sessionId, user, group);

		final boolean isServerAdmin = getAccessControl().getAuthorizationService().checkProjectAdminAccess(
			sessionId.toAPI(),
			null,
			ESProjectAdminPrivileges.DeleteOrgUnit);

		if (!isServerAdmin) {
			getAccessControl().getAuthorizationService().checkProjectAdminAccessForOrgUnit(
				sessionId.toAPI(),
				group.toAPI());
		}

		getGroup(group).getMembers().remove(getOrgUnit(user));
		save();
	}

	/**
	 * {@inheritDoc}
	 */
	public void deleteGroup(SessionId sessionId, ACOrgUnitId groupId) throws ESException {

		checkForNulls(sessionId, groupId);

		final ESAuthorizationService authorizationService = getAccessControl().getAuthorizationService();

		authorizationService.checkProjectAdminAccess(
			sessionId.toAPI(),
			null,
			ESProjectAdminPrivileges.DeleteOrgUnit);
		authorizationService.checkProjectAdminAccessForOrgUnit(
			sessionId.toAPI(),
			groupId.toAPI());

		// also check all members
		final ACGroup group = getGroup(groupId);
		for (final ACOrgUnit<?> member : group.getMembers()) {
			authorizationService.checkProjectAdminAccessForOrgUnit(
				sessionId.toAPI(),
				member.getId().toAPI());
		}

		for (final Iterator<ACGroup> iter = getGroups().iterator(); iter.hasNext();) {
			final ACGroup nextGroup = iter.next();
			final List<ACGroup> groups = getGroups(sessionId, groupId);
			if (nextGroup.getId().equals(groupId)) {
				for (final ACGroup acGroup : groups) {
					removeMember(sessionId, acGroup.getId(), nextGroup.getId());
				}
				getAccessControl().getOrgUnitProviderService().removeGroup(nextGroup.toAPI());
				EcoreUtil.delete(nextGroup);
				save();
				return;
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("rawtypes")
	public List<ACOrgUnit> getMembers(SessionId sessionId, ACOrgUnitId groupId) throws ESException {

		checkForNulls(sessionId, groupId);

		getAccessControl().getAuthorizationService().checkProjectAdminAccess(
			sessionId.toAPI(),
			null);

		// quickfix
		final List<ACOrgUnit> result = new ArrayList<ACOrgUnit>();
		for (final ACOrgUnit orgUnit : getGroup(groupId).getMembers()) {
			result.add(ModelUtil.clone(orgUnit));
		}
		clearMembersFromGroups(result);
		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	public void addMember(SessionId sessionId, ACOrgUnitId groupId, ACOrgUnitId member) throws ESException {

		checkForNulls(sessionId, groupId, member);

		final ESAuthorizationService authorizationService = getAccessControl().getAuthorizationService();

		final boolean isServerAdmin = authorizationService.checkProjectAdminAccess(
			sessionId.toAPI(),
			null,
			ESProjectAdminPrivileges.ChangeAssignmentsOfOrgUnits);

		if (!isServerAdmin) {
			authorizationService.checkProjectAdminAccessForOrgUnit(
				sessionId.toAPI(),
				groupId.toAPI());
		}

		addToGroup(groupId, member);
	}

	private void addToGroup(ACOrgUnitId group, ACOrgUnitId member) throws ESException {
		final ACGroup acGroup = getGroup(group);
		final ACOrgUnit<?> acMember = getOrgUnit(member);
		acGroup.getMembers().add(acMember);
		save();
	}

	/**
	 * {@inheritDoc}
	 */
	public void removeMember(SessionId sessionId, ACOrgUnitId group, ACOrgUnitId member) throws ESException {

		checkForNulls(sessionId, group, member);

		final ESAuthorizationService authorizationService = getAccessControl().getAuthorizationService();

		final boolean isServerAdmin = authorizationService.checkProjectAdminAccess(
			sessionId.toAPI(),
			null,
			ESProjectAdminPrivileges.ChangeAssignmentsOfOrgUnits);

		if (!isServerAdmin) {
			authorizationService.checkProjectAdminAccessForOrgUnit(
				sessionId.toAPI(),
				group.toAPI());
		}

		removeFromGroup(group, member);
	}

	private void removeFromGroup(ACOrgUnitId group, ACOrgUnitId member) throws ESException {
		final ACGroup acGroup = getGroup(group);
		final ACOrgUnit<?> acMember = getOrgUnit(member);
		if (acGroup.getMembers().contains(acMember)) {
			acGroup.getMembers().remove(acMember);
			save();
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("rawtypes")
	public List<ACOrgUnit> getParticipants(SessionId sessionId, ProjectId projectId) throws ESException {

		checkForNulls(sessionId);
		checkProjectAdminAccess(sessionId, projectId);

		final List<ACOrgUnit> result = new ArrayList<ACOrgUnit>();

		for (final ACOrgUnit<ESUser> orgUnit : getUsers()) {
			final List<Role> roles = orgUnit.getRoles();
			for (final Role role : roles) {
				if (isServerAdmin(role) || role.getProjects().contains(projectId)) {
					result.add(ModelUtil.clone(orgUnit));
				}
			}
		}

		for (final ACOrgUnit<ESGroup> orgUnit : getGroups()) {
			final List<Role> roles = orgUnit.getRoles();
			for (final Role role : roles) {
				if (isServerAdmin(role) || role.getProjects().contains(projectId)) {
					result.add(ModelUtil.clone(orgUnit));
				}
			}
		}

		// quickfix
		clearMembersFromGroups(result);
		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	public void addParticipant(SessionId sessionId, ProjectId projectId, ACOrgUnitId participantId, EClass roleClass)
		throws ESException {

		checkForNulls(sessionId, projectId, participantId, roleClass);

		final boolean isServerAdmin = getAccessControl().getAuthorizationService()
			.checkProjectAdminAccess(
				sessionId.toAPI(),
				projectId.toAPI(),
				ESProjectAdminPrivileges.AssignRoleToOrgUnit);

		if (!isServerAdmin && roleClass.equals(RolesPackage.eINSTANCE.getServerAdmin())) {
			throw new AccessControlException(
				Messages.AdminEmfStoreImpl_Not_Allowed_To_Create_Participant_With_ServerAdminRole);
		}

		projectId = getProjectId(projectId);
		final ACOrgUnit<?> orgUnit = getOrgUnit(participantId);
		final List<Role> roles = orgUnit.getRoles();
		for (final Role role : roles) {
			if (role.getProjects().contains(projectId)) {
				return;
			}
		}
		// check whether role exists
		final List<Role> roles2 = orgUnit.getRoles();
		for (final Role role : roles2) {
			if (areEqual(role, roleClass)) {
				role.getProjects().add(ModelUtil.clone(projectId));
				save();
				return;
			}
		}

		final Role newRole = createRoleFromEClass(roleClass);

		newRole.getProjects().add(ModelUtil.clone(projectId));
		orgUnit.getRoles().add(newRole);
		save();
	}

	/**
	 * {@inheritDoc}
	 */
	public void addInitialParticipant(SessionId sessionId, ProjectId projectId, ACOrgUnitId participantId,
		EClass roleClass) throws ESException {

		checkForNulls(sessionId, projectId, participantId, roleClass);
		checkSession(sessionId);

		// check if requested role is the server administrator role, which we never allow to be assigned via this call
		if (isServerAdminRole(roleClass)) {
			throw new AccessControlException(Messages.AdminEmfStoreImpl_Not_Allowed_To_Assign_ServerAdminRole);
		}

		final SessionId session = resolveSessionById(sessionId.getId());
		final ACUser resolvedUser = resolveUserBySessionId(session.getId());

		if (!resolvedUser.getId().equals(participantId)) {
			throw new AccessControlException(Messages.AdminEmfStoreImpl_OnlyAllowedForRequstingUser);
		}

		// Checks if the user is a project administrator and whether the ShareProject privilege
		// has been set in the es.properties. This method will throw an exception
		// if the user is either not a project administrator or the ShareProject privilege has not been set.
		checkProjectAdminAccess(session, ESProjectAdminPrivileges.ShareProject);

		// check if requesting session did actually share a project before
		checkIfSessionIsAssociatedWithProject(session, projectId);

		projectId = getProjectId(projectId);
		final ACOrgUnit<?> orgUnit = getOrgUnit(participantId);

		for (final Role role : orgUnit.getRoles()) {
			if (areEqual(role, roleClass)) {
				role.getProjects().add(ModelUtil.clone(projectId));
				save();
				return;
			}
		}
	}

	private static void checkIfSessionIsAssociatedWithProject(SessionId sessionId, ProjectId projectId)
		throws AccessControlException {

		final EList<Adapter> eAdapters = sessionId.eAdapters();
		for (final Adapter adapter : eAdapters) {
			if (ShareProjectAdapter.class.isInstance(adapter)) {
				final ShareProjectAdapter shareAdapter = (ShareProjectAdapter) adapter;
				final boolean didRemove = shareAdapter.removeProject(projectId);
				if (didRemove) {
					return;
				}
				throw new AccessControlException(Messages.AdminEmfStoreImpl_IllegalRequestToAddInitialRole);
			}
		}

		// no ShareProjectAdapter with the correct project found
		throw new AccessControlException(Messages.AdminEmfStoreImpl_IllegalRequestToAddInitialRole);
	}

	private Role createRoleFromEClass(EClass roleClass) {
		return (Role) RolesPackage.eINSTANCE.getEFactoryInstance().create(
			(EClass) RolesPackage.eINSTANCE.getEClassifier(roleClass.getName()));
	}

	private ProjectId getProjectId(ProjectId projectId) throws ESException {
		for (final ProjectHistory projectHistory : getServerSpace().getProjects()) {
			if (projectHistory.getProjectId().equals(projectId)) {
				return projectHistory.getProjectId();
			}
		}
		throw new ESException(Messages.AdminEmfStoreImpl_Unknown_ProjectID);
	}

	/**
	 * {@inheritDoc}
	 */
	public void removeParticipant(SessionId sessionId, ProjectId projectId, ACOrgUnitId participantId)
		throws ESException {
		checkForNulls(sessionId, projectId, participantId);

		final boolean isServerAdmin = getAccessControl().getAuthorizationService().checkProjectAdminAccess(
			sessionId.toAPI(),
			projectId.toAPI(),
			ESProjectAdminPrivileges.AssignRoleToOrgUnit);

		final ACOrgUnit<?> orgUnit = getOrgUnit(participantId);
		projectId = getProjectId(projectId);

		final List<Role> roles = orgUnit.getRoles();
		for (final Role role : roles) {
			if (role.getProjects().contains(projectId)) {
				if (!isServerAdmin && role.canAdministrate(projectId)) {
					throw new AccessControlException(Messages.AdminEmfStoreImpl_RemovePA_Violation_1
						+ Messages.AdminEmfStoreImpl_RemovePA_Violation_2);
				}
				role.getProjects().remove(projectId);
				save();
				return;
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public Role getRole(SessionId sessionId, ProjectId projectId, ACOrgUnitId orgUnitId) throws ESException {

		checkForNulls(sessionId, projectId, orgUnitId);
		getAccessControl().getAuthorizationService().checkProjectAdminAccess(
			sessionId.toAPI(),
			projectId.toAPI());
		projectId = getProjectId(projectId);

		final ACOrgUnit<?> oUnit = getOrgUnit(orgUnitId);
		final List<Role> roles = oUnit.getRoles();
		for (final Role role : roles) {
			if (isServerAdmin(role) || role.getProjects().contains(projectId)) {
				return role;
			}
		}
		throw new ESException(Messages.AdminEmfStoreImpl_Could_Not_Find_OrgUnit);
	}

	/**
	 * {@inheritDoc}
	 */
	public void changeRole(final SessionId sessionId, final ProjectId projectId, final ACOrgUnitId orgUnitId,
		final EClass roleClass) throws ESException {

		checkForNulls(sessionId, projectId, orgUnitId, roleClass);
		checkSession(sessionId);

		final SessionId session = resolveSessionById(sessionId.getId());

		checkProjectAdminAccess(session, projectId, ESProjectAdminPrivileges.AssignRoleToOrgUnit);
		final boolean isServerAdmin = checkProjectAdminAccessForOrgUnit(session, projectId, orgUnitId);

		// trying to assign server administrator role although caller has no server role
		if (!isServerAdmin && isServerAdminRole(roleClass)) {
			throw new AccessControlException(Messages.AdminEmfStoreImpl_Not_Allowed_To_Assign_ServerAdminRole);
		}

		final ProjectId resolvedProjectId = getProjectId(projectId);
		final ACOrgUnit<?> orgUnit = getOrgUnit(orgUnitId);
		final Role role = getRole(resolvedProjectId, orgUnit);

		// remove old role first
		if (role != null) {

			if (!isServerAdmin && role.canAdministrate(resolvedProjectId)) {
				throw new AccessControlException(
					Messages.AdminEmfStoreImpl_RemovePA_Violation_1
					+ Messages.AdminEmfStoreImpl_RemovePA_Violation_2);
			}

			role.getProjects().remove(resolvedProjectId);
			if (role.getProjects().isEmpty()) {
				orgUnit.getRoles().remove(role);
			}
		}

		if (isServerAdminRole(roleClass)) {
			orgUnit.getRoles().add(RolesFactory.eINSTANCE.createServerAdmin());
			save();
			return;
		}

		// add project to role if it exists
		final List<Role> roles = orgUnit.getRoles();
		for (final Role r : roles) {
			if (r.eClass().getName().equals(roleClass.getName())) {
				r.getProjects().add(ModelUtil.clone(resolvedProjectId));
				save();
				return;
			}
		}

		// create role if does not exists
		final Role newRole = createRoleFromEClass(roleClass);
		newRole.getProjects().add(ModelUtil.clone(resolvedProjectId));
		orgUnit.getRoles().add(newRole);
		save();
	}

	/**
	 * {@inheritDoc}
	 */
	public void assignRole(SessionId sessionId, ACOrgUnitId orgUnitId, EClass roleClass)
		throws ESException {

		checkForNulls(sessionId, orgUnitId, roleClass);

		final ESAuthorizationService authorizationService = getAccessControl().getAuthorizationService();
		authorizationService.checkProjectAdminAccess(
			sessionId.toAPI(),
			null,
			ESProjectAdminPrivileges.AssignRoleToOrgUnit);
		final boolean isServerAdmin = authorizationService.checkProjectAdminAccessForOrgUnit(
			sessionId.toAPI(),
			orgUnitId.toAPI());

		if (!isServerAdmin && isServerAdminRole(roleClass)) {
			throw new AccessControlException("A project admin is not allowed to assign a server admin role"); //$NON-NLS-1$
		}

		final ACOrgUnit<?> orgUnit = getOrgUnit(orgUnitId);

		// check if org unit alrady has role
		final List<Role> roles = orgUnit.getRoles();
		for (final Role role : roles) {
			if (areEqual(role, roleClass)) {
				return;
			}
		}

		final Role newRole = createRoleFromEClass(roleClass);

		orgUnit.getRoles().add(newRole);
		save();
	}

	/**
	 * {@inheritDoc}
	 */
	public List<ACUser> getUsers(SessionId sessionId) throws ESException {
		checkForNulls(sessionId);
		getAccessControl().getAuthorizationService().checkProjectAdminAccess(
			sessionId.toAPI(),
			null);
		final List<ACUser> result = new ArrayList<ACUser>();
		for (final ACUser user : getUsers()) {
			result.add(user);
		}
		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	@SuppressWarnings("rawtypes")
	public List<ACOrgUnit> getOrgUnits(SessionId sessionId) throws ESException {
		checkForNulls(sessionId);
		checkSession(sessionId);

		checkProjectAdminAccess(sessionId);

		final List<ACOrgUnit> result = new ArrayList<ACOrgUnit>();

		for (final ACOrgUnit<ESUser> user : getUsers()) {
			result.add(ModelUtil.clone(user));
		}

		for (final ACOrgUnit<ESGroup> group : getGroups()) {
			result.add(ModelUtil.clone(group));
		}

		// quickfix
		clearMembersFromGroups(result);
		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	public List<ProjectInfo> getProjectInfos(SessionId sessionId) throws ESException {
		checkForNulls(sessionId);
		final List<ProjectInfo> result = new ArrayList<ProjectInfo>();
		for (final ProjectHistory projectHistory : getServerSpace().getProjects()) {
			try {
				getAccessControl().getAuthorizationService().checkProjectAdminAccess(
					sessionId.toAPI(),
					projectHistory.getProjectId().toAPI());
				result.add(getProjectInfo(projectHistory));
			} catch (final AccessControlException ace) {
				// ignore
			}
		}
		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	public ACOrgUnitId createUser(SessionId sessionId, String name) throws ESException {
		checkForNulls(sessionId, name);
		getAccessControl().getAuthorizationService().checkProjectAdminAccess(
			sessionId.toAPI(),
			null,
			ESProjectAdminPrivileges.CreateUser);

		if (userExists(name)) {
			throw new InvalidInputException("Username '" + name + "' already exists."); //$NON-NLS-1$ //$NON-NLS-2$
		}
		final ACUser acUser = AccesscontrolFactory.eINSTANCE.createACUser();
		acUser.setName(name);
		acUser.setDescription(StringUtils.EMPTY);
		getAccessControl().getOrgUnitProviderService().addUser(acUser.toAPI());
		save();
		return ModelUtil.clone(acUser.getId());
	}

	private boolean userExists(String name) {
		for (final ACUser user : getUsers()) {
			if (user.getName().equals(name)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * {@inheritDoc}
	 */
	public void deleteUser(SessionId sessionId, ACOrgUnitId userId) throws ESException {
		checkForNulls(sessionId, userId);
		final ESAuthorizationService authorizationService = getAccessControl().getAuthorizationService();
		authorizationService.checkProjectAdminAccessForOrgUnit(
			sessionId.toAPI(),
			userId.toAPI());
		authorizationService.checkProjectAdminAccess(
			sessionId.toAPI(),
			null,
			ESProjectAdminPrivileges.DeleteOrgUnit);
		for (final Iterator<ACUser> iter = getUsers().iterator(); iter.hasNext();) {
			final ACUser user = iter.next();
			final List<ACGroup> groups = getGroups(sessionId, userId);
			if (user.getId().equals(userId)) {
				for (final ACGroup acGroup : groups) {
					removeMember(sessionId, acGroup.getId(), userId);
				}
				getAccessControl().getOrgUnitProviderService().removeUser(user.toAPI());
				// TODO: move ecore delete into ServerSpace#deleteUser implementation
				EcoreUtil.delete(user);
				save();
				return;
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void changeOrgUnit(SessionId sessionId, ACOrgUnitId orgUnitId, String name, String description)
		throws ESException {
		checkForNulls(sessionId, orgUnitId, name, description);
		getAccessControl().getAuthorizationService().checkProjectAdminAccessForOrgUnit(
			sessionId.toAPI(),
			orgUnitId.toAPI());
		final ACOrgUnit<?> orgUnit = getOrgUnit(orgUnitId);
		orgUnit.setName(name);
		orgUnit.setDescription(description);
		save();
	}

	/**
	 *
	 * {@inheritDoc}
	 *
	 * @see org.eclipse.emf.emfstore.internal.server.AdminEmfStore#changeUser(org.eclipse.emf.emfstore.internal.server.model.SessionId,
	 *      org.eclipse.emf.emfstore.internal.server.model.accesscontrol.ACOrgUnitId, java.lang.String,
	 *      java.lang.String)
	 */
	public void changeUser(SessionId sessionId, ACOrgUnitId userId, String name, String password) throws ESException {

		checkForNulls(sessionId, userId, name, password);
		checkSession(sessionId);

		final ESAuthorizationService authorizationService = getAccessControl().getAuthorizationService();
		final ESSessionId resolvedSession = getAccessControl().getSessions().resolveSessionById(sessionId.getId());
		final SessionId session = APIUtil.toInternal(SessionId.class, resolvedSession);

		final ACOrgUnit<?> orgUnit = getOrgUnit(userId);
		final ACUser requestingUser = resolveUserBySessionId(sessionId.getId());

		if (orgUnit.equals(requestingUser)) {
			updateUser(userId, name, password);
			return;
		}

		final boolean isServerAdmin = checkProjectAdminAccess(session, ESProjectAdminPrivileges.ChangeUserPassword);

		if (!isServerAdmin) {
			authorizationService.checkProjectAdminAccessForOrgUnit(
				session.toAPI(),
				userId.toAPI());
		}

		updateUser(userId, name, password);
	}

	private void updateUser(ACOrgUnitId userId, String name, String password) throws ESException {

		final ACUser user = (ACUser) getOrgUnit(userId);
		user.setName(name);
		user.setPassword(password);
		save();
	}

	/**
	 * {@inheritDoc}
	 */
	public ACOrgUnit<?> getOrgUnit(SessionId sessionId, ACOrgUnitId orgUnitId) throws ESException {
		checkForNulls(sessionId, orgUnitId);
		getAccessControl().getAuthorizationService().checkProjectAdminAccess(
			sessionId.toAPI(),
			null);
		// quickfix
		final ACOrgUnit<?> orgUnit = ModelUtil.clone(getOrgUnit(orgUnitId));
		clearMembersFromGroup(orgUnit);
		return orgUnit;
	}

	/**
	 * This method is used as fix for the containment issue of group.
	 */
	@SuppressWarnings("rawtypes")
	private void clearMembersFromGroups(Collection<ACOrgUnit> orgUnits) {
		for (final ACOrgUnit orgUnit : orgUnits) {
			clearMembersFromGroup(orgUnit);
		}
	}

	/**
	 * This method is used as fix for the containment issue of group.
	 */
	@SuppressWarnings("rawtypes")
	private void clearMembersFromGroup(ACOrgUnit orgUnit) {
		if (orgUnit instanceof ACGroup) {
			((ACGroup) orgUnit).getMembers().clear();
		}
	}

	private boolean isServerAdmin(Role role) {
		return role.eClass().getName().equals(RolesPackage.Literals.SERVER_ADMIN.getName());
	}

	private boolean isServerAdminRole(EClass role) {
		return role.getName().equals(RolesPackage.Literals.SERVER_ADMIN.getName());
	}

	private boolean areEqual(Role role, EClass roleClass) {
		return role.eClass().getName().equals(roleClass.getName());
	}

	private ProjectInfo getProjectInfo(ProjectHistory project) {
		final ProjectInfo info = ModelFactory.eINSTANCE.createProjectInfo();
		info.setName(project.getProjectName());
		info.setDescription(project.getProjectDescription());
		info.setProjectId(ModelUtil.clone(project.getProjectId()));
		info.setVersion(project.getLastVersion().getPrimarySpec());
		return info;
	}

	private ACGroup getGroup(ACOrgUnitId orgUnitId) throws ESException {
		for (final ACGroup group : getGroups()) {
			if (group.getId().equals(orgUnitId)) {
				return group;
			}
		}
		throw new ESException(Messages.AdminEmfStoreImpl_Group_Does_Not_Exist);
	}

	private ACOrgUnit<?> getOrgUnit(ACOrgUnitId orgUnitId) throws ESException {
		for (final ACOrgUnit<ESUser> unit : getUsers()) {
			if (unit.getId().equals(orgUnitId)) {
				return unit;
			}
		}
		for (final ACOrgUnit<ESGroup> unit : getGroups()) {
			if (unit.getId().equals(orgUnitId)) {
				return unit;
			}
		}
		throw new ESException(Messages.AdminEmfStoreImpl_OrgUnit_Does_Not_Exist);
	}

	private Role getRole(ProjectId projectId, ACOrgUnit<?> orgUnit) {
		final List<Role> roles = orgUnit.getRoles();
		for (final Role role : roles) {
			if (isServerAdmin(role) || role.getProjects().contains(projectId)) {
				// return (Role) ModelUtil.clone(role);
				return role;
			}
		}
		return null;
	}

	private void save() throws ESException {
		try {
			getAccessControl().getOrgUnitProviderService().save();
		} catch (final IOException e) {
			throw new StorageException(StorageException.NOSAVE, e);
		} catch (final NullPointerException e) {
			throw new StorageException(StorageException.NOSAVE, e);
		}
	}

	private void checkForNulls(Object... objects) throws InvalidInputException {
		for (final Object obj : objects) {
			if (obj == null) {
				throw new InvalidInputException();
			}
		}
	}

	/**
	 * {@inheritDoc}.
	 *
	 * @see org.eclipse.emf.emfstore.internal.server.core.AbstractEmfstoreInterface#initSubInterfaces()
	 */
	@Override
	protected void initSubInterfaces() throws FatalESException {
	}
}
