/*
ESUP-portail is a french academic project developed under the GPL (General Public License) augmented according to the following :
A binary or source file developped by ESUP-portail can be used or compiled with products under Apache license.
The official english text of the GPL can be found here : http://www.gnu.org/licenses/gpl.html .
A non official french translation can be found here : http://www.linux-France.org/article/these/gpl.html .
The different kinds of licenses governing the products developed by the Apache foundation can be found here : http://www.apache.org/licenses .
It follows that you can as well as use download contents as well modify and redistribute them provided you respect the GPL terms.
Downloading and using such contents do not provide any guaranty.
Be sure that you have well understood the terms of the license before using the contents it covers.
The ESUP-portail distribution includes the following distributions :
    * UPortal :
      software developed by JA-SIG (Java Architecture - Special Interest Group)
      You can find the license page here : http://mis105.udel.edu/ja-sig/uportal/license.html
    * CAS :
      SSO solution developed by Yale University
      You can find the project page here : http://www.yale.edu/tp/auth
    * Cocoon :
      XML framework distributed by the Apache foundation under Apache license;
      Please find the full text here : http://cocoon.apache.org/2.1/license.html
    * Mod_dav:
      A DAV module for Apache web server
      You can find the project page here : http://www.webdav.org/mod_dav
    * IMP :
      webmail from Horde application framework
      You can find the project page here : http://www.horde.org
    * …. To be completed
*/
package org.esupportail.portal.channels.CStockage.administration;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ojb.broker.util.GUID;
import org.esupportail.portal.channels.CStockage.config.Server;
import org.esupportail.portal.channels.CStockage.config.Space;
import org.esupportail.portal.channels.CStockage.exception.DataBaseException;
import org.esupportail.portal.channels.CStockage.exception.PropertiesException;
import org.esupportail.portal.channels.CStockage.exception.ServerException;
import org.esupportail.portal.channels.CStockage.spacesPersonalization.DataBaseAccess;
import org.esupportail.portal.channels.CStockage.spacesPersonalization.DirectorySharingProperties;
import org.esupportail.portal.channels.CStockage.spacesPersonalization.ServerTool;
import org.esupportail.portal.channels.CStockage.spacesPersonalization.target.GroupForPersonalization;
import org.esupportail.portal.channels.CStockage.spacesPersonalization.target.UserForPersonalization;

/**
 * Id: AdministrationTool.java,v 1.0 13 janv. 2005
 * Copyright (c) 2005 Esup Portail (www.esup-portail.org)
 * Classes: AdministrationTool
 * Original Author: Yohan Colmant
 * This class is a tool used to manage the administration actions
 */
public class AdministrationTool {

	/**
	 * Logger object
	 */
	protected static final Log log = LogFactory.getLog(AdministrationTool.class);
	
	
	/**
	 * The object used to access the database
	 */
	private DataBaseAccess dbAccess;
	
	
	/**
	 * If the server into the database is administrated
	 */
	public static final String ADMINISTRATED_SERVER = "administrated_server";

	
	/**
	 * Constructor
	 * @throws PropertiesException
	 */
	public AdministrationTool() throws PropertiesException {
		dbAccess = new DataBaseAccess();		
	}
	

	

	
	
	
	
	
	/******************
	 * ADMINISTRATION 
	 *****************/
	

