DefaultSampleService implements SampleService, PaginatedDataSource<Sample> { @Override public long update(Sample sample) throws IOException { Sample managed = get(sample.getId()); User changeUser = authorizationManager.getCurrentUser(); managed.setChangeDetails(changeUser); boolean validateAliasUniqueness = !managed.getAlias().equals(sample.getAlias()); maybeRemoveFromBox(sample, managed); boxService.throwIfBoxPositionIsFilled(sample); if (sample.getParent() != null) { ((DetailedSample) sample).setParent((DetailedSample) get(sample.getParent().getId())); } LimsUtils.updateParentVolume(sample, managed, changeUser); updateParentSlides(sample, managed, changeUser); loadChildEntities(sample); validateChange(sample, managed); applyChanges(managed, sample); if (isDetailedSample(managed)) { DetailedSample detailedUpdated = (DetailedSample) managed; if (detailedUpdated.getParent() != null) { detailedUpdated.setParent((DetailedSample) get(detailedUpdated.getParent().getId())); validateHierarchy(detailedUpdated); } } save(managed, validateAliasUniqueness); if (sample.getParent() != null) { sampleStore.update(sample.getParent()); } boxService.updateBoxableLocation(sample); return sample.getId(); }  void setSampleStore(SampleStore sampleStore); void setAuthorizationManager(AuthorizationManager authorizationManager); void setSampleClassService(SampleClassService sampleClassService); void setSampleValidRelationshipService(SampleValidRelationshipService sampleValidRelationshipService); void setProjectStore(ProjectStore projectStore); void setTissueOriginDao(TissueOriginDao tissueOriginDao); void setTissueTypeDao(TissueTypeDao tissueTypeDao); void setDetailedQcStatusService(DetailedQcStatusService detailedQcStatusService); void setSubprojectService(SubprojectService subprojectService); void setSamplePurposeDao(SamplePurposeDao samplePurposeDao); void setTissueMaterialDao(TissueMaterialDao tissueMaterialDao); void setLabService(LabService labService); void setBoxService(BoxService boxService); void setWorksetService(WorksetService worksetService); void setFileAttachmentService(FileAttachmentService fileAttachmentService); void setNamingSchemeHolder(NamingSchemeHolder namingSchemeHolder); @CoverageIgnore Boolean getAutoGenerateIdBarcodes(); @CoverageIgnore void setAutoGenerateIdBarcodes(Boolean autoGenerateIdBarcodes); @CoverageIgnore Boolean isUniqueExternalNameWithinProjectRequired(); @CoverageIgnore void setUniqueExternalNameWithinProjectRequired(Boolean uniqueExternalNameWithinProjectRequired); @Override Sample get(long sampleId); @Override long create(Sample sample); @Override void confirmExternalNameUniqueForProjectIfRequired(String newExternalName, Sample sample); boolean isValidRelationship(Sample parent, Sample child); @Override long update(Sample sample); @Override List<Sample> list(); @Override Long countAll(); @Override Collection<Sample> listByProjectId(long projectId); @Override List<Sample> listByIdList(List<Long> idList); @Override @Transactional(propagation = Propagation.REQUIRED) Collection<SampleIdentity> getIdentitiesByExternalNameOrAliasAndProject(String externalName, Long projectId, boolean exactMatch); @Override List<Sample> getByAlias(String alias); @Override Sample getByBarcode(String barcode); @Override void addNote(Sample sample, Note note); @Override void deleteNote(Sample sample, Long noteId); @Override AuthorizationManager getAuthorizationManager(); @Override DeletionStore getDeletionStore(); void setDeletionStore(DeletionStore deletionStore); @Override void authorizeDeletion(Sample object); @Override ValidationResult validateDeletion(Sample object); @Override void beforeDelete(Sample object); @Override void afterDelete(Sample object); @Override Sample save(Sample sample); @Override long count(Consumer<String> errorHandler, PaginationFilter... filter); @Override List<Sample> list(Consumer<String> errorHandler, int offset, int limit, boolean sortDir, String sortCol,
      PaginationFilter... filter); @Override EntityReference getNextInProject(Sample sample); @Override EntityReference getPreviousInProject(Sample sample); @Override TransactionTemplate getTransactionTemplate();  }
@Test public void testUpdatePlainSample() throws Exception { Sample old = makePlainSample(); Mockito.when(sampleStore.getSample(old.getId())).thenReturn(old); Sample updated = makePlainSample(); updated.setAlias("newAlias"); updated.setDescription("newDesc"); updated.setSampleType("newType"); updated.setDetailedQcStatus(mockDetailedQcStatus(5L, "Ready")); updated.setScientificName(mockScientificName(2L, "newSciName")); updated.setTaxonIdentifier("newTaxonId"); updated.setVolume(new BigDecimal("5.5")); updated.setVolumeUnits(VolumeUnit.MICROLITRES); updated.setName("newName"); mockShellProjectWithRealLookup(updated); sut.update(updated); ArgumentCaptor<Sample> updatedCapture = ArgumentCaptor.forClass(Sample.class); Mockito.verify(sampleStore).update(updatedCapture.capture()); Sample result = updatedCapture.getValue(); assertEquals("Sample sampleType should be modifiable", updated.getSampleType(), result.getSampleType()); assertEquals("Sample description should be modifiable", updated.getDescription(), result.getDescription()); assertEquals("Sample sampleType should be modifiable", updated.getSampleType(), result.getSampleType()); assertEquals("Sample detailedQcStatus should be modifiable", updated.getDetailedQcStatus(), result.getDetailedQcStatus()); assertEquals("Sample scientificName should be modifiable", updated.getScientificName(), result.getScientificName()); assertEquals("Sample taxonIdentifier should be modifiable", updated.getTaxonIdentifier(), result.getTaxonIdentifier()); assertEquals("Sample volume should be modifiable", updated.getVolume(), result.getVolume()); assertEquals("Sample project should be modifiable", updated.getProject().getId(), result.getProject().getId()); assertEquals("Sample name should NOT be modifiable", old.getName(), result.getName()); }