package se.cambio.cm.model.generic.dao;
import se.cambio.cm.model.util.CMElement;
import se.cambio.cm.model.util.CMTypeManager;
import se.cambio.openehr.util.ExceptionHandler;
import se.cambio.openehr.util.IOUtils;
import se.cambio.openehr.util.UnicodeBOMInputStream;
import se.cambio.openehr.util.exceptions.FolderNotFoundException;
import se.cambio.openehr.util.exceptions.InstanceNotFoundException;
import se.cambio.openehr.util.exceptions.InternalErrorException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
public class FileGenericCMElementDAO <E extends CMElement> implements GenericCMElementDAO<E>{
private Class<E> cmElementClass;
private File folder;
private Collection<String> fileExtensions;
public FileGenericCMElementDAO(Class<E> cmElementClass, File folder) {
this.cmElementClass = cmElementClass;
this.folder = folder;
}
@Override
public Collection<E> searchByIds(Collection<String> ids) throws InternalErrorException, InstanceNotFoundException {
Collection<E> cmElements = searchAll();
Collection<E> foundCMElements = new ArrayList<E>();
for (E cmElement : cmElements) {
if (ids.contains(cmElement.getId())) {
foundCMElements.add(cmElement);
}
}
checkMissingInstance(ids, foundCMElements);
return foundCMElements;
}
@Override
public Collection<String> searchAllIds() throws InternalErrorException {
if (!folder.isDirectory()) {
throw new FolderNotFoundException(folder.getAbsolutePath());
}
Collection<String> ids = new ArrayList<String>();
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
if (listOfFiles[i].isFile()) {
String fileName = listOfFiles[i].getName();
String fileExtension = matchingFileExtension(fileName);
if (fileExtension!=null) {
String id = getId(fileName, fileExtension);
ids.add(id);
}
}
}
return ids;
}
@Override
public Collection<E> searchAll() throws InternalErrorException {
Collection<E> cmElements = new ArrayList<E>();
if (!folder.isDirectory()) {
throw new FolderNotFoundException(folder.getAbsolutePath());
}
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
File file = listOfFiles[i];
if (file.isFile()) {
String fileName = file.getName();
String fileExtension = matchingFileExtension(fileName);
if (fileExtension!=null) {
try {
FileInputStream fis = new FileInputStream(file.getAbsolutePath());
try {
E cmElement = getCMElement(fileName, fileExtension, fis, new Date(file.lastModified()));
cmElements.add(cmElement);
}finally{
fis.close();
}
} catch (Exception e) {
ExceptionHandler.handle(e);
}
}
}
}
return cmElements;
}
public E getCMElement(String fileName, String fileExtension, InputStream fis, Date date) throws IOException, InternalErrorException {
UnicodeBOMInputStream ubis = new UnicodeBOMInputStream(fis);
ubis.skipBOM();
String id = getId(fileName, fileExtension);
String src = IOUtils.toString(ubis, "UTF-8");
return (E)new CMElementBuilder<E>()
.setId(id)
.setFormat(fileExtension)
.setSource(src)
.setLastUpdate(date)
.createCMElement(cmElementClass);
}
private String getId(String fileName, String fileExtension) {
return fileName.substring(0, fileName.length() - fileExtension.length() - 1);
}
private String matchingFileExtension(String fileName) throws InternalErrorException {
for(String fileExtension: getFileExtensions()){
if (fileName.endsWith("."+fileExtension)){
return fileExtension;
}
}
return null;
}
@Override
public void insert(E cmElement) throws InternalErrorException {
upsert(cmElement);
}
@Override
public void update(E cmElement) throws InternalErrorException {
upsert(cmElement);
}
private void upsert(E cmElement) throws InternalErrorException {
if (!folder.isDirectory()) {
throw new FolderNotFoundException(folder.getAbsolutePath());
}
File file = new File(folder, cmElement.getId() + "." + cmElement.getFormat());
try {
Files.write(Paths.get(file.toURI()), cmElement.getSource().getBytes());
} catch (IOException e) {
throw new InternalErrorException(e);
}
}
@Override
public void remove(String id) throws InternalErrorException {
if (!folder.isDirectory()) {
throw new FolderNotFoundException(folder.getAbsolutePath());
}
File file = new File(folder, id + "." + getFileExtensions().iterator().next());
file.delete();
}
@Override
public void removeAll() throws InternalErrorException {
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
File file = listOfFiles[i];
String matchingExtension = matchingFileExtension(file.getName());
if (matchingExtension != null){
String id = getId(file.getName(), matchingExtension);
remove(id);
}
}
}
@Override
public Date getLastUpdateDate() throws InternalErrorException {
if (!folder.isDirectory()) {
throw new FolderNotFoundException(folder.getAbsolutePath());
}
Date lastModifiedDate = null;
File[] listOfFiles = folder.listFiles();
for (int i = 0; i < listOfFiles.length; i++) {
File file = listOfFiles[i];
Date date = new Date(file.lastModified());
if (lastModifiedDate == null || date.after(lastModifiedDate)){
lastModifiedDate = date;
}
}
return lastModifiedDate;
}
private void checkMissingInstance(Collection<String> ids, Collection<E> cmElements) throws InstanceNotFoundException {
Collection<String> foundIds = new ArrayList<String>();
for (CMElement cmElement: cmElements){
foundIds.add(cmElement.getId());
}
for(String id: ids){
if (!foundIds.contains(id)){
throw new InstanceNotFoundException(id, getCMElementClassName());
}
}
}
private String getCMElementClassName() {
return getCMElementClass().getSimpleName();
}
private Class<E> getCMElementClass() {
return cmElementClass;
}
public Collection<String> getFileExtensions() throws InternalErrorException {
if (fileExtensions == null) {
fileExtensions = CMTypeManager.getInstance().getCMTypeByClass(getCMElementClass()).getFileExtensions();
}
return fileExtensions;
}
}
/*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 2.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 2.0 (the 'License'); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an 'AS IS' basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
*
* The Initial Developers of the Original Code are Iago Corbal and Rong Chen.
* Portions created by the Initial Developer are Copyright (C) 2012-2013
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Software distributed under the License is distributed on an 'AS IS' basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* ***** END LICENSE BLOCK *****
*/