	/**
	 * Get the users for whose the resource is shared
	 * @return the list of the servers
	 * @throws DataBaseException
	 * @throws PropertiesException
	 * @throws ServerException
	 */
	public Vector getAdministratedSpaces() throws DataBaseException, PropertiesException, ServerException {

		// the servers list
		Vector servers = new Vector();
		
		// do the request
		Vector result = dbAccess.getAdministratedSpaces();
		
		// log
		if (log.isDebugEnabled()){
			log.debug("getAdministratedSpaces"+" :: loaded servers");
		}
		
		// get the server object
		for (int r=0; result!=null && r<result.size(); r++) {
			
			String[] line = (String[])result.elementAt(r);
			String serverId = line[0];
			String serverName = line[1];
			String serverXml = line[2];

			// log
			if (log.isDebugEnabled()){
				log.debug("getAdministratedSpaces"+" :: "+serverId+" "+serverName);
			}
			
			// check if we still have this server key
			Server server = null;
			for (int i=0; server==null && i<servers.size(); i++) {
				Server s = (Server)servers.elementAt(i);
				if (serverName.equals(s.getName())) {
					server = s;
				}
			}
			
			// if not found
			if (server==null) {
				// instanciate server
				ServerTool tool = new ServerTool(serverXml);
				server = tool.getServer();
				server.setName(serverName);
				server.setId(serverId);
				
				// put server into the list
				servers.add(server);
				
				// for each space, we initialize the DirectorySharingProperties and set the targets
				ArrayList spaces = server.getSpaces();
				for (int i=0; i<spaces.size(); i++) {
					Space space = (Space)spaces.get(i);
					String spaceKey = space.getKey();
					
					// init the DirectorySharingProperties
					space.setTargetsOfSharing(new DirectorySharingProperties(null));
					
					// set the targets from the database
					Vector targets = dbAccess.getTargetsOfAdministratedSpaces(serverId, spaceKey);

					// log
					if (log.isDebugEnabled()){
						log.debug("getAdministratedSpaces"+" :: loaded spaces");
					}
					
					for (int j=0; targets!=null && j<targets.size(); j++) {
						String[] lineSpace = (String[])targets.elementAt(j);
						
						String availableSpaceTargetId = lineSpace[0];
						String targetKey = lineSpace[1];
						String targetType = lineSpace[2];
						String obliged = lineSpace[3];
						
						// log
						if (log.isDebugEnabled()){
							log.debug("getAdministratedSpaces"+" :: "+availableSpaceTargetId+" "+targetKey+" "+targetType+" "+obliged);
						}
						
						// add the user or the group to the good space
						if (targetType.equals(DataBaseAccess.TARGET_IS_USER)) {
							
							// construct a user
							UserForPersonalization user = new UserForPersonalization(targetKey);
							user.getPersonalization().setIdOfSharing(availableSpaceTargetId);
							user.getPersonalization().setObliged(obliged);
							if (!space.getTargetsOfSharing().getUsers().contains(user))
								space.getTargetsOfSharing().getUsers().addElement(user);
							
						}
						else {
							
							// construct a group
							GroupForPersonalization group = new GroupForPersonalization(targetKey, null, true);
							group.getPersonalization().setIdOfSharing(availableSpaceTargetId);
							group.getPersonalization().setObliged(obliged);
							if (!space.getTargetsOfSharing().getGroups().contains(group))
								space.getTargetsOfSharing().getGroups().addElement(group);
							
						}
					}
					
				}
			}
		}
		
		
		// return the servers
		return servers;
	}
	
	
	
	
	
