public void testSaveRecord(String intWithRangeValue) throws Exception { login("admin", "password", new String[] {Role.ADMIN}); request.setMethod("POST"); request.setRequestURI("/bdrs/user/singleSiteMultiTaxa.htm"); DateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy"); dateFormat.setLenient(false); GregorianCalendar cal = new GregorianCalendar(); cal.set(2010, 10, 12, 15, 30); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); Date sightingDate = cal.getTime(); Map<String, String> params = new HashMap<String, String>(); params.put("surveyId", survey.getId().toString()); params.put("latitude", "-36.879620605027"); params.put("longitude", "126.650390625"); params.put("date", dateFormat.format(sightingDate)); params.put("time_hour", new Integer(cal.get(Calendar.HOUR_OF_DAY)).toString()); params.put("time_minute", new Integer(cal.get(Calendar.MINUTE)).toString()); params.put("notes", "This is a test record"); params.put("sightingIndex", "2"); Map<Attribute, Object> surveyScopeAttributeValueMapping = new HashMap<Attribute, Object>(); Map<IndicatorSpecies, Map<Attribute, Object>> recordScopeAttributeValueMapping = new HashMap<IndicatorSpecies, Map<Attribute, Object>>(2); Map<Attribute, Object> attributeValueMapping; // We have 2 species set up so lets save them both int sightingIndex = 0; String surveyPrefix = ""; for (IndicatorSpecies taxon : new IndicatorSpecies[] {speciesA, speciesB}) { params.put( String.format("%d_survey_species_search", sightingIndex), taxon.getScientificName()); params.put(String.format("%d_species", sightingIndex), taxon.getId().toString()); params.put( String.format("%d_number", sightingIndex), new Integer(sightingIndex + 21).toString()); String recordPrefix = String.format("%d_", sightingIndex); String prefix; String key; String value; // The value in the post dict attributeValueMapping = new HashMap<Attribute, Object>(); Map<Attribute, Object> valueMap; recordScopeAttributeValueMapping.put(taxon, attributeValueMapping); for (Attribute attr : survey.getAttributes()) { if (AttributeScope.SURVEY.equals(attr.getScope())) { prefix = surveyPrefix; valueMap = surveyScopeAttributeValueMapping; } else { prefix = recordPrefix; valueMap = attributeValueMapping; } key = String.format(AttributeParser.ATTRIBUTE_NAME_TEMPLATE, prefix, attr.getId()); value = ""; switch (attr.getType()) { case INTEGER: Integer val = new Integer(sightingIndex + 30); value = val.toString(); valueMap.put(attr, val); break; case INTEGER_WITH_RANGE: valueMap.put(attr, intWithRangeValue); break; case DECIMAL: value = String.format("50.%d", sightingIndex); valueMap.put(attr, Double.parseDouble(value)); break; case DATE: Date date = new Date(System.currentTimeMillis()); value = dateFormat.format(date); // Reparsing the date strips out the hours, minutes and seconds valueMap.put(attr, dateFormat.parse(value)); break; case STRING_AUTOCOMPLETE: case STRING: value = String.format("String %d", sightingIndex); valueMap.put(attr, value); break; case TEXT: value = String.format("Text %d", sightingIndex); valueMap.put(attr, value); break; case STRING_WITH_VALID_VALUES: value = attr.getOptions().get(sightingIndex).getValue(); valueMap.put(attr, value); break; case FILE: String file_filename = String.format("attribute_%d", attr.getId()); MockMultipartFile mockFileFile = new MockMultipartFile(key, file_filename, "audio/mpeg", file_filename.getBytes()); ((MockMultipartHttpServletRequest) request).addFile(mockFileFile); valueMap.put(attr, mockFileFile); break; case IMAGE: String image_filename = String.format("attribute_%d", attr.getId()); MockMultipartFile mockImageFile = new MockMultipartFile(key, image_filename, "image/png", image_filename.getBytes()); ((MockMultipartHttpServletRequest) request).addFile(mockImageFile); valueMap.put(attr, mockImageFile); break; default: Assert.assertTrue("Unknown Attribute Type: " + attr.getType().toString(), false); break; } params.put(key, value); } sightingIndex += 1; } request.setParameters(params); ModelAndView mv = handle(request, response); Assert.assertEquals(2, recordDAO.countAllRecords().intValue()); Assert.assertTrue(mv.getView() instanceof RedirectView); RedirectView redirect = (RedirectView) mv.getView(); Assert.assertEquals(redirectionService.getMySightingsUrl(survey), redirect.getUrl()); sightingIndex = 0; for (IndicatorSpecies taxon : new IndicatorSpecies[] {speciesA, speciesB}) { List<Record> records = recordDAO.getRecords(taxon); Assert.assertEquals(1, records.size()); Record record = records.get(0); Assert.assertEquals(survey.getId(), record.getSurvey().getId()); // Coordinates are truncates to 6 decimal points Assert.assertEquals( new Double(params.get("latitude")).doubleValue(), record.getPoint().getY(), Math.pow(10, -6)); Assert.assertEquals( new Double(params.get("longitude")).doubleValue(), record.getPoint().getX(), Math.pow(10, -6)); Assert.assertEquals(sightingDate, record.getWhen()); Assert.assertEquals(sightingDate.getTime(), record.getTime().longValue()); Assert.assertEquals(params.get("notes"), record.getNotes()); Assert.assertEquals(taxon, record.getSpecies()); Assert.assertEquals(sightingIndex + 21, record.getNumber().intValue()); Map<Attribute, Object> attributeValueMap = recordScopeAttributeValueMapping.get(taxon); Object expected; for (TypedAttributeValue recAttr : record.getAttributes()) { if (AttributeScope.SURVEY.equals(recAttr.getAttribute().getScope())) { expected = surveyScopeAttributeValueMapping.get(recAttr.getAttribute()); } else { expected = attributeValueMap.get(recAttr.getAttribute()); } switch (recAttr.getAttribute().getType()) { case INTEGER: case INTEGER_WITH_RANGE: Assert.assertEquals(expected, recAttr.getNumericValue().intValue()); break; case DECIMAL: Assert.assertEquals(expected, recAttr.getNumericValue().doubleValue()); break; case DATE: Assert.assertEquals(expected, recAttr.getDateValue()); break; case STRING_AUTOCOMPLETE: case STRING: case TEXT: Assert.assertEquals(expected, recAttr.getStringValue()); break; case STRING_WITH_VALID_VALUES: Assert.assertEquals(expected, recAttr.getStringValue()); break; case FILE: case IMAGE: String filename = ((MockMultipartFile) expected).getOriginalFilename(); Assert.assertEquals(filename, recAttr.getStringValue()); break; default: Assert.assertTrue( "Unknown Attribute Type: " + recAttr.getAttribute().getType().toString(), false); break; } } sightingIndex += 1; } // Test Save and Add Another request.setParameter("submitAndAddAnother", "submitAndAddAnother"); mv = handle(request, response); Assert.assertEquals(4, recordDAO.countAllRecords().intValue()); Assert.assertTrue(mv.getView() instanceof RedirectView); redirect = (RedirectView) mv.getView(); Assert.assertEquals("/bdrs/user/surveyRenderRedirect.htm", redirect.getUrl()); }
@RolesAllowed({Role.USER, Role.POWERUSER, Role.SUPERVISOR, Role.ADMIN}) @RequestMapping(value = "/bdrs/user/atlas.htm", method = RequestMethod.GET) public ModelAndView addRecord( HttpServletRequest request, HttpServletResponse response, @RequestParam(value = "surveyId", required = true) int surveyId, @RequestParam(value = "taxonSearch", required = false) String taxonSearch, @RequestParam(value = "recordId", required = false, defaultValue = "0") int recordId, @RequestParam(value = "guid", required = false) String guid) { Survey survey = surveyDAO.getSurvey(surveyId); Record record = recordDAO.getRecord(recordId); record = record == null ? new Record() : record; IndicatorSpecies species = null; if (guid != null && !guid.isEmpty()) { species = taxaDAO.getIndicatorSpeciesByGuid(guid); } if (species == null && taxonSearch != null && !taxonSearch.isEmpty()) { List<IndicatorSpecies> speciesList = surveyDAO.getSpeciesForSurveySearch(surveyId, taxonSearch); if (speciesList.isEmpty()) { species = null; } else if (speciesList.size() == 1) { species = speciesList.get(0); } else { log.warn( "Multiple species found for survey " + surveyId + " and taxon search \"" + taxonSearch + "\". Using the first."); species = speciesList.get(0); } } if (species == null && record.getSpecies() != null) { species = record.getSpecies(); } ModelAndView mv; if (species == null) { InputStreamReader reader = null; try { Preference p = preferenceDAO.getPreferenceByKey("ala.species.short.url"); URL url; if (p != null) { url = new URL(p.getValue() + "/" + guid + ".json"); } else { url = new URL( "http://bie.ala.org.au/species/shortProfile/" + guid + ".json"); // fallback to the BIE } URLConnection conn = url.openConnection(); reader = new InputStreamReader(conn.getInputStream()); StringBuffer buff = new StringBuffer(); int c; while ((c = reader.read()) != -1) { buff.append((char) c); } JSONObject ob = JSONObject.fromObject(buff.toString()); IndicatorSpecies taxon = new IndicatorSpecies(); log.debug("Found species information from the atlas : "); log.debug(buff.toString()); // Scientific Name taxon.setScientificName(ob.getString("scientificName")); taxon.setAuthor(ob.getString("author")); taxon.setScientificNameAndAuthor( ob.getString("scientificName") + " " + ob.getString("scientificNameAuthorship")); taxon.setYear(ob.getString("year")); Metadata md = new Metadata(); md.setKey(Metadata.SCIENTIFIC_NAME_SOURCE_DATA_ID); md.setValue(guid); metadataDAO.save(md); taxon.getMetadata().add(md); // Rank TaxonRank rank = TaxonRank.findByIdentifier(ob.getString("rank")); taxon.setTaxonRank(rank); // Common Name taxon.setCommonName(ob.getString("commonName")); md = new Metadata(); md.setKey(Metadata.COMMON_NAME_SOURCE_DATA_ID); md.setValue(ob.getString("commonNameGUID")); metadataDAO.save(md); taxon.getMetadata().add(md); // Group String family = ob.getString("family"); if (family != null) { TaxonGroup g = taxaDAO.getTaxonGroup(family); if (g == null) { g = taxaDAO.createTaxonGroup(family, false, false, false, false, false, true); } taxon.setTaxonGroup(g); } else { TaxonGroup g = taxaDAO.createTaxonGroup("Other", false, false, false, false, false, true); taxon.setTaxonGroup(g); } // Images. // Thumbnail if (ob.containsKey("thumbnail")) { SpeciesProfile sp = new SpeciesProfile(); sp.setType( SpeciesProfile .SPECIES_PROFILE_THUMBNAIL); // this is a 100x100 image, might resize for the // other ones. sp.setHeader("Thumbnail"); sp.setDescription("Thumbnail for " + taxon.getScientificName()); String filename = ob.getString("thumbnail"); String ext = getExtension(filename); ManagedFile mf = new ManagedFile(); mf.setContentType(""); mf.setCredit(""); mf.setLicense(""); mf.setDescription(taxon.getScientificName() + " - " + taxon.getCommonName()); mf.setFilename(mf.getUuid() + ext); mf = managedFileDAO.save(mf); fileService.createFile( mf.getClass(), mf.getId(), mf.getFilename(), downloadFile(new URL(filename))); mf.setContentType(fileService.getFile(mf, mf.getFilename()).getContentType()); managedFileDAO.save(mf); sp.setContent(mf.getUuid()); speciesProfileDAO.save(sp); taxon.getInfoItems().add(sp); // Now thumbnail the thumbnail... BufferedImage fortyXforty = imageService.resizeImage( fileService.getFile(mf, mf.getFilename()).getInputStream(), 40, 40); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(fortyXforty, "png", baos); baos.flush(); byte[] data = baos.toByteArray(); baos.close(); sp = new SpeciesProfile(); sp.setType( SpeciesProfile .SPECIES_PROFILE_IMAGE_40x40); // this is a 100x100 image, might resize for the // other ones. sp.setHeader("40x40 Thumbnail"); sp.setDescription("40x40 Thumbnail for " + taxon.getScientificName()); mf = new ManagedFile(); mf.setContentType(""); mf.setCredit(""); mf.setLicense(""); mf.setDescription(taxon.getScientificName() + " - " + taxon.getCommonName()); mf.setFilename(mf.getUuid() + ".png"); mf = managedFileDAO.save(mf); fileService.createFile(mf.getClass(), mf.getId(), mf.getFilename(), data); mf.setContentType(fileService.getFile(mf, mf.getFilename()).getContentType()); managedFileDAO.save(mf); sp.setContent(mf.getUuid()); speciesProfileDAO.save(sp); taxon.getInfoItems().add(sp); } // Main Image if (ob.containsKey("imageURL")) { SpeciesProfile sp = new SpeciesProfile(); sp.setType(SpeciesProfile.SPECIES_PROFILE_IMAGE); sp.setHeader("Image"); sp.setDescription("Image for " + taxon.getScientificName()); String filename = ob.getString("imageURL"); String ext = getExtension(filename); ManagedFile mf = new ManagedFile(); mf.setContentType(""); mf.setCredit(""); mf.setLicense(""); mf.setDescription(taxon.getScientificName() + " - " + taxon.getCommonName()); mf.setFilename(mf.getUuid() + ext); mf = managedFileDAO.save(mf); fileService.createFile( mf.getClass(), mf.getId(), mf.getFilename(), downloadFile(new URL(filename))); mf.setContentType(fileService.getFile(mf, mf.getFilename()).getContentType()); managedFileDAO.save(mf); sp.setContent(mf.getUuid()); speciesProfileDAO.save(sp); taxon.getInfoItems().add(sp); } // Save the Taxon species = taxaDAO.save(taxon); } catch (IOException ioe) { log.error("Could not retrieve species profile from the Atlas", ioe); species = null; } finally { if (reader != null) { try { reader.close(); } catch (IOException ioe) { log.error("Error closing stream from Atlas webservice, possible network error", ioe); } } } } if (species == null) { log.debug("Could not determine species, reverting to tracker form"); // The atlas form relies upon a preconfigured species. // If we do not have one, fall back to the tracker form. mv = new ModelAndView(new RedirectView("tracker.htm")); mv.addAllObjects(request.getParameterMap()); mv.addObject("surveyId", surveyId); return mv; } else { // Add all attribute form fields Map<String, FormField> formFieldMap = new HashMap<String, FormField>(); // Add all property form fields for (String propertyName : RECORD_PROPERTY_NAMES) { formFieldMap.put( propertyName, formFieldFactory.createRecordFormField( survey, record, propertyName, species, Taxonomic.TAXONOMIC)); } // Determine the file attribute to use for the form (if there is one) // Sort the list of survey attributes by weight so that we can // correctly select the first file attribute. List<Attribute> attributeList = survey.getAttributes(); Collections.sort(attributeList, new ComparePersistentImplByWeight()); // Retrieve the first file attribute and if present, the associated // record attribute. Attribute fileAttr = null; AttributeValue fileRecAttr = null; for (Attribute attr : attributeList) { if (fileAttr == null && AttributeType.FILE.equals(attr.getType())) { // Attribute found. fileAttr = attr; // Try to locate matching record attribute for (AttributeValue recAttr : record.getAttributes()) { if (fileRecAttr == null && fileAttr.equals(recAttr.getAttribute())) { fileRecAttr = recAttr; } } } } // Map all the existing file attributes to record attributes. Map<Attribute, AttributeValue> fileAttrToRecAttrMap = new HashMap<Attribute, AttributeValue>(); FormField fileFormField = formFieldFactory.createRecordFormField(survey, record, fileAttr, fileRecAttr); Map<String, String> errorMap = (Map<String, String>) getRequestContext().getSessionAttribute("errorMap"); getRequestContext().removeSessionAttribute("errorMap"); Map<String, String> valueMap = (Map<String, String>) getRequestContext().getSessionAttribute("valueMap"); getRequestContext().removeSessionAttribute("valueMap"); Metadata predefinedLocationsMD = survey.getMetadataByKey(Metadata.PREDEFINED_LOCATIONS_ONLY); boolean predefinedLocationsOnly = predefinedLocationsMD != null && Boolean.parseBoolean(predefinedLocationsMD.getValue()); Set<Location> locations = new TreeSet<Location>(new LocationNameComparator()); locations.addAll(survey.getLocations()); if (!predefinedLocationsOnly) { locations.addAll(locationDAO.getUserLocations(getRequestContext().getUser())); } Metadata defaultLocId = getRequestContext().getUser().getMetadataObj(Metadata.DEFAULT_LOCATION_ID); Location defaultLocation; if (defaultLocId == null) { defaultLocation = null; } else { int defaultLocPk = Integer.parseInt(defaultLocId.getValue()); defaultLocation = locationDAO.getLocation(defaultLocPk); } mv = new ModelAndView("atlas"); mv.addObject("record", record); mv.addObject("taxon", species); mv.addObject("survey", survey); mv.addObject("locations", locations); mv.addObject("formFieldMap", formFieldMap); mv.addObject("fileFormField", fileFormField); mv.addObject("preview", request.getParameter("preview") != null); mv.addObject("defaultLocation", defaultLocation); mv.addObject("errorMap", errorMap); mv.addObject("valueMap", valueMap); } return mv; }