Java tutorial
/* fEMR - fast Electronic Medical Records Copyright (C) 2014 Team fEMR fEMR is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. fEMR is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with fEMR. If not, see <http://www.gnu.org/licenses/>. If you have any questions, contact <info@teamfemr.org>. */ package femr.business.services; import com.avaje.ebean.ExpressionList; import com.typesafe.config.ConfigFactory; import java.awt.image.BufferedImage; import java.io.*; import java.nio.charset.Charset; import java.nio.file.*; import java.util.ArrayList; import java.util.List; import femr.business.helpers.DomainMapper; import femr.business.helpers.LogicDoer; import femr.business.helpers.QueryProvider; import femr.common.models.PatientEncounterItem; import femr.common.dto.ServiceResponse; import com.google.inject.Inject; import femr.common.models.PhotoItem; import femr.data.daos.IRepository; import femr.data.models.*; import femr.ui.models.medical.EditViewModelPost; import femr.util.stringhelpers.StringUtils; import org.apache.commons.codec.binary.Base64; import play.mvc.Http.MultipartFormData.FilePart; import javax.imageio.ImageIO; public class PhotoService implements IPhotoService { private String _profilePhotoPath; private String _encounterPhotoPath; private IRepository<IPhoto> patientPhotoRepository; private IRepository<IPatient> patientRepository; private IRepository<IPatientEncounterPhoto> patientEncounterPhotoRepository; private DomainMapper domainMapper; @Inject public PhotoService(IRepository<IPhoto> patientPhotoRepository, IRepository<IPatient> patientRepository, IRepository<IPatientEncounterPhoto> patientEncounterPhotoRepository, DomainMapper domainMapper) { this.patientPhotoRepository = patientPhotoRepository; this.patientRepository = patientRepository; this.patientEncounterPhotoRepository = patientEncounterPhotoRepository; this.domainMapper = domainMapper; this.Init(); } protected void Init() { File f; _profilePhotoPath = LogicDoer.getPatientPhotoPath(); _encounterPhotoPath = LogicDoer.getMedicalPhotoPath(); //Ensure folder exists, if not, create it f = new File(_profilePhotoPath); if (!f.exists()) f.mkdirs(); f = new File(_encounterPhotoPath); if (!f.exists()) f.mkdirs(); } /** * {@inheritDoc} */ @Override public ServiceResponse<Boolean> SavePatientPhotoAndUpdatePatient(String imageString, int patientId, Boolean deleteFlag) { ServiceResponse<Boolean> response = new ServiceResponse<>(); ExpressionList<Patient> query = QueryProvider.getPatientQuery().where().eq("id", patientId); try { IPatient patient = patientRepository.findOne(query); String imageFileName = "/Patient_" + patient.getId() + ".jpg"; if (StringUtils.isNotNullOrWhiteSpace(imageString)) { if (patient.getPhoto() == null) { //Create new photo Id record IPhoto pPhoto = domainMapper.createPhoto("", imageFileName); pPhoto = patientPhotoRepository.create(pPhoto); patient.setPhoto(pPhoto); patientRepository.update(patient); } else { //Record already exists: //photoId = patient.getPhoto().getId(); } //save image to disk String parsedImage = imageString.substring(imageString.indexOf(",") + 1); BufferedImage bufferedImage = decodeToImage(parsedImage); File photoFile = new File(_profilePhotoPath + imageFileName); ImageIO.write(bufferedImage, "jpg", photoFile); } else { if (deleteFlag != null) if (deleteFlag && patient.getPhoto() != null) { //delete photo //First make sure the photoId is null in the patient record Integer id = patient.getPhoto().getId(); patient.setPhoto(null); patientRepository.update(patient); //Now remove the photo record: this.deletePhotoById(id, _profilePhotoPath); } } response.setResponseObject(true); } catch (Exception ex) { response.setResponseObject(false); response.addError("HandlePatientPhoto", ex.getMessage()); } return response; } /** * {@inheritDoc} */ @Override public ServiceResponse<String> getPhotoPathForPatient(int patientId) { ServiceResponse<String> response = new ServiceResponse<>(); ExpressionList<Patient> query = QueryProvider.getPatientQuery().where().eq("id", patientId); try { IPatient patient = patientRepository.findOne(query); if (patient.getPhoto() == null) { response.setResponseObject(null); } else { response.setResponseObject(_profilePhotoPath + patient.getPhoto().getFilePath()); } } catch (Exception ex) { response.addError("", ex.getMessage()); return response; } return response; } /** * {@inheritDoc} */ @Override public ServiceResponse<String> getPhotoPath(int photoId) { ServiceResponse<String> response = new ServiceResponse<>(); ExpressionList<Photo> query = QueryProvider.getPhotoQuery().where().eq("id", photoId); try { IPhoto photo = patientPhotoRepository.findOne(query); response.setResponseObject(_encounterPhotoPath + photo.getFilePath()); } catch (Exception ex) { response.addError("", ex.getMessage()); } return response; } /** * {@inheritDoc} */ @Override public ServiceResponse<Boolean> HandleEncounterPhotos(List<FilePart> encounterImages, PatientEncounterItem patientEncounterItem, EditViewModelPost mod) { ServiceResponse<Boolean> sr = new ServiceResponse<>(); try { int count = mod.getPhotoId().size(); FilePart fp; for (Integer i = 0; i < count; i++) { Integer id = mod.getPhotoId().get(i); if (id == null) { //This is a new image, add it to the DB and filesystem: for (FilePart fp_iterator : encounterImages) { String keyName = fp_iterator.getKey(); int leftBracket = keyName.indexOf("["); int rightBracket = keyName.indexOf("]"); if (leftBracket >= 0 && rightBracket >= 0) { keyName = keyName.substring(leftBracket + 1, rightBracket); String tempindex = i.toString(); if (keyName.equalsIgnoreCase(tempindex)) { saveNewEncounterImage(fp_iterator, patientEncounterItem, mod.getImageDescText().get(i)); break; } } } } else { Boolean bDelete = mod.getDeleteRequested().get(i); if (bDelete == null) bDelete = false; if (bDelete) { //Delete image if (mod.getPhotoId().get(i) != null) this.deletePhotoById(mod.getPhotoId().get(i), _encounterPhotoPath); } else { //Possibly update the image Boolean bisUpdate = mod.getHasUpdatedDesc().get(i); if (bisUpdate != null) { if (bisUpdate) { Integer photoId = mod.getPhotoId().get(i); if (photoId != null) { //updateImageDescription(photoId, mod.getImageDescText().get(i)); ExpressionList<Photo> photoUpdateQuery = QueryProvider.getPhotoQuery().where() .eq("id", photoId); try { IPhoto savedPhoto = patientPhotoRepository.findOne(photoUpdateQuery); savedPhoto.setDescription(mod.getImageDescText().get(i)); patientPhotoRepository.update(savedPhoto); } catch (Exception ex) { sr.addError("", "error updating description: " + ex.getMessage()); } } } } } } } sr.setResponseObject(true); } catch (Exception ex) { sr.setResponseObject(false); sr.addError("HandleEncounterPhotos()", ex.getMessage()); } return sr; } /** * {@inheritDoc} */ @Override public ServiceResponse<List<PhotoItem>> GetEncounterPhotos(int encounterId) { ServiceResponse<List<PhotoItem>> response = new ServiceResponse<>(); try { ExpressionList<PatientEncounterPhoto> query = QueryProvider.getPatientEncounterPhotoQuery().where() .eq("patient_encounter_id", encounterId); List<? extends IPatientEncounterPhoto> photoList = patientEncounterPhotoRepository.find(query); if (photoList != null) { List<PhotoItem> returnList = new ArrayList<>(); for (IPatientEncounterPhoto pep : photoList) { ExpressionList<Photo> photoQuery = QueryProvider.getPhotoQuery().where().eq("id", pep.getPhotoId()); try { IPhoto savedPhoto = patientPhotoRepository.findOne(photoQuery); returnList.add( domainMapper.createPhotoItem(savedPhoto, femr.ui.controllers.routes.PhotoController .GetPhoto(savedPhoto.getId()).toString())); } catch (Exception ex) { response.addError("", ex.getMessage()); return response; } } response.setResponseObject(returnList); } } catch (Exception ex) { response.addError("photo", ex.getMessage()); } return response; } private void saveNewEncounterImage(FilePart image, PatientEncounterItem patientEncounter, String descriptionText) { try { String imageFileName; //Create photo record: IPhoto pPhoto = new Photo(); pPhoto.setDescription(descriptionText); pPhoto.setFilePath(""); pPhoto = patientPhotoRepository.create(pPhoto); ExpressionList<Photo> findPhotoQuery = QueryProvider.getPhotoQuery().where().eq("id", pPhoto.getId()); IPhoto editPhoto = patientPhotoRepository.findOne(findPhotoQuery); imageFileName = "Patient_" + patientEncounter.getPatientId() + "_Enc_" + patientEncounter.getId() + "_Photo_" + editPhoto.getId(); editPhoto.setFilePath(imageFileName); //Since the record ID is part of the file name // I am setting the filePath field after the record is created patientPhotoRepository.update(editPhoto); //Link photo record in photoEncounter table IPatientEncounterPhoto pep = new PatientEncounterPhoto(); pep.setPhotoId(editPhoto.getId()); pep.setPatientEncounterId(patientEncounter.getId()); patientEncounterPhotoRepository.create(pep); //Save image to disk Path src = FileSystems.getDefault().getPath(image.getFile().getAbsolutePath()); Path dest = FileSystems.getDefault().getPath(this._encounterPhotoPath + imageFileName); java.nio.file.Files.move(src, dest, StandardCopyOption.ATOMIC_MOVE); } catch (Exception ex) { String test = "uh oh"; } } private ServiceResponse<IPhoto> deletePhotoById(int id, String imagePath) { ExpressionList<Photo> query = QueryProvider.getPhotoQuery().where().eq("id", id); IPhoto savedPhoto = patientPhotoRepository.findOne(query); if (savedPhoto != null) { //Delete any references from the patientencounterphotos table ExpressionList<PatientEncounterPhoto> peQuery = QueryProvider.getPatientEncounterPhotoQuery().where() .eq("photo_id", id); List<? extends IPatientEncounterPhoto> pep = patientEncounterPhotoRepository.find(peQuery); if (pep != null) patientEncounterPhotoRepository.delete(pep); File photo = new File(imagePath + savedPhoto.getFilePath()); photo.delete(); patientPhotoRepository.delete(savedPhoto); } ServiceResponse<IPhoto> response = new ServiceResponse<>(); if (savedPhoto != null) { response.setResponseObject(savedPhoto); } else { response.addError("photo", "photo could not be deleted from the database"); } return response; } /** * Decodes a base64 encoded string to an image * * @param imageString base64 encoded string that has been parsed to only include imageBytes * @return the decoded image */ private static BufferedImage decodeToImage(String imageString) { BufferedImage image = null; byte[] imageByte; try { Base64 newDecoder = new Base64(); byte[] bytes = imageString.getBytes(Charset.forName("UTF-8")); imageByte = newDecoder.decode(bytes); ByteArrayInputStream bis = new ByteArrayInputStream(imageByte); image = ImageIO.read(bis); bis.close(); } catch (Exception e) { e.printStackTrace(); } return image; } }