Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package edu.harvard.iq.dataverse.mydata; import edu.harvard.iq.dataverse.DvObject; import edu.harvard.iq.dataverse.DvObjectServiceBean; import edu.harvard.iq.dataverse.RoleAssigneeServiceBean; import edu.harvard.iq.dataverse.authorization.DataverseRolePermissionHelper; import edu.harvard.iq.dataverse.authorization.groups.GroupServiceBean; import edu.harvard.iq.dataverse.search.SearchFields; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.logging.Logger; import javax.json.Json; import javax.json.JsonArrayBuilder; import javax.json.JsonObjectBuilder; import org.apache.commons.lang.StringUtils; /** * Given a user and a set of filters (dvobject type, roles, publication status): * - Use postgres to identify DvObject types * - Format a solr query string * * @author rmp553 */ //@Stateless public class MyDataFinder { private static final Logger logger = Logger.getLogger(MyDataFinder.class.getCanonicalName()); private String userIdentifier; MyDataFilterParams filterParams; // !! RMP - Excluded by default; don't have cases yet to make this true private boolean excludeHarvestedData = true; //private String searchTerm = "*"; // -------------------- private DataverseRolePermissionHelper rolePermissionHelper; private RoleAssigneeServiceBean roleAssigneeService; private DvObjectServiceBean dvObjectServiceBean; private GroupServiceBean groupService; //private RoleAssigneeServiceBean roleService = new RoleAssigneeServiceBean(); //private MyDataQueryHelperServiceBean myDataQueryHelperService; // -------------------- public boolean errorFound = false; public String errorMessage = null; // -------------------- public Map<Long, Boolean> harvestedDataverseIds = new HashMap<>(); // Populated in initial query. DvObject ids -- regardless of Dtype, // are sorted into respective buckets in regard to permissions. // The same id may appear in multiple lists--and more than once // // ---------------------------- // POPULATED IN STEP 1 (1st query) // ---------------------------- public Map<Long, Long> childToParentIds = new HashMap<>(); public Map<Long, Boolean> idsWithDataversePermissions = new HashMap<>(); // { role id : true } public Map<Long, Boolean> idsWithDatasetPermissions = new HashMap<>(); // { role id : true } public Map<Long, Boolean> idsWithFilePermissions = new HashMap<>(); // { role id : true } private List<Long> directDvObjectIds = new ArrayList<>(); // Lists later used to format Solr Queries // // ---------------------------- // POPULATED IN STEP 2 (2nd query) // ---------------------------- private List<Long> directDataverseIds = new ArrayList<>(); private List<Long> directDatasetIds = new ArrayList<>(); private List<Long> directFileIds = new ArrayList<>(); private List<Long> datasetParentIds = new ArrayList<>(); // dataverse has dataset permissions private List<Long> fileParentIds = new ArrayList<>(); // dataset has file permissions private List<Long> fileGrandparentFileIds = new ArrayList<>(); // dataverse has file permissions public MyDataFinder(DataverseRolePermissionHelper rolePermissionHelper, RoleAssigneeServiceBean roleAssigneeService, DvObjectServiceBean dvObjectServiceBean, GroupServiceBean groupService) { this.msgt("MyDataFinder, constructor"); this.rolePermissionHelper = rolePermissionHelper; this.roleAssigneeService = roleAssigneeService; this.dvObjectServiceBean = dvObjectServiceBean; this.groupService = groupService; this.loadHarvestedDataverseIds(); } private void loadHarvestedDataverseIds() { for (Long id : dvObjectServiceBean.getAllHarvestedDataverseIds()) { harvestedDataverseIds.put(id, true); } } public void setExcludeHarvestedData(boolean val) { this.excludeHarvestedData = val; } public boolean isHarvestedDataExcluded() { return excludeHarvestedData; } /** * Check if a dvobject id is in the Harvested Id dict * @param id * @return */ private boolean isHarvesteDataverseId(Long id) { if (id == null) { return false; } if (this.harvestedDataverseIds.containsKey(id)) { return true; } return false; } public void initFields() { // ---------------------------- // POPULATED IN STEP 1 (1st query) // ---------------------------- this.childToParentIds = new HashMap<>(); this.idsWithDataversePermissions = new HashMap<>(); // { role id : true } this.idsWithDatasetPermissions = new HashMap<>(); // { role id : true } this.idsWithFilePermissions = new HashMap<>(); // { role id : true } this.directDvObjectIds = new ArrayList<>(); // Lists later used to format Solr Queries // // ---------------------------- // POPULATED IN STEP 2 (2nd query) // ---------------------------- this.directDataverseIds = new ArrayList<>(); this.directDatasetIds = new ArrayList<>(); this.directFileIds = new ArrayList<>(); this.datasetParentIds = new ArrayList<>(); // dataverse has dataset permissions this.fileParentIds = new ArrayList<>(); // dataset has file permissions this.fileGrandparentFileIds = new ArrayList<>(); // dataverse has file permissions } public DataverseRolePermissionHelper getRolePermissionHelper() { return this.rolePermissionHelper; } /* private ArrayList<Long> dataverseIds; private ArrayList<Long> primaryDatasetIds; private ArrayList<Long> primaryFileIds; private ArrayList<Long> parentIds; */ /*public void runFindDataSteps(String userIdentifier){ this.userIdentifier = userIdentifier; msgt("runFindDataSteps: " + userIdentifier); if (!runStep1RoleAssignments()){ return; } if (!runStep2DirectAssignments()){ return; } if (!fileGrandparentFileIds.isEmpty()){ runStep3FilePermsAssignedAtDataverse(); } }*/ public void runFindDataSteps(MyDataFilterParams filterParams) { this.filterParams = filterParams; this.userIdentifier = this.filterParams.getUserIdentifier(); if (this.filterParams.hasError()) { this.addErrorMessage(filterParams.getErrorMessage()); return; } if (!runStep1RoleAssignments()) { return; } if (!runStep2DirectAssignments()) { return; } if (!fileGrandparentFileIds.isEmpty()) { runStep3FilePermsAssignedAtDataverse(); } } public List<String> getSolrFilterQueriesForTotalCounts() { return this.getSolrFilterQueries(true); } public List<String> getSolrFilterQueries() { return this.getSolrFilterQueries(false); } /** * Get the final queries for the Solr Search object * * @return */ private List<String> getSolrFilterQueries(boolean totalCountsOnly) { if (this.hasError()) { throw new IllegalStateException( "Error encountered earlier. Before calling this method on a MyDataFinder object, first check 'hasError()'"); } // init filterQueries list List<String> filterQueries = new ArrayList<>(); // ----------------------------------------------------------------- // (1) Add entityId/parentId FQ // - by entityId (dvObject id) and parentId (dvObject ownerId) // ----------------------------------------------------------------- String dvObjectFQ = this.getSolrDvObjectFilterQuery(); if (dvObjectFQ == null) { this.addErrorMessage(DataRetrieverAPI.MSG_NO_RESULTS_FOUND); return null; } filterQueries.add(dvObjectFQ); // ----------------------------------------------------------------- // For total counts, don't filter by publicationStatus or DvObjectType // ----------------------------------------------------------------- if (totalCountsOnly == true) { return filterQueries; } // ----------------------------------------------------------------- // (2) FQ by dvObjectType // ----------------------------------------------------------------- filterQueries.add(this.filterParams.getSolrFragmentForDvObjectType()); //fq=dvObjectType:(dataverses+OR+datasets+OR+files) //fq=(dvObjectType:Dataset) //filterQueries.add("dvObjectType:(dataverses OR datasets OR files)"); // ----------------------------------------------------------------- // (3) FQ by Publication Status // ----------------------------------------------------------------- filterQueries.add(this.filterParams.getSolrFragmentForPublicationStatus()); //fq=publicationStatus:"Unpublished"&fq=publicationStatus:"Draft" return filterQueries; } public String getSolrDvObjectFilterQuery() { if (this.hasError()) { throw new IllegalStateException( "Error encountered earlier. Before calling this method on a MyDataFinder object,first check 'hasError()'"); } // Build lists of Ids List<Long> entityIds = new ArrayList<>(); List<Long> parentIds = new ArrayList<>(); List<Long> datasetParentIdsForFQ = new ArrayList<>(); List<Long> fileParentIdsForFQ = new ArrayList<>(); if (this.filterParams.areDataversesIncluded()) { entityIds.addAll(this.directDataverseIds); // dv ids } if (this.filterParams.areDatasetsIncluded()) { entityIds.addAll(this.directDatasetIds); // dataset ids parentIds.addAll(this.datasetParentIds); // dv ids that are dataset parents datasetParentIdsForFQ.addAll(this.datasetParentIds); } if (this.filterParams.areFilesIncluded()) { entityIds.addAll(this.directFileIds); // file ids parentIds.addAll(this.fileParentIds); // dataset ids that are file parents fileParentIdsForFQ.addAll(this.fileParentIds); } // Remove duplicates by Creating a Set // Set<Long> distinctEntityIds = new HashSet<>(entityIds); Set<Long> distinctParentIds = new HashSet<>(parentIds); if ((distinctEntityIds.size() == 0) && (distinctParentIds.size() == 0)) { this.addErrorMessage(DataRetrieverAPI.MSG_NO_RESULTS_FOUND); return null; } msg("distinctEntityIds (1): " + distinctEntityIds.size()); msg("distinctParentIds: " + distinctParentIds.size()); // See if we can trim down the list of distinctEntityIds // If we have the parent of a distinctEntityId in distinctParentIds, // then we query it via the parent // List<Long> finalDirectEntityIds = new ArrayList<>(); for (Long idToCheck : distinctEntityIds) { if (this.childToParentIds.containsKey(idToCheck)) { // Do we have the parent in our map? // we are not checking the parent of dataverses, so add this explicitly // Similar to SEK 7/015 - all direct dataverse ids are used because child dataverses with direct assignments are being lost. // if (this.directDataverseIds.contains(idToCheck)) { // Add all dataverse ids explicitly finalDirectEntityIds.add(idToCheck); } else if (!distinctParentIds.contains(this.childToParentIds.get(idToCheck))) { // Is the parent also in our list of Ids to query? // No, then let's check this id directly // finalDirectEntityIds.add(idToCheck); } } } // Set the distinctEntityIds to the finalDirectEntityIds //distinctEntityIds = new HashSet<>(distinctEntityIds); distinctEntityIds = new HashSet<>(finalDirectEntityIds); msg("distinctEntityIds (2): " + distinctEntityIds.size()); // Start up a SolrQueryFormatter for building clauses // SolrQueryFormatter sqf = new SolrQueryFormatter(); // Build clauses String entityIdClause = null; if (distinctEntityIds.size() > 0) { entityIdClause = sqf.buildIdQuery(distinctEntityIds, SearchFields.ENTITY_ID, null); } String parentIdClause = null; if (distinctParentIds.size() > 0) { parentIdClause = sqf.buildIdQuery(distinctParentIds, SearchFields.PARENT_ID, "datasets OR files"); } if ((entityIdClause != null) && (parentIdClause != null)) { return "(" + entityIdClause + " OR " + parentIdClause + ")"; } else if (entityIdClause != null) { // only entityIdClause return entityIdClause; } else if (parentIdClause != null) { // only parentIdClause return parentIdClause; } // Shouldn't get here... return null; } public String getTestString() { if (this.hasError()) { return this.getErrorMessage(); } List<String> outputList = new ArrayList<>(); // ---------------------- // idsWithDatasetPermissions // ---------------------- List<String> idList = new ArrayList<>(); outputList.add("<h4>dataset ids: " + this.idsWithDatasetPermissions.size() + "</h4>"); for (Map.Entry pair : this.idsWithDatasetPermissions.entrySet()) { idList.add(pair.getKey().toString()); } outputList.add("<pre>" + StringUtils.join(idList, ", ") + "</pre>"); // ---------------------- // datasetParentIds // ---------------------- List<String> idList2 = new ArrayList<>(); outputList.add("<h4>datasetParentIds ids: " + this.datasetParentIds.size() + "</h4>"); for (Long dpId : this.datasetParentIds) { idList2.add(dpId.toString()); } outputList.add("<pre>" + StringUtils.join(idList2, ", ") + "</pre>"); return StringUtils.join(outputList, "<br />"); } public String formatUserIdentifierAsAssigneeIdentifier(String userIdentifier) { if (userIdentifier == null) { return null; } if (userIdentifier.startsWith("@")) { return userIdentifier; } return "@" + userIdentifier; } /** * "publication_statuses" : [ name 1, name 2, etc.] * * @return */ public JsonObjectBuilder getSelectedFilterParamsAsJSON() { JsonObjectBuilder jsonData = Json.createObjectBuilder(); jsonData.add("publication_statuses", this.filterParams.getListofSelectedPublicationStatuses()) .add("role_names", this.getListofSelectedRoles()); return jsonData; } /** * "publication_statuses" : [ name 1, name 2, etc.] * * @return */ public JsonArrayBuilder getListofSelectedRoles() { JsonArrayBuilder jsonArray = Json.createArrayBuilder(); for (Long roleId : this.filterParams.getRoleIds()) { jsonArray.add(this.rolePermissionHelper.getRoleName(roleId)); } return jsonArray; } private boolean runStep1RoleAssignments() { List<Object[]> results = this.roleAssigneeService.getAssigneeAndRoleIdListFor(filterParams); //logger.info("runStep1RoleAssignments results: " + results.toString()); if (results == null) { this.addErrorMessage("Sorry, the EntityManager isn't working (still)."); return false; } else if (results.isEmpty()) { List<String> roleNames = this.rolePermissionHelper.getRoleNamesByIdList(this.filterParams.getRoleIds()); if ((roleNames == null) || (roleNames.isEmpty())) { this.addErrorMessage("Sorry, you have no assigned roles."); } else { if (roleNames.size() == 1) { this.addErrorMessage( "Sorry, nothing was found for this role: " + StringUtils.join(roleNames, ", ")); } else { this.addErrorMessage( "Sorry, nothing was found for these roles: " + StringUtils.join(roleNames, ", ")); } } return false; } // Iterate through assigned objects, a single object may end up in // multiple "buckets" for (Object[] ra : results) { Long dvId = (Long) ra[0]; Long roleId = (Long) ra[1]; //---------------------------------- // Is this is a harvested Dataverse? // If so, skip it. //---------------------------------- if ((this.isHarvestedDataExcluded()) && (this.isHarvesteDataverseId(dvId))) { continue; } //---------------------------------- // Put dvId in 1 or more buckets, depending pn if role // applies to a Dataverse, Dataset, and/or File //---------------------------------- if (this.rolePermissionHelper.hasDataversePermissions(roleId)) { this.idsWithDataversePermissions.put(dvId, true); } if (this.rolePermissionHelper.hasDatasetPermissions(roleId)) { this.idsWithDatasetPermissions.put(dvId, true); } if (this.rolePermissionHelper.hasFilePermissions(roleId)) { this.idsWithFilePermissions.put(dvId, true); } directDvObjectIds.add(dvId); } return true; } private boolean runStep2DirectAssignments() { if (this.hasError()) { throw new IllegalStateException( "Error encountered earlier. Before calling this method on a MyData object,first check 'hasError()'"); } //msgt("runStep2DirectAssignments"); List<Object[]> results = this.dvObjectServiceBean.getDvObjectInfoForMyData(directDvObjectIds); msgt("runStep2DirectAssignments number of results: " + results.size()); //List<RoleAssignment> results = this.roleAssigneeService.getAssignmentsFor(this.userIdentifier); if (results.isEmpty()) { this.addErrorMessage("Sorry, you have no assigned Dataverses, Datasets, or Files."); return false; } Integer dvIdAsInteger; Long dvId; String dtype; Long parentId; // ----------------------------------------------- // Iterate through assigned objects // ----------------------------------------------- for (Object[] ra : results) { dvIdAsInteger = (Integer) ra[0]; // ?? Why? dvId = new Long(dvIdAsInteger); dtype = (String) ra[1]; parentId = (Long) ra[2]; // ----------------------------------------------- // If this object is harvested, then skip it... // ----------------------------------------------- if (this.isHarvestedDataExcluded()) { if ((this.isHarvesteDataverseId(dvId)) || (this.isHarvesteDataverseId(parentId))) { continue; } } this.childToParentIds.put(dvId, parentId); switch (dtype) { case (DvObject.DATAVERSE_DTYPE_STRING): //if (this.idsWithDataversePermissions.containsKey(dvId)){ this.directDataverseIds.add(dvId); // Direct dataverse (no indirect dataverses) //} if (this.idsWithDatasetPermissions.containsKey(dvId)) { this.datasetParentIds.add(dvId); // Parent to dataset } if (this.idsWithFilePermissions.containsKey(dvId)) { this.fileGrandparentFileIds.add(dvId); // Grandparent to file // Also show the Dataset--even though the permissions don't apply directly // e.g. The Permissions flows: // from the DV -> through the DS -> to the file this.datasetParentIds.add(dvId); // Parent to dataset } break; case (DvObject.DATASET_DTYPE_STRING): //if (this.idsWithDatasetPermissions.containsKey(dvId)){ this.directDatasetIds.add(dvId); // Direct dataset //} if (this.idsWithFilePermissions.containsKey(dvId)) { this.fileParentIds.add(dvId); // Parent to file } break; case (DvObject.DATAFILE_DTYPE_STRING): if (this.idsWithFilePermissions.containsKey(dvId)) { this.directFileIds.add(dvId); // Direct file } break; } // end switch } // Direct ids no longer needed // this.directDvObjectIds = null; return true; } private boolean runStep3FilePermsAssignedAtDataverse() { msgt("runStep3FilePermsAssignedAtDataverse"); if ((this.fileGrandparentFileIds == null) || (this.fileGrandparentFileIds.isEmpty())) { return true; } List<Object[]> results = this.dvObjectServiceBean .getDvObjectInfoByParentIdForMyData(this.fileGrandparentFileIds); msg("runStep3FilePermsAssignedAtDataverse results count: " + results.size()); /* SEK 07/09 Ticket 2329 Removed failure for empty results - if there are none let it go */ if (results.isEmpty()) { return true; // RMP, shouldn't throw an error if no results } Integer dvIdAsInteger; Long dvId; String dtype; Long parentId; // Iterate through object list // for (Object[] ra : results) { dvIdAsInteger = (Integer) ra[0]; // ?? Why? dvId = new Long(dvIdAsInteger); dtype = (String) ra[1]; parentId = (Long) ra[2]; this.childToParentIds.put(dvId, parentId); // Should ALWAYS be a Dataset! if (dtype.equals(DvObject.DATASET_DTYPE_STRING)) { this.fileParentIds.add(dvId); } } return true; } /* private void postStep2Cleanup(){ // Clear step1 lookups idsWithDataversePermissions = null; idsWithDatasetPermissions = null; idsWithFilePermissions = null; directDvObjectIds = null; // Direct ids no longer needed }*/ public boolean hasError() { return this.errorFound; } public String getErrorMessage() { return this.errorMessage; } private void addErrorMessage(String s) { this.errorFound = true; this.errorMessage = s; } private void msg(String s) { //logger.fine(s); } private void msgt(String s) { msg("-------------------------------"); msg(s); msg("-------------------------------"); } } // end: MyDataFinder