/*
 * Created by IntelliJ IDEA.
 * User: Mike
 * Date: Jan 29, 2004
 * Time: 5:58:01 PM
 */
package com.atlassian.confluence.rpc.xmlrpc;

import bucket.core.InfrastructureException;
import com.atlassian.confluence.rpc.InvalidSessionException;
import com.atlassian.confluence.rpc.NotPermittedException;
import com.atlassian.confluence.rpc.RemoteException;
import com.atlassian.confluence.rpc.soap.ConfluenceSoapService;
import com.atlassian.confluence.rpc.soap.beans.*;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.log4j.Category;

import java.lang.reflect.InvocationTargetException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Vector;

public class ConfluenceXmlRpcHandlerImpl implements ConfluenceXmlRpcHandler
{
    public static final Category log = Category.getInstance(ConfluenceXmlRpcHandlerImpl.class);

    ConfluenceSoapService soapServiceDelegator;

    public void setSoapServiceDelegator(ConfluenceSoapService soapServiceDelegator)
    {
        this.soapServiceDelegator = soapServiceDelegator;
    }

    public String login(String username, String password) throws RemoteException
    {
        return soapServiceDelegator.login(username, password);
    }

    public boolean logout(String token) throws RemoteException
    {
        return soapServiceDelegator.logout(token);
    }

