/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 * http://www.dspace.org/license/
 */
package org.dspace.content.crosswalk;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.AuthorizeManager;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.content.DSpaceObject;
import org.dspace.content.packager.PackageException;
import org.dspace.content.packager.PackageUtils;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group;
import org.jdom.Element;
import org.jdom.Namespace;

/**
 * METSRights Ingestion & Dissemination Crosswalk
 * <p>
 * Translate between DSpace internal policies (i.e. permissions) and the
 * METSRights metadata schema
 * (see <a href="http://www.loc.gov/standards/rights/METSRights.xsd">
 * http://www.loc.gov/standards/rights/METSRights.xsd</a> for details).
 * <p>
 * Examples of METSRights usage available from:
 * <a href="http://www.loc.gov/standards/rights/">
 * http://www.loc.gov/standards/rights/</a>
 * <p>
 * This Crosswalk provides a way to export DSpace permissions into a standard
 * format, and then re-import or restore them into a DSpace instance.
 *
 * @author Tim Donohue
 * @version $Revision: 2108 $
 */
public class METSRightsCrosswalk 
    implements IngestionCrosswalk, DisseminationCrosswalk
{
    /** log4j category */
    private static Logger log = Logger.getLogger(METSRightsCrosswalk.class);

    private static final Namespace METSRights_NS =
        Namespace.getNamespace("rights", "http://cosimo.stanford.edu/sdr/metsrights/");

    // XML schemaLocation fragment for this crosswalk, from config.
    private String schemaLocation =
        METSRights_NS.getURI()+" http://cosimo.stanford.edu/sdr/metsrights.xsd";

    private static final Namespace namespaces[] = { METSRights_NS };

    private static final Map<Integer,String> otherTypesMapping = new HashMap<Integer,String>();
    static
    {
        //Mapping of DSpace Policy Actions to METSRights PermissionType values
        // (These are the values stored in the @OTHERPERMITTYPE attribute in METSRights)
        // NOTE: READ, WRITE, DELETE are not included here as they map directly to existing METSRights PermissionTypes
        otherTypesMapping.put(Constants.ADD, "ADD CONTENTS");
        otherTypesMapping.put(Constants.REMOVE, "REMOVE CONTENTS");
        otherTypesMapping.put(Constants.ADMIN, "ADMIN");
        otherTypesMapping.put(Constants.DEFAULT_BITSTREAM_READ, "READ FILE CONTENTS");
        otherTypesMapping.put(Constants.DEFAULT_ITEM_READ, "READ ITEM CONTENTS");
    }

    // Value of METSRights <Context> @CONTEXTCLASS attribute to use for DSpace Groups
    private static final String GROUP_CONTEXTCLASS = "MANAGED GRP";
    // Value of METSRights <Context> @CONTEXTCLASS attribute to use for DSpace EPeople
    private static final String PERSON_CONTEXTCLASS = "ACADEMIC USER";
    // Value of METSRights <Context> @CONTEXTCLASS attribute to use for "Anonymous" DSpace Group
    private static final String ANONYMOUS_CONTEXTCLASS = "GENERAL PUBLIC";
    // Value of METSRights <Context> @CONTEXTCLASS attribute to use for "Administrator" DSpace Group
    private static final String ADMIN_CONTEXTCLASS = "REPOSITORY MGR";
    // Value of METSRights <UserName> @USERTYPE attribute to use for DSpace Groups
    private static final String GROUP_USERTYPE = "GROUP";
    // Value of METSRights <UserName> @USERTYPE attribute to use for DSpace Groups
    private static final String PERSON_USERTYPE = "INDIVIDUAL";


    /*----------- Dissemination functions -------------------*/

    @Override
    public Namespace[] getNamespaces()
    {
        return (Namespace[]) ArrayUtils.clone(namespaces);
    }

    @Override
    public String getSchemaLocation()
    {
        return schemaLocation;
    }

    @Override
    public boolean canDisseminate(DSpaceObject dso)
    {
        //can disseminate all types of DSpace Objects, except for SITE
        return (dso.getType()!=Constants.SITE);
    }

    /**
     * Actually Disseminate into METSRights schema.  This method locates all DSpace
     * policies (permissions) for the provided object, and translates them into
     * METSRights PermissionTypes.
     *
     * @param dso DSpace Object
     * @return XML Element corresponding to the new <RightsDeclarationMD> translation
     * @throws CrosswalkException
     * @throws IOException
     * @throws SQLException
     * @throws AuthorizeException
     */
    @Override
    public Element disseminateElement(DSpaceObject dso)
        throws CrosswalkException,
               IOException, SQLException, AuthorizeException
    {
        if(dso==null)
        {
            return null;
        }
        // we don't have a way to provide METSRights for a SITE object
        else if(dso.getType() == Constants.SITE)
        {
            throw new CrosswalkObjectNotSupported("The METSRightsCrosswalk cannot crosswalk a SITE object");
        }


        //Root element: RightsDeclarationMD
        // All DSpace content is just under LICENSE -- no other rights can be claimed
        Element rightsMD = new Element("RightsDeclarationMD", METSRights_NS);
        rightsMD.setAttribute("RIGHTSCATEGORY", "LICENSED");

        //Three sections to METSRights:
        // * RightsDeclaration - general rights statement
        // * RightsHolder - info about who owns rights
        // * Context - info about specific permissions granted
        // We're just crosswalking DSpace policies to "Context" permissions by default
        // It's too difficult to make statements about who owns the rights and
        // what those rights are -- too many types of content can be stored in DSpace

        //Get all policies on this DSpace Object
        Context context = new Context();
        List<ResourcePolicy> policies = AuthorizeManager.getPolicies(context, dso);

        //For each DSpace policy
        for(ResourcePolicy policy : policies)
        {
           // DSpace Policies can either reference a Group or an Individual, but not both!
           Group group = policy.getGroup();
           EPerson person = policy.getEPerson();

           // Create our <Context> node for this policy
           Element rightsContext = new Element("Context", METSRights_NS);

  
           //First, handle Group-based policies
           // For Group policies we need to setup a
           // <Context CONTEXTCLASS='[group-type]'><UserName USERTYPE='GROUP'>[group-name]</UserName>...
           if(group != null)
           {
              //Default all DSpace groups to have "MANAGED GRP" as the type
              String contextClass=GROUP_CONTEXTCLASS;

              if(group.getID()==0) //DSpace Anonymous Group = 'GENERAL PUBLIC' type
              {
                  contextClass = ANONYMOUS_CONTEXTCLASS;
              }
              else if(group.getID()==1) //DSpace Administrator Group = 'REPOSITORY MGR' type
              {
                  contextClass = ADMIN_CONTEXTCLASS;
              }

              rightsContext.setAttribute("CONTEXTCLASS", contextClass);

              //If this is a "MANAGED GRP", then create a <UserName> child
              //to specify the group Name, and set @USERTYPE='GROUP'
              if(contextClass.equals(GROUP_CONTEXTCLASS))
              {
                  try
                  {
                      //Translate the Group name for export.  This ensures that groups with Internal IDs in their names
                      // (e.g. COLLECTION_1_ADMIN) are properly translated using the corresponding Handle or external identifier.
                      String exportGroupName = PackageUtils.translateGroupNameForExport(context, group.getName());

                      //If translated group name is returned as "null", this means the Group name
                      // had an Internal Collection/Community ID embedded, which could not be
                      // translated properly to a Handle.  We will NOT export these groups,
                      // as they could cause conflicts or data integrity problems if they are
                      // imported into another DSpace system.
                      if(exportGroupName!=null && !exportGroupName.isEmpty())
                      {
                          //Create <UserName USERTYPE='GROUP'> element.  Add the Group's name to that element
                          Element rightsUser = new Element("UserName", METSRights_NS);
                          rightsUser.setAttribute("USERTYPE",GROUP_USERTYPE);
                          rightsUser.addContent(exportGroupName);
                          rightsContext.addContent(rightsUser);
                      }
                      else
                          //Skip over this Group, as we couldn't translate it for export.
                          //The Group seems to refer to a Community or Collection which no longer exists
                          continue; 
                  }
                  catch(PackageException pe)
                  {
                      //A PackageException will only be thrown if translateGroupNameForExport() fails
                      //We'll just wrap it as a CrosswalkException and throw it upwards
                      throw new CrosswalkException(pe);
                  }
              }

              rightsMD.addContent(rightsContext);

           }//end if group
           //Next, handle User-based policies
           // For User policies we need to setup a
           // <Context CONTEXTCLASS='ACADEMIC USER'><UserName USERTYPE='INDIVIDUAL'>[group-name]</UserName>...
           else if(person!=null)
           {
              // All EPeople are considered 'Academic Users'
              rightsContext.setAttribute("CONTEXTCLASS", PERSON_CONTEXTCLASS);

              //Create a <UserName> node corresponding to person's email, set @USERTYPE='INDIVIDUAL'
              Element rightsUser = new Element("UserName", METSRights_NS);
              rightsUser.setAttribute("USERTYPE",PERSON_USERTYPE);
              rightsUser.addContent(person.getEmail());
              rightsContext.addContent(rightsUser);

              rightsMD.addContent(rightsContext);
           }//end if person
           else
               log.error("Policy " + String.valueOf(policy.getID())
                       + " is neither user nor group!  Omitted from package.");


           //Translate the DSpace ResourcePolicy into a <Permissions> element
           Element rightsPerm = translatePermissions(policy);
           rightsContext.addContent(rightsPerm);
           
        }//end for each policy

        context.complete();
        return rightsMD;
    }

    @Override
    public List<Element> disseminateList(DSpaceObject dso)
        throws CrosswalkException,
               IOException, SQLException, AuthorizeException
    {
        List<Element> result = new ArrayList<Element>(1);
        result.add(disseminateElement(dso));
        return result;
    }

    @Override
    public boolean preferList()
    {
        return false;
    }


    /**
     * Translates a DSpace ResourcePolicy's permissions into a METSRights
     * <code>Permissions</code> element. Returns the created
     * <code>Permissions</code> element. This element may be empty if
     * there was an issue translating the ResourcePolicy.
     *
     * @param policy  The DSpace ResourcePolicy
     * @return the Element representing the METSRIghts <code>Permissions</code> or null.
     */
    private Element translatePermissions(ResourcePolicy policy)
    {
        //Create our <Permissions> node to store all permissions in this context
        Element rightsPerm = new Element("Permissions", METSRights_NS);

        //Determine the 'actions' permitted by this DSpace policy, and translate to METSRights PermissionTypes
        int action = policy.getAction();
        //All READ-based actions = cannot modify or delete object
        if(action==Constants.READ
                || action==Constants.DEFAULT_BITSTREAM_READ
                || action==Constants.DEFAULT_ITEM_READ)
        {
             // For DSpace, READ = Discover and Display
             rightsPerm.setAttribute("DISCOVER", "true");
             rightsPerm.setAttribute("DISPLAY", "true");
             //Read = cannot modify or delete
             rightsPerm.setAttribute("MODIFY", "false");
             rightsPerm.setAttribute("DELETE", "false");
        }
        //All WRITE-based actions = can modify, but cannot delete
        else if(action == Constants.WRITE
                || action==Constants.ADD)
        {
            rightsPerm.setAttribute("DISCOVER", "true");
            rightsPerm.setAttribute("DISPLAY", "true");
            //Write = can modify, but cannot delete
            rightsPerm.setAttribute("MODIFY", "true");
            rightsPerm.setAttribute("DELETE", "false");
        }
        //All DELETE-based actions = can modify & can delete
        //(NOTE: Although Constants.DELETE is marked as "obsolete", it is still used in dspace-api)
        else if(action == Constants.DELETE
                || action==Constants.REMOVE)
        {
            rightsPerm.setAttribute("DISCOVER", "true");
            rightsPerm.setAttribute("DISPLAY", "true");
            //Delete = can both modify and delete
            rightsPerm.setAttribute("MODIFY", "true");
            rightsPerm.setAttribute("DELETE", "true");
        }
        //ADMIN action = full permissions
        else if(action == Constants.ADMIN)
        {
            rightsPerm.setAttribute("DISCOVER", "true");
            rightsPerm.setAttribute("DISPLAY", "true");
            rightsPerm.setAttribute("COPY", "true");
            rightsPerm.setAttribute("DUPLICATE", "true");
            rightsPerm.setAttribute("MODIFY", "true");
            rightsPerm.setAttribute("DELETE", "true");
            rightsPerm.setAttribute("PRINT", "true");
        }
        else
        {
            //Unknown action -- don't enable any rights by default
            //NOTE: ALL WORKFLOW RELATED ACTIONS ARE NOT INCLUDED IN METSRIGHTS
            //DSpace API no longer assigns nor checks any of the following 'action' types:
            // * Constants.WORKFLOW_STEP_1
            // * Constants.WORKFLOW_STEP_2
            // * Constants.WORKFLOW_STEP_3
            // * Constants.WORKFLOW_ABORT
        }//end if

        //Also add in OTHER permissionTypes, as necessary (see 'otherTypesMapping' above)
        // (These OTHER permissionTypes are used to tell apart similar DSpace permissions during Ingestion)
        if(otherTypesMapping.containsKey(action))
        {
            //if found in our 'otherTypesMapping', enable @OTHER attribute and add in the appropriate value to @OTHERPERMITTYPE attribute
            rightsPerm.setAttribute("OTHER", "true");
            rightsPerm.setAttribute("OTHERPERMITTYPE", otherTypesMapping.get(action));
        }

        return rightsPerm;
    }


    /*----------- Ingestion functions -------------------*/

    /**
     * Ingest a whole XML document, starting at specified root.
     *
     * @param context
     * @param dso
     * @param root
     * @throws CrosswalkException
     * @throws IOException
     * @throws SQLException
     * @throws AuthorizeException
     */
    @Override
    public void ingest(Context context, DSpaceObject dso, Element root)
        throws CrosswalkException, IOException, SQLException, AuthorizeException
    {
        if (!(root.getName().equals("RightsDeclarationMD")))
        {
            throw new MetadataValidationException("Wrong root element for METSRights: " + root.toString());
        }
        ingest(context, dso, root.getChildren());
    }

    /**
     * Ingest a List of XML elements
     * <P>
     * This method creates new DSpace Policies based on the parsed
     * METSRights XML contents. These Policies assign permissions
     * to DSpace Groups or EPeople.
     * <P>
     * NOTE: This crosswalk will NOT create missing DSpace Groups or EPeople.
     * Therefore, it is recommended to use this METSRightsCrosswalk in
     * conjunction with another Crosswalk which can create/restore missing
     * Groups or EPeople (e.g. RoleCrosswalk).
     *
     * @param context
     * @param dso
     * @throws CrosswalkException
     * @throws IOException
     * @throws SQLException
     * @throws AuthorizeException
     * @see RoleCrosswalk
     */
    @Override
    public void ingest(Context context, DSpaceObject dso, List<Element> ml)
        throws CrosswalkException, IOException, SQLException, AuthorizeException
    {
        // we cannot crosswalk METSRights to a SITE object
        if (dso.getType() == Constants.SITE)
        {
            throw new CrosswalkObjectNotSupported("Wrong target object type, METSRightsCrosswalk cannot crosswalk a SITE object.");
        }

        //First, clear all existing Policies on this DSpace Object
        // as we don't want them to conflict with policies we will be adding
        if(!ml.isEmpty())
        {
            AuthorizeManager.removeAllPolicies(context, dso);
        }

        // Loop through each Element in the List
        for (Element element : ml)
        {
            // if we're fed a <RightsDeclarationMD> wrapper object, recurse on its guts:
            if (element.getName().equals("RightsDeclarationMD"))
            {
                ingest(context, dso, element.getChildren());
            }
            // "Context" section (where permissions are stored)
            else if (element.getName().equals("Context"))
            {
                //get what class of context this is
                String contextClass = element.getAttributeValue("CONTEXTCLASS");

                //also get reference to the <Permissions> element
                Element permsElement = element.getChild("Permissions", METSRights_NS);

                //Check if this permission pertains to Anonymous users
                if(ANONYMOUS_CONTEXTCLASS.equals(contextClass))
                {
                    //get DSpace Anonymous group, ID=0
                    Group anonGroup = Group.find(context, 0);
                    if(anonGroup==null)
                    {
                        throw new CrosswalkInternalException("The DSpace database has not been properly initialized.  The Anonymous Group is missing from the database.");
                    }

                    assignPermissions(context, dso, anonGroup, permsElement);
                } // else if this permission declaration pertains to Administrators
                else if(ADMIN_CONTEXTCLASS.equals(contextClass))
                {
                    //get DSpace Administrator group, ID=1
                    Group adminGroup = Group.find(context, 1);
                    if(adminGroup==null)
                    {
                        throw new CrosswalkInternalException("The DSpace database has not been properly initialized.  The Administrator Group is missing from the database.");
                    }

                    assignPermissions(context, dso, adminGroup, permsElement);
                } // else if this permission pertains to another DSpace group
                else if(GROUP_CONTEXTCLASS.equals(contextClass))
                {
                    try
                    {
                        //we need to find the name of DSpace group it pertains to
                        //Get the text within the <UserName> child element,
                        // this is the group's name
                        String groupName = element.getChildTextTrim("UserName", METSRights_NS);

                        //Translate Group name back to internal ID format (e.g. COLLECTION_<ID>_ADMIN)
                        // from its external format (e.g. COLLECTION_<handle>_ADMIN)
                        groupName = PackageUtils.translateGroupNameForImport(context, groupName);

                        //Check if this group exists in DSpace already
                        Group group = Group.findByName(context, groupName);

                        //if not found, throw an error -- user should restore group from the SITE AIP
                        if(group==null)
                        {
                            throw new CrosswalkInternalException("Cannot restore Group permissions on object ("
                                    + "type=" + Constants.typeText[dso.getType()] + ", "
                                    + "handle=" + dso.getHandle() + ", "
                                    + "ID=" + dso.getID()
                                    + "). The Group named '" + groupName + "' is missing from DSpace. "
                                    + "Please restore this group using the SITE AIP, or recreate it.");
                        }

                        //assign permissions to group on this object
                        assignPermissions(context, dso, group, permsElement);
                    }
                    catch(PackageException pe)
                    {
                        //A PackageException will only be thrown if translateDefaultGroupName() fails
                        //We'll just wrap it as a CrosswalkException and throw it upwards
                        throw new CrosswalkException(pe);
                    }
                }//end if Group
                else if(PERSON_CONTEXTCLASS.equals(contextClass))
                {
                    //we need to find the person it pertains to
                    // Get the text within the <UserName> child element,
                    // this is the person's email address
                    String personEmail = element.getChildTextTrim("UserName", METSRights_NS);

                    //Check if this person exists in DSpace already
                    EPerson person = EPerson.findByEmail(context, personEmail);

                    //If cannot find by email, try by netID
                    //(though METSRights should contain email if it was exported by DSpace)
                    if(person==null)
                    {
                        person = EPerson.findByNetid(context, personEmail);
                    }

                    //if not found, throw an error -- user should restore person from the SITE AIP
                    if(person==null)
                    {
                        throw new CrosswalkInternalException("Cannot restore Person permissions on object ("
                                + "type=" + Constants.typeText[dso.getType()] + ", "
                                + "handle=" + dso.getHandle() + ", "
                                + "ID=" + dso.getID()
                                + "). The Person with email/netid '" + personEmail + "' is missing from DSpace. "
                                + "Please restore this Person object using the SITE AIP, or recreate it.");
                    }

                    //assign permissions to person on this object
                    assignPermissions(context, dso, person, permsElement);
                }//end if Person
                else
                    log.error("Unrecognized CONTEXTCLASS:  " + contextClass);
            } //end if "Context" element
        }//end while loop
    }


    /**
     * Parses the 'permsElement' (corresponding to a <code>Permissions</code>
     * element), and assigns those permissions to the specified Group
     * on the specified DSpace Object.
     *
     * @param context DSpace context object
     * @param dso The DSpace Object
     * @param group The DSpace Group
     * @param permsElement The METSRights <code>Permissions</code> element
     */
    private void assignPermissions(Context context, DSpaceObject dso, Group group, Element permsElement)
            throws SQLException, AuthorizeException
    {
        //first, parse our permissions to determine which action we are allowing in DSpace
        int actionID = parsePermissions(permsElement);

        //If action ID is less than base READ permissions (value=0),
        // then something must've gone wrong in the parsing
        if(actionID < Constants.READ)
        {
            log.warn("Unable to properly restore all access permissions on object ("
                        + "type=" + Constants.typeText[dso.getType()] + ", "
                        + "handle=" + dso.getHandle() + ", "
                        + "ID=" + dso.getID()
                        + ") for group '" + group.getName() + "'.");
        }

        //Otherwise, add the appropriate group policy for this object
        AuthorizeManager.addPolicy(context, dso, actionID, group);
    }

     /**
     * Parses the 'permsElement' (corresponding to a <code>Permissions</code>
     * element), and assigns those permissions to the specified EPerson
     * on the specified DSpace Object.
     *
     * @param context DSpace context object
     * @param dso The DSpace Object
     * @param person The DSpace EPerson
     * @param permsElement The METSRights <code>Permissions</code> element
     */
    private void assignPermissions(Context context, DSpaceObject dso, EPerson person, Element permsElement)
            throws SQLException, AuthorizeException
    {
        //first, parse our permissions to determine which action we are allowing in DSpace
        int actionID = parsePermissions(permsElement);

        //If action ID is less than base READ permissions (value=0),
        // then something must've gone wrong in the parsing
        if(actionID < Constants.READ)
        {
            log.warn("Unable to properly restore all access permissions on object ("
                        + "type=" + Constants.typeText[dso.getType()] + ", "
                        + "handle=" + dso.getHandle() + ", "
                        + "ID=" + dso.getID()
                        + ") for person '" + person.getEmail() + "'.");
        }

        //Otherwise, add the appropriate EPerson policy for this object
        AuthorizeManager.addPolicy(context, dso, actionID, person);
    }

    /**
     * Parses the 'permsElement' (corresponding to a <code>Permissions</code>
     * element) to find the corresponding DSpace permission type.  This
     * DSpace permission type must be one of the Action IDs specified in
     * <code>org.dspace.core.Constants</code>
     * <P>
     * Returns -1 if failed to parse permissions.
     *
     * @param permsElement The METSRights <code>Permissions</code> element
     * @return A DSpace Action ID from <code>org.dspace.core.Constants</code>
     */
    private int parsePermissions(Element permsElement)
    {
        //First, check if the @OTHERPERMITTYPE attribute is specified
        String otherPermitType = permsElement.getAttributeValue("OTHERPERMITTYPE");

        //if @OTHERPERMITTYPE attribute exists, it will map directly to a DSpace Action type
        if(otherPermitType!=null && !otherPermitType.isEmpty())
        {
            if(otherTypesMapping.containsValue(otherPermitType))
            {
                //find the Action ID this value maps to
                for(int actionType: otherTypesMapping.keySet())
                {
                    //if found, this is the Action ID corresponding to this permission
                    if(otherTypesMapping.get(actionType).equals(otherPermitType))
                    {
                        return actionType;
                    }
                }
            }
            else
            {
                log.warn("Unrecognized @OTHERPERMITTYPE attribute value ("
                            + otherPermitType
                            + ") found in METSRights section of METS Manifest.");
            }
        }
        else // Otherwise, a closer analysis of all Permission element attributes is necessary
        {
            boolean discoverPermit = Boolean.parseBoolean(permsElement.getAttributeValue("DISCOVER"));
            boolean displayPermit = Boolean.parseBoolean(permsElement.getAttributeValue("DISPLAY"));
            boolean modifyPermit = Boolean.parseBoolean(permsElement.getAttributeValue("MODIFY"));
            boolean deletePermit = Boolean.parseBoolean(permsElement.getAttributeValue("DELETE"));
            boolean otherPermit = Boolean.parseBoolean(permsElement.getAttributeValue("OTHER"));

            //if DELETE='true'
            if(deletePermit && !otherPermit)
            {
                //This must refer to the DELETE action type
                //(note REMOVE & ADMIN action type have @OTHERPERMITTYPE values specified)
                return Constants.DELETE;
            }//if MODIFY='true'
            else if(modifyPermit && !otherPermit)
            {
                //This must refer to the WRITE action type
                //(note ADD action type has an @OTHERPERMITTYPE value specified)
                return Constants.WRITE;
            }
            else if(discoverPermit && displayPermit && !otherPermit)
            {
                //This must refer to the READ action type
                return Constants.READ;
            }
        }

        //if we got here, we failed to parse out proper permissions
        // return -1 to signify failure (as 0 = READ permissions)
        return -1;
    }
}