	/**
	 * Add a new complete server configuration into the database
	 * @param server the server object containing each space
	 * @throws DataBaseException
	 */
	public void addStorageAvailableAdministratedSpace(Server server) throws DataBaseException {
		
		// the server is new, we have to set an id
		String serverId = server.getId();
		if (serverId == null) {
			serverId = new GUID().toString();
			server.setId(serverId);
		}
		
		// for each space, we generate a key
		ArrayList spaces = server.getSpaces();
		for (int i=0; i<spaces.size(); i++) {
			Space s = (Space)spaces.get(i);
			if (s.getKey()==null)
				s.setKey(new GUID().toString());
		}

		// the xml for the server
		String xmlServer = server.getXml();
		//System.out.println(xmlServer);

		// we add the server sharing to the database
		dbAccess.addStorageAvailableSpace(serverId, server.getName(), xmlServer, ADMINISTRATED_SERVER, null, null);
		
		// for each space, we add users and groups
		for (int i=0; i<spaces.size(); i++) {
			Space s = (Space)spaces.get(i);
			String spaceKey = s.getKey();
			
			DirectorySharingProperties targets = s.getTargetsOfSharing();
			Vector users = targets.getUsers();
			Vector groups = targets.getGroups();
			
			// users
			Enumeration iter = users.elements();
			while (iter.hasMoreElements()) {
				
				UserForPersonalization user = (UserForPersonalization)iter.nextElement();
				
				// if we don't have this, we add into database
				dbAccess.addStorageAvailableSpaceTarget(user.getKey(), null, DataBaseAccess.TARGET_IS_USER, serverId, spaceKey, user.getPersonalization().isObliged());
			}

			// groups
			iter = groups.elements();
			while (iter.hasMoreElements()) {
				
				GroupForPersonalization group = (GroupForPersonalization)iter.nextElement();
				
				// if we don't have this, we add into database
				dbAccess.addStorageAvailableSpaceTarget(group.getKey(), null, DataBaseAccess.TARGET_IS_GROUP, serverId, spaceKey, group.getPersonalization().isObliged());
			}
		}
	}
	
	

	
	/**
	 * Add a new complete server configuration into the database
	 * @param server the server object containing each space
	 * @throws DataBaseException
	 */
	public void updateStorageAvailableAdministratedSpace(Server server, boolean changeXml, Vector addedSpaces, Vector deletedSpaces, Vector oldSpacesTargetsChanged, Vector newSpacesTargetsChanged) throws DataBaseException {
		
		// the server id
		String serverId = server.getId();
		
		// for each space, we generate a key
		ArrayList spaces = server.getSpaces();
		for (int i=0; i<spaces.size(); i++) {
			Space s = (Space)spaces.get(i);
			if (s.getKey()==null)
				s.setKey(new GUID().toString());
		}

		// we update the XML in the case of
		if (changeXml) {

			// the xml for the server
			String xmlServer = server.getXml();
			//System.out.println(xmlServer);

			dbAccess.updateXmlServerAvailableSpace(xmlServer, serverId);
		}
		
		// for each deleted space
		for (int i=0; i<deletedSpaces.size(); i++) {
			Space space = (Space)deletedSpaces.elementAt(i);
			
			// get each user
			Vector users = space.getTargetsOfSharing().getUsers();
			Enumeration iter = users.elements();
			while (iter.hasMoreElements()) {
				UserForPersonalization user = (UserForPersonalization)iter.nextElement();
				
				// the id of sharing of the user
				String userIdOfSharing = user.getPersonalization().getIdOfSharing();
				
				// delete from the database			
				dbAccess.delStorageUsersPreferences(userIdOfSharing);
				dbAccess.delStorageAvailableSpaceTarget(userIdOfSharing);
			}
			
			// get each group
			Vector groups = space.getTargetsOfSharing().getGroups();
			iter = groups.elements();
			while (iter.hasMoreElements()) {
				GroupForPersonalization group = (GroupForPersonalization)iter.nextElement();
				
				// the id of sharing of the group
				String groupIdOfSharing = group.getPersonalization().getIdOfSharing();
				
				// delete from the database			
				dbAccess.delStorageUsersPreferences(groupIdOfSharing);
				dbAccess.delStorageAvailableSpaceTarget(groupIdOfSharing);
			}
		}
		
		// for each added space
		for (int i=0; i<addedSpaces.size(); i++) {
			Space space = (Space)addedSpaces.elementAt(i);
			String spaceKey = space.getKey();
			
			DirectorySharingProperties targets = space.getTargetsOfSharing();
			Vector users = targets.getUsers();
			Vector groups = targets.getGroups();
			
			// users
			Enumeration iter = users.elements();
			while (iter.hasMoreElements()) {
				
				UserForPersonalization user = (UserForPersonalization)iter.nextElement();
				
				// if we don't have this, we add into database
				dbAccess.addStorageAvailableSpaceTarget(user.getKey(), null, DataBaseAccess.TARGET_IS_USER, serverId, spaceKey, user.getPersonalization().isObliged());
			}

			// groups
			iter = groups.elements();
			while (iter.hasMoreElements()) {
				
				GroupForPersonalization group = (GroupForPersonalization)iter.nextElement();
				
				// if we don't have this, we add into database
				dbAccess.addStorageAvailableSpaceTarget(group.getKey(), null, DataBaseAccess.TARGET_IS_GROUP, serverId, spaceKey, group.getPersonalization().isObliged());
			}
			
		}
		

		// for each modified space
		for (int j=0; j<oldSpacesTargetsChanged.size(); j++) {
			
			Space oldSpace = (Space)oldSpacesTargetsChanged.elementAt(j);
			DirectorySharingProperties oldTargets = oldSpace.getTargetsOfSharing();
			Vector oldUsers = oldTargets.getUsers();
			Vector oldGroups = oldTargets.getGroups();
			
			Space newSpace = (Space)newSpacesTargetsChanged.elementAt(j);
			DirectorySharingProperties newTargets = newSpace.getTargetsOfSharing();
			Vector newUsers = newTargets.getUsers();
			Vector newGroups = newTargets.getGroups();
			
			String spaceKey = oldSpace.getKey();
			
			//Vector addedUsers = new Vector();
			//Vector addedGroups = new Vector();
			//Vector deletedUsers = new Vector();
			//Vector deletedGroups = new Vector();
			//Vector modifiedUsers = new Vector();
			//Vector modifiedGroups = new Vector();
			
			// added and modified users
			Enumeration iter = newUsers.elements();
			while (iter.hasMoreElements()) {
				UserForPersonalization newUser = (UserForPersonalization)iter.nextElement();
				UserForPersonalization oldUser = null;
				for (int i=0; i<oldUsers.size() && oldUser==null; i++) {
					UserForPersonalization userTemp = (UserForPersonalization)oldUsers.get(i);
					if (!userTemp.getPersonalization().isInheritedAcl() && userTemp.getKey().equals(newUser.getKey())) {
						oldUser = userTemp;
					}
				}
				
				// added
				if (oldUser==null) {
					//addedUsers.add(newUser);
					if (log.isDebugEnabled()) {
						log.debug("updateStorageAvailableAdministratedSpace"+" :: "+"add user "+newUser.getDisplayName()+" to space "+spaceKey);
					}
					dbAccess.addStorageAvailableSpaceTarget(newUser.getKey(), null, DataBaseAccess.TARGET_IS_USER, serverId, spaceKey, newUser.getPersonalization().isObliged());
				}
				
				// modified
				else {
					
					if (!newUser.equals(oldUser)) {
						//modifiedUsers.add(newUser);
						if (log.isDebugEnabled()) {
							log.debug("updateStorageAvailableAdministratedSpace"+" :: "+"modify user "+newUser.getDisplayName()+" to space "+spaceKey);
						}
						dbAccess.updateObligedTarget(newUser.getPersonalization().getIdOfSharing(), newUser.getPersonalization().isObliged());
					}
					
				}
			}

			// added and modified groups
			iter = newGroups.elements();
			while (iter.hasMoreElements()) {
				GroupForPersonalization newGroup = (GroupForPersonalization)iter.nextElement();
				GroupForPersonalization oldGroup = null;
				for (int i=0; i<oldGroups.size() && oldGroup==null; i++) {
					GroupForPersonalization groupTemp = (GroupForPersonalization)oldGroups.get(i);
					if (!groupTemp.getPersonalization().isInheritedAcl() && groupTemp.getKey().equals(newGroup.getKey())) {
						oldGroup = groupTemp;
					}
				}
				
				// added
				if (oldGroup==null) {
					//addedUsers.add(newGroup);
					if (log.isDebugEnabled()) {
						log.debug("updateStorageAvailableAdministratedSpace"+" :: "+"add group "+newGroup.getDisplayName());
					}
					dbAccess.addStorageAvailableSpaceTarget(newGroup.getKey(), null, DataBaseAccess.TARGET_IS_GROUP, serverId, spaceKey, newGroup.getPersonalization().isObliged());
				}
				
				// modified
				else {
					
					if (!newGroup.equals(oldGroup)) {
						//modifiedUsers.add(newGroup);
						if (log.isDebugEnabled()) {
							log.debug("updateStorageAvailableAdministratedSpace"+" :: "+"modify group "+newGroup.getDisplayName());
						}
						dbAccess.updateObligedTarget(newGroup.getPersonalization().getIdOfSharing(), newGroup.getPersonalization().isObliged());
					}
					
				}
			}
			
			// deleted users
			iter = oldUsers.elements();
			while (iter.hasMoreElements()) {
				UserForPersonalization oldUser = (UserForPersonalization)iter.nextElement();
				UserForPersonalization newUser = null;
				for (int i=0; i<newUsers.size() && newUser==null; i++) {
					UserForPersonalization userTemp = (UserForPersonalization)newUsers.get(i);
					if (!userTemp.getPersonalization().isInheritedAcl() && userTemp.getKey().equals(oldUser.getKey())) {
						newUser = userTemp;
					}
				}
				
				// deleted
				if (newUser==null) {
					//deletedUsers.add(oldUser);
					if (log.isDebugEnabled()) {
						log.debug("updateStorageAvailableAdministratedSpace"+" :: "+"delete user "+oldUser.getDisplayName());
					}
					dbAccess.delStorageUsersPreferences(oldUser.getPersonalization().getIdOfSharing());
					dbAccess.delStorageAvailableSpaceTarget(oldUser.getPersonalization().getIdOfSharing());
				}
				
			}

			// deleted groups
			iter = oldGroups.elements();
			while (iter.hasMoreElements()) {
				GroupForPersonalization oldGroup = (GroupForPersonalization)iter.nextElement();
				GroupForPersonalization newGroup = null;
				for (int i=0; i<newGroups.size() && newGroup==null; i++) {
					GroupForPersonalization groupTemp = (GroupForPersonalization)newGroups.get(i);
					if (!groupTemp.getPersonalization().isInheritedAcl() && groupTemp.getKey().equals(oldGroup.getKey())) {
						newGroup = groupTemp;
					}
				}
				
				// deleted
				if (newGroup==null) {
					//deletedGroups.add(oldGroup);
					if (log.isDebugEnabled()) {
						log.debug("updateStorageAvailableAdministratedSpace"+" :: "+"delete group "+oldGroup.getDisplayName());
					}
					dbAccess.delStorageUsersPreferences(oldGroup.getPersonalization().getIdOfSharing());
					dbAccess.delStorageAvailableSpaceTarget(oldGroup.getPersonalization().getIdOfSharing());
				}
				
			}
			
		}
		
		
		
		
	}
	

	

