public static Search_Result search(Database database, Search_Param params) {
        
        Logger.getLogger(API.class.getName()).log(Level.FINE, "Entering API.getFields()");
        Search_Result result;
        try {
            ValidateUser_Result vResult = validateUser(database, new ValidateUser_Param(params.username(), params.password()));
            if (vResult == null || !vResult.validated()) { // not validated
                result = null;
            }
            else { // User exists
                
                // Extract field IDs and convert to ArrayList<String>
                String[] fieldIdArray = params.fields().split(",");
                ArrayList<String> fieldIdsAsStrings = (ArrayList<String>) removeEmptyStrings(Arrays.asList(fieldIdArray));

                // Extract values and convert to ArrayList<String>
                String[] valueArray = params.values().split(",");
                ArrayList<String> values = (ArrayList<String>) removeEmptyStrings(Arrays.asList(valueArray));
                
                // Search database for the Records with values in values and
                // field IDs in fieldIdsAsStrings
                ArrayList<Record> records = (ArrayList) database.search(fieldIdsAsStrings, values);

                // Extract info for Search_Result
                Image currentImage; // current Image for the iteration
                ArrayList<Image> tImages; // result of get query inside for loop
                ArrayList<Integer> imageIds = new ArrayList<>(); // for Search_Result
                ArrayList<String> imagePaths = new ArrayList<>(); // for Search_Result
                ArrayList<Integer> rowNumbers = new ArrayList<>(); // for Search_Result
                ArrayList<Integer> fieldIds = new ArrayList<>(); // for Search_Result
                HashMap<Integer, Image> images = new HashMap<>(); // To limit # of database queries
                Image tImage = new Image(); // base Image object for running get queries
                tImage.setCurrentUser(Images.IMAGE_COMPLETED); // Only completed images are searchable
                for (Record record : records) {

                    // If we haven't already grabbed this Image from the database
                    if (!images.containsKey(record.imageId())) {
                        // Get this Image out of the database
                        tImage.setImageId(record.imageId());
                        tImages = (ArrayList) database.get(tImage);
                        
                        // Should only return one Image, because image IDs are unique
                        assert tImages.size() == 1;
                        int firstImageIndex = 0;
                        currentImage = tImages.get(firstImageIndex);
                        
                        // Add this image to the map
                        images.put(new Integer(record.imageId()), currentImage);
                    }
                    else { // If we have grabbed it already
                        // Take it from the HashMap
                        currentImage = images.get(record.imageId());
                    }
                    
                    // Grab info from the Image and Record for the Search_Result
                    imageIds.add(currentImage.imageId());
                    imagePaths.add(currentImage.path());
                    rowNumbers.add(record.rowNumber());
                    fieldIds.add(new Integer(record.fieldId()));
                }
                result = new Search_Result(imageIds, imagePaths, rowNumbers, fieldIds);
            }
        }
        catch (DatabaseException | GetFailedException | Search_Result.Search_ResultException ex) {
            result = null;
            Logger.getLogger(API.class.getName()).log(Level.WARNING, "search request failed.", ex);
        }
        Logger.getLogger(API.class.getName()).log(Level.FINE, "Entering API.getFields()");
        return result;
        
    }