    public Vector getSpaces(String token) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getSpaces(token));
    }

    public Vector getBlogEntries(String token, String spaceKey) throws RemoteException
    {
        try
        {
            return Translator.makeVector(soapServiceDelegator.getBlogEntries(token, spaceKey));
        }
        catch (RemoteException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new RemoteException(e);
        }
    }

    public Hashtable getBlogEntryByDayAndTitle(String token, String spaceKey, int dayOfMonth, String postTitle) throws RemoteException
    {
        return Translator.makeStruct(soapServiceDelegator.getBlogEntryByDayAndTitle(token, spaceKey, dayOfMonth, postTitle));
    }

    public Vector getComments(String token, String pageId) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getComments(token, makePageId(pageId)));
    }

    public Hashtable getComment(String token, String commentId) throws InvalidSessionException, RemoteException
    {
        return Translator.makeStruct(soapServiceDelegator.getComment(token, Long.parseLong(commentId)));
    }

    public Hashtable addComment(String token, Hashtable comment) throws InvalidSessionException, NotPermittedException, RemoteException
    {
        RemoteComment rComment = new RemoteComment();

        comment.remove("created");

        convertLong(comment, "id");
        convertLong(comment, "pageId");

        try
        {
            BeanUtils.populate(rComment, comment);
        }
        catch (IllegalAccessException e)
        {
            log.warn("Unable to add comment via XML-RPC: " + e.getMessage(), e);
            throw new InfrastructureException("Unable to add comment: " + e.toString(), e);
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }

        return Translator.makeStruct(soapServiceDelegator.addComment(token, rComment));
    }

    public boolean removeComment(String token, String commentId) throws InvalidSessionException, NotPermittedException, RemoteException
    {
        return soapServiceDelegator.removeComment(token, Long.parseLong(commentId));
    }

    public Vector getAncestors(String token, String pageId) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getAncestors(token, makePageId(pageId)));
    }

    public Vector getChildren(String token, String pageId) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getChildren(token, makePageId(pageId)));
    }

    public Vector getDescendents(String token, String pageId) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getDescendents(token, makePageId(pageId)));
    }

    public Vector getAttachments(String token, String pageId) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getAttachments(token, makePageId(pageId)));
    }

    public Hashtable getBlogEntry(String token, String blogEntryId) throws RemoteException
    {
        return Translator.makeStruct(soapServiceDelegator.getBlogEntry(token, makePageId(blogEntryId)));
    }

    public Vector getPages(String token, String spaceKey) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getPages(token, spaceKey));
    }

    public Hashtable getPage(String token, String pageId) throws RemoteException
    {
        return Translator.makeStruct(soapServiceDelegator.getPage(token, makePageId(pageId)));
    }

    public Hashtable getPage(String token, String spaceKey, String pageTitle) throws RemoteException
    {
        return Translator.makeStruct(soapServiceDelegator.getPage(token, spaceKey, pageTitle));
    }

    public Vector getPageHistory(String token, String pageId) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getPageHistory(token, makePageId(pageId)));
    }

    public Hashtable getSpace(String token, String spaceKey) throws RemoteException
    {
        return Translator.makeStruct(soapServiceDelegator.getSpace(token, spaceKey));
    }

    public Vector getPermissions(String token, String spaceKey) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getPermissions(token, spaceKey));
    }

    public Vector getPermissionsForUser(String token, String spaceKey, String userName) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getPermissionsForUser(token, spaceKey, userName));
    }

    public Vector getPagePermissions(String token, String pageId) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getPagePermissions(token, makePageId(pageId)));
    }

    private long makePageId(String pageId) throws RemoteException
    {
        try
        {
            return Long.parseLong(pageId);
        }
        catch (NumberFormatException e)
        {
            throw new RemoteException("You must supply a valid number as the page ID.");
        }
    }

    public String renderContent(String token, String spaceKey, String pageId, String newContent) throws RemoteException
    {
        return soapServiceDelegator.renderContent(token, spaceKey, makePageId(pageId), newContent);
    }

    public String renderContent(String token, String spaceKey, String pageId, String newContent, Hashtable renderParameters) throws RemoteException
    {
        return soapServiceDelegator.renderContent(token, spaceKey, makePageId(pageId), newContent, renderParameters);
    }

    public Boolean removePage(String token, String pageId) throws RemoteException
    {
        return soapServiceDelegator.removePage(token, makePageId(pageId));
    }

    public Vector search(String token, String query, int maxResults) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.search(token, query, maxResults));
    }

    public Vector search(String token, String query, Hashtable params, int maxResults) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.search(token, query, params, maxResults));
    }

    public Hashtable storeBlogEntry(String token, Hashtable blogEntryStruct) throws RemoteException
    {
        RemoteBlogEntry rblog = new RemoteBlogEntry();
        convertLong(blogEntryStruct, "id");
        convertInteger(blogEntryStruct, "version");

        // As with storePages we remove the publishDate because it is not needed and causing an exception.
        blogEntryStruct.remove("publishDate");

        try
        {
            BeanUtils.populate(rblog, blogEntryStruct);
        }
        catch (IllegalAccessException e)
        {
            throw new InfrastructureException("Bad error :)", e);
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }
        return Translator.makeStruct(soapServiceDelegator.storeBlogEntry(token, rblog));
    }

    private void convertLong(Hashtable table, String key)
    {
        if (table.containsKey(key))
        {
            table.put(key, new Long((String) table.get(key)));
        }
    }

    private void convertDate(Hashtable table, String key)
    {
        if (table.containsKey(key))
        {
            String dateString = (String) table.get(key);
            try
            {
                Date d = SimpleDateFormat.getDateInstance().parse(dateString);
                table.put(key, d);
            }
            catch (ParseException pe)
            {
                throw new RuntimeException("Error parsing date '" + dateString + "'", pe);
            }
        }
    }

    private void convertInteger(Hashtable table, String key)
    {
        if (table.containsKey(key))
        {
            table.put(key, new Integer((String) table.get(key)));
        }
    }

    public Hashtable storePage(String token, Hashtable pageStruct) throws RemoteException
    {
        RemotePage rpage = new RemotePage();

        // convert values stored in the struct as Strings, but in the object as long or int
        convertLong(pageStruct, "id");

        if (pageStruct.containsKey("parentId"))
            pageStruct.put("parentId", new Long((String) pageStruct.get("parentId")));

        if (pageStruct.containsKey("version"))
            pageStruct.put("version", new Integer((String) pageStruct.get("version")));

        // HACK! Dates make XML-RPC barf for some reason...
        // but we don't need them for add or edit page, so let's remove 'em!
        pageStruct.remove("modified");
        pageStruct.remove("created");

        try
        {
            BeanUtils.populate(rpage, pageStruct);
        }
        catch (IllegalAccessException e)
        {
            throw new InfrastructureException("Bad error :)", e);
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }
        return Translator.makeStruct(soapServiceDelegator.storePage(token, rpage));
    }

    private String getRequiredStringParameter(Hashtable map, String key)
    {
        if (!map.containsKey(key))
        {
            throw new RuntimeException("No '" + key + "' specified.");
        }
        return (String) map.get(key);
    }


    /* Attachments API */
    public Hashtable addAttachment(String token, String contentId, Hashtable attachment, byte[] attachmentData) throws RemoteException
    {
        RemoteAttachment attachmentStruct = new RemoteAttachment(
                Long.parseLong(contentId),
                getRequiredStringParameter(attachment, "fileName"),
                getRequiredStringParameter(attachment, "contentType"),
                (String) attachment.get("comment")
        );
        return Translator.makeStruct(soapServiceDelegator.addAttachment(token, Long.parseLong(contentId), attachmentStruct, attachmentData));
    }

    public Hashtable getAttachment(String token, String contentId, String fileName, String version) throws RemoteException
    {
        return Translator.makeStruct(soapServiceDelegator.getAttachment(token, Long.parseLong(contentId), fileName, Integer.parseInt(version)));
    }

    public byte[] getAttachmentData(String token, String contentId, String fileName, String version) throws RemoteException
    {
        return soapServiceDelegator.getAttachmentData(token, Long.parseLong(contentId), fileName, Integer.parseInt(version));
    }

    public boolean removeAttachment(String token, String contentId, String fileName) throws RemoteException, NotPermittedException
    {
        return soapServiceDelegator.removeAttachment(token, Long.parseLong(contentId), fileName);
    }

    public boolean moveAttachment(String token, String originalContentId, String originalFileName, String newContentId, String newFileName) throws RemoteException, NotPermittedException
    {
        return soapServiceDelegator.moveAttachment(token, Long.parseLong(originalContentId), originalFileName, Long.parseLong(newContentId), newFileName);
    }

    /* Spaces API */

    public Hashtable addSpace(String token, Hashtable space) throws RemoteException
    {
        RemoteSpace rSpace = new RemoteSpace();
        try
        {
            BeanUtils.populate(rSpace, space);
        }
        catch (Exception e)
        {
            log.warn("Unable to create space via XML-RPC: " + e.getMessage(), e);
            throw new InfrastructureException("Unable to create space: " + e.toString(), e);
        }
        return Translator.makeStruct(soapServiceDelegator.addSpace(token, rSpace));
    }

    public Hashtable addPersonalSpace(String token, Hashtable space, String username) throws RemoteException
    {
        RemoteSpace rSpace = new RemoteSpace();
        try
        {
            BeanUtils.populate(rSpace, space);
        }
        catch (Exception e)
        {
            log.warn("Unable to create space via XML-RPC: " + e.getMessage(), e);
            throw new InfrastructureException("Unable to create space: " + e.toString(), e);
        }
        return Translator.makeStruct(soapServiceDelegator.addPersonalSpace(token, rSpace, username));
    }

    public boolean convertToPersonalSpace(String token, String userName, String spaceKey, String newName, boolean updateLinks) throws RemoteException
    {
        return soapServiceDelegator.convertToPersonalSpace(token, userName, spaceKey, newName, updateLinks);
    }

    public Boolean removeSpace(String token, String spaceKey) throws RemoteException
    {
        return soapServiceDelegator.removeSpace(token, spaceKey);
    }

    public String exportSpace(String token, String spaceKey, String exportType) throws RemoteException
    {
        return soapServiceDelegator.exportSpace(token, spaceKey, exportType);
    }

    public boolean addPermissionToSpace(String token, String permission, String remoteEntityName, String spaceKey) throws RemoteException
    {
        return soapServiceDelegator.addPermissionToSpace(token, permission, remoteEntityName, spaceKey);
    }

    public boolean addPermissionsToSpace(String token, Vector permissions, String remoteEntityName, String spaceKey) throws RemoteException
    {
        return soapServiceDelegator.addPermissionsToSpace(token, convertPermissionsVectorToArray(permissions), remoteEntityName, spaceKey);
    }

    private String[] convertPermissionsVectorToArray(Vector permissions) throws RemoteException
    {
        // Convert the Vector into a String array
        String[] permissionsArray = new String[permissions.size()];

        for (int i = 0; i < permissions.size(); i++)
        {
            Object object = permissions.elementAt(i);

            // Make sure the permission is a String, otherwise throw an error
            if (object instanceof String)
                permissionsArray[i] = (String) object;
            else
                throw new RemoteException("Unable to add permissions to Space: Permissions must be Strings");
        }
        return permissionsArray;
    }

    public boolean removePermissionFromSpace(String token, String permission, String remoteEntityName, String spaceKey) throws NotPermittedException, RemoteException
    {
        return soapServiceDelegator.removePermissionFromSpace(token, permission, remoteEntityName, spaceKey);
    }

    public boolean addAnonymousPermissionToSpace(String token, String permission, String spaceKey) throws RemoteException
    {
        return soapServiceDelegator.addAnonymousPermissionToSpace(token, permission, spaceKey);
    }

    public boolean addAnonymousPermissionsToSpace(String token, Vector permissions, String spaceKey) throws RemoteException
    {
        return soapServiceDelegator.addAnonymousPermissionsToSpace(token, convertPermissionsVectorToArray(permissions), spaceKey);
    }

    public boolean removeAnonymousPermissionFromSpace(String token, String permission, String spaceKey) throws NotPermittedException, RemoteException
    {
        return soapServiceDelegator.removeAnonymousPermissionFromSpace(token, permission, spaceKey);
    }

    public String[] getSpaceLevelPermissions(String token) throws RemoteException
    {
        return soapServiceDelegator.getSpaceLevelPermissions(token);
    }

    /* Admin API */

    public Hashtable getServerInfo(String token) throws RemoteException
    {
        return Translator.makeStruct(soapServiceDelegator.getServerInfo(token));
    }

    public String exportSite(String token, boolean exportAttachments) throws RemoteException
    {
        return soapServiceDelegator.exportSite(token, exportAttachments);
    }

    public boolean flushIndexQueue(String token) throws RemoteException
    {
        return soapServiceDelegator.flushIndexQueue(token);
    }

    public boolean clearIndexQueue(String token) throws RemoteException
    {
        return soapServiceDelegator.clearIndexQueue(token);
    }

    /* Users API */
    // Groups
    public Vector getGroups(String token) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getGroups(token));
    }

    public boolean hasGroup(String token, String groupname) throws InvalidSessionException, RemoteException
    {
        return soapServiceDelegator.hasGroup(token, groupname);
    }

    public boolean addGroup(String token, String groupname) throws RemoteException
    {
        return soapServiceDelegator.addGroup(token, groupname);
    }

    public boolean removeGroup(String token, String groupname, String defaultGroupName) throws RemoteException
    {
        return soapServiceDelegator.removeGroup(token, groupname, defaultGroupName);
    }

    public Vector getUserGroups(String token, String username) throws RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getUserGroups(token, username));
    }

    public boolean addUserToGroup(String token, String username, String groupname) throws RemoteException
    {
        soapServiceDelegator.addUserToGroup(token, username, groupname);
        return true;
    }

    public boolean removeAllPermissionsForGroup(String token, String groupname) throws RemoteException
    {
        return soapServiceDelegator.removeAllPermissionsForGroup(token, groupname);
    }

    public boolean removeUserFromGroup(String token, String username, String groupname) throws RemoteException
    {
        return soapServiceDelegator.removeUserFromGroup(token, username, groupname);
    }

    // Users
    public Hashtable getUser(String token, String username) throws RemoteException
    {
        return Translator.makeStruct(soapServiceDelegator.getUser(token, username));
    }

    public boolean hasUser(String token, String username) throws InvalidSessionException, RemoteException
    {
        return soapServiceDelegator.hasUser(token, username);
    }

    public boolean addUser(String token, Hashtable remoteUser, String password) throws RemoteException
    {
        RemoteUser rUser = new RemoteUser();

        try
        {
            BeanUtils.populate(rUser, remoteUser);
        }
        catch (Exception e)
        {
            log.warn("Unable to create user via XML-RPC: " + e.getMessage(), e);
            throw new InfrastructureException("Unable to create user: " + e.toString(), e);
        }

        soapServiceDelegator.addUser(token, rUser, password);
        return true;
    }

    public boolean removeUser(String token, String username) throws RemoteException
    {
        return soapServiceDelegator.removeUser(token, username);
    }

    public boolean editUser(String token, Hashtable remoteUser) throws NotPermittedException, InvalidSessionException, RemoteException
    {
        RemoteUser rUser = new RemoteUser();

        try
        {
            BeanUtils.populate(rUser, remoteUser);
        }
        catch (Exception e)
        {
            log.warn("Unable to edit user via XML-RPC: " + e.getMessage(), e);
            throw new InfrastructureException("Unable to edit user: " + e.toString(), e);
        }

        return soapServiceDelegator.editUser(token, rUser);
    }

    public boolean deactivateUser(String token, String username) throws NotPermittedException, InvalidSessionException, RemoteException
    {
        return soapServiceDelegator.deactivateUser(token, username);
    }

    public boolean reactivateUser(String token, String username) throws NotPermittedException, InvalidSessionException, RemoteException
    {
        return soapServiceDelegator.reactivateUser(token, username);
    }

    public Vector getActiveUsers(String token, boolean viewAll) throws InvalidSessionException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getActiveUsers(token, viewAll));
    }

    public boolean setUserInformation(String token, Hashtable userInfo) throws NotPermittedException, InvalidSessionException, RemoteException
    {
        RemoteUserInformation rUser = new RemoteUserInformation();

        if (userInfo.containsKey("id"))
            userInfo.put("id", new Long((String) userInfo.get("id")));

        if (userInfo.containsKey("version"))
            userInfo.put("version", new Integer((String) userInfo.get("version")));

        userInfo.remove("creationDate");
        userInfo.remove("lastModificationDate");

        try
        {
            BeanUtils.populate(rUser, userInfo);
        }
        catch (Exception e)
        {
            log.warn("Unable to edit user information via XML-RPC: " + e.getMessage(), e);
            throw new InfrastructureException("Unable to edit user information: " + e.toString(), e);
        }

        return soapServiceDelegator.setUserInformation(token, rUser);
    }

    public Hashtable getUserInformation(String token, String username) throws InvalidSessionException, RemoteException
    {
        return Translator.makeStruct(soapServiceDelegator.getUserInformation(token, username));
    }

    public boolean changeMyPassword(String token, String oldPass, String newPass) throws InvalidSessionException, RemoteException
    {
        return soapServiceDelegator.changeMyPassword(token, oldPass, newPass);
    }

    public boolean changeUserPassword(String token, String username, String newPass) throws NotPermittedException, InvalidSessionException, RemoteException
    {
        return soapServiceDelegator.changeUserPassword(token, username, newPass);
    }

    public boolean addProfilePicture(String token, String userName, String fileName, String mimeType, byte[] pictureData) throws RemoteException
    {
        return soapServiceDelegator.addProfilePicture(token, userName, fileName, mimeType, pictureData);
    }

    /* Labels API */
    public Vector getLabelsById(String token, String objectId) throws NotPermittedException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getLabelsById(token, makePageId(objectId)));
    }

    public Vector getMostPopularLabels(String token, int maxCount) throws NotPermittedException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getMostPopularLabels(token, maxCount));
    }

    public Vector getMostPopularLabelsInSpace(String token, String spaceKey, int maxCount) throws NotPermittedException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getMostPopularLabelsInSpace(token, spaceKey, maxCount));
    }

    public Vector getLabelContentById(String token, String labelId) throws NotPermittedException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getLabelContentById(token, Long.parseLong(labelId)));
    }

    public Vector getLabelContentByName(String token, String labelName) throws NotPermittedException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getLabelContentByName(token, labelName));
    }

    public Vector getLabelContentByObject(String token, Hashtable labelObject) throws NotPermittedException, RemoteException
    {
        // Convert the Hashtable into a RemoteLabel object
        RemoteLabel remoteLabel = new RemoteLabel();

        convertLong(labelObject, "id");

        try
        {
            BeanUtils.populate(remoteLabel, labelObject);
        }
        catch (IllegalAccessException e)
        {
            throw new InfrastructureException("Error in populating RemoteLabel bean", e);
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }

        return Translator.makeVector(soapServiceDelegator.getLabelContentByObject(token, remoteLabel));
    }

    public Vector getRecentlyUsedLabels(String token, int maxResults) throws InvalidSessionException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getRecentlyUsedLabels(token, maxResults));
    }

    public Vector getRecentlyUsedLabelsInSpace(String token, String spaceKey, int maxResults) throws InvalidSessionException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getRecentlyUsedLabelsInSpace(token, spaceKey, maxResults));
    }

    public Vector getSpacesWithLabel(String token, String labelName) throws InvalidSessionException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getSpacesWithLabel(token, labelName));
    }

    public Vector getRelatedLabels(String token, String labelName, int maxResults) throws InvalidSessionException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getRelatedLabels(token, labelName, maxResults));
    }

    public Vector getRelatedLabelsInSpace(String token, String labelName, String spaceKey, int maxResults) throws InvalidSessionException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getRelatedLabelsInSpace(token, labelName, spaceKey, maxResults));
    }

    public Vector getLabelsByDetail(String token, String labelName, String namespace, String spaceKey, String owner) throws InvalidSessionException, RemoteException, NotPermittedException
    {
        return Translator.makeVector(soapServiceDelegator.getLabelsByDetail(token, labelName, namespace, spaceKey, owner));
    }

    public Vector getSpacesContainingContentWithLabel(String token, String labelName) throws InvalidSessionException, RemoteException
    {
        return Translator.makeVector(soapServiceDelegator.getSpacesContainingContentWithLabel(token, labelName));
    }

    public boolean addLabelByName(String token, String labelName, String objectId) throws NotPermittedException, RemoteException
    {
        return soapServiceDelegator.addLabelByName(token, labelName, Long.parseLong(objectId));
    }

    public boolean addLabelById(String token, String labelId, String objectId) throws NotPermittedException, RemoteException
    {
        return soapServiceDelegator.addLabelById(token, Long.parseLong(labelId), Long.parseLong(objectId));
    }

    public boolean addLabelByObject(String token, Hashtable labelObject, String objectId) throws NotPermittedException, RemoteException
    {
        // Convert the Hashtable into a RemoteLabel object
        RemoteLabel remoteLabel = new RemoteLabel();

        convertLong(labelObject, "id");

        try
        {
            BeanUtils.populate(remoteLabel, labelObject);
        }
        catch (IllegalAccessException e)
        {
            throw new InfrastructureException("Error in populating RemoteLabel bean", e);
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }

        return soapServiceDelegator.addLabelByObject(token, remoteLabel, Long.parseLong(objectId));
    }

    public boolean addLabelByNameToSpace(String token, String labelName, String spaceKey) throws NotPermittedException, InvalidSessionException, RemoteException
    {
        return soapServiceDelegator.addLabelByNameToSpace(token, labelName, spaceKey);
    }

    public boolean removeLabelByName(String token, String labelName, String objectId) throws NotPermittedException, RemoteException
    {
        return soapServiceDelegator.removeLabelByName(token, labelName, Long.parseLong(objectId));
    }

    public boolean removeLabelById(String token, String labelId, String objectId) throws NotPermittedException, RemoteException
    {
        return soapServiceDelegator.removeLabelById(token, Long.parseLong(labelId), Long.parseLong(objectId));
    }

    public boolean removeLabelByObject(String token, Hashtable labelObject, String objectId) throws NotPermittedException, RemoteException
    {
        // Convert the Hashtable into a RemoteLabel object
        RemoteLabel remoteLabel = new RemoteLabel();

        convertLong(labelObject, "id");

        try
        {
            BeanUtils.populate(remoteLabel, labelObject);
        }
        catch (IllegalAccessException e)
        {
            throw new InfrastructureException("Error in populating RemoteLabel bean", e);
        }
        catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }

        return soapServiceDelegator.removeLabelByObject(token, remoteLabel, Long.parseLong(objectId));
    }

    public boolean removeLabelByNameFromSpace(String token, String labelName, String spaceKey) throws NotPermittedException, InvalidSessionException, RemoteException
    {
        return soapServiceDelegator.removeLabelByNameFromSpace(token, labelName, spaceKey);
    }

}