	/**
	 * Delete sharing properties for this server into the database
	 * @param server the server to delete
	 * @throws DataBaseException
	 */
	public void delStorageAvailableAdministratedServer(Server server) throws DataBaseException {
 
		// the id of the server
		String serverId = server.getId();
		
		// the spaces
		ArrayList spaces = server.getSpaces();
		
		// for each space
		for (int s=0; s<spaces.size(); s++) {
			
			// the selected space
			Space space = (Space)spaces.get(s);
			
			// get each user
			Vector users = space.getTargetsOfSharing().getUsers();
			Enumeration iter = users.elements();
			while (iter.hasMoreElements()) {
				UserForPersonalization user = (UserForPersonalization)iter.nextElement();
				
				// the id of sharing of the user
				String userIdOfSharing = user.getPersonalization().getIdOfSharing();
				
				// delete from the database			
				dbAccess.delStorageUsersPreferences(userIdOfSharing);
				dbAccess.delStorageAvailableSpaceTarget(userIdOfSharing);
			}
			
			// get each group
			Vector groups = space.getTargetsOfSharing().getGroups();
			iter = groups.elements();
			while (iter.hasMoreElements()) {
				GroupForPersonalization group = (GroupForPersonalization)iter.nextElement();
				
				// the id of sharing of the group
				String groupIdOfSharing = group.getPersonalization().getIdOfSharing();
				
				// delete from the database			
				dbAccess.delStorageUsersPreferences(groupIdOfSharing);
				dbAccess.delStorageAvailableSpaceTarget(groupIdOfSharing);
			}
			
		}
		
		// delete the server
		dbAccess.delStorageAvailableSpace(serverId);
			
	}
	

	/**
	 * Update the name of the server of the sharing properties into the database
	 * @param serverId the id of the server
	 * @param newName the new name of the server administration
	 * @return the result of the query
	 * @throws DataBaseException
	 */
	public void updateServerNameAvailableSpace(String serverId, String newName) throws DataBaseException {

		// update the database
		dbAccess.updateServerNameAvailableSpace(serverId, newName);
	}
	
}
