package ch.elexis.omnivore.data.service.internal; import static ch.elexis.omnivore.Constants.CATEGORY_MIMETYPE; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Optional; import org.apache.commons.io.IOUtils; import org.osgi.service.component.annotations.Component; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ch.elexis.core.exceptions.ElexisException; import ch.elexis.core.exceptions.PersistenceException; import ch.elexis.core.model.ICategory; import ch.elexis.core.model.IDocument; import ch.elexis.core.model.IPersistentObject; import ch.elexis.core.model.ITag; import ch.elexis.core.services.IDocumentStore; import ch.elexis.data.Patient; import ch.elexis.data.PersistentObject; import ch.elexis.data.Query; import ch.elexis.data.dto.CategoryDocumentDTO; import ch.elexis.omnivore.Constants; import ch.elexis.omnivore.data.DocHandle; import ch.elexis.omnivore.data.dto.DocHandleDocumentDTO; import ch.rgw.tools.JdbcLink.Stm; @Component public class OmnivoreDocumentStore implements IDocumentStore { private static final String STORE_ID = "ch.elexis.data.store.omnivore"; private static Logger log = LoggerFactory.getLogger(OmnivoreDocumentStore.class); @Override public String getId(){ return STORE_ID; } @Override public String getName(){ return "Omnivore"; } @Override public List<IDocument> getDocuments(String patientId, String authorId, ICategory category, List<ITag> tag){ Query<DocHandle> query = new Query<>(DocHandle.class); query.add(DocHandle.FLD_PATID, Query.EQUALS, patientId); if (category != null) { query.add(DocHandle.FLD_CAT, Query.EQUALS, category.getName(), true); } if (tag != null) { query.startGroup(); for (ITag t : tag) { query.add(DocHandle.FLD_KEYWORDS, Query.EQUALS, t.getName()); query.or(); } query.endGroup(); } List<DocHandle> docs = query.execute(); List<IDocument> results = new ArrayList<>(); for (DocHandle doc : docs) { results.add(new DocHandleDocumentDTO(doc, STORE_ID)); } return results; } @Override public List<ICategory> getCategories(){ Stm stm = PersistentObject.getDefaultConnection().getStatement(); ResultSet rs = stm .query("select distinct category from " + DocHandle.TABLENAME + " order by category"); List<ICategory> categories = new ArrayList<>(); try { while (rs.next()) { String typ = rs.getString("Category"); if (typ != null) { categories.add(new CategoryDocumentDTO(typ)); } } } catch (SQLException e) { log.error("Error executing distinct docHandle category selection", e); } PersistentObject.getDefaultConnection().releaseStatement(stm); return categories; } @Override public Optional<IDocument> loadDocument(String id){ DocHandle doc = DocHandle.load(id); if (doc.exists()) { return Optional.of(new DocHandleDocumentDTO(doc, STORE_ID)); } return Optional.empty(); } @Override public void removeDocument(IDocument document){ DocHandle doc = DocHandle.load(document.getId()); if (doc.exists()) { doc.delete(); } } @Override public IDocument saveDocument(IDocument document) throws ElexisException{ return save(document, null); } @Override public IDocument saveDocument(IDocument document, InputStream content) throws ElexisException{ return save(document, content); } private IDocument save(IDocument document, InputStream content) throws ElexisException{ try { DocHandle doc = DocHandle.load(document.getId()); String category = document.getCategory() != null ? document.getCategory().getName() : null; if (doc.exists()) { // update an existing document String[] fetch = new String[] { DocHandle.FLD_PATID, DocHandle.FLD_TITLE, DocHandle.FLD_MIMETYPE, DocHandle.FLD_CAT, DocHandle.FLD_KEYWORDS }; String[] data = new String[] { document.getPatientId(), document.getTitle(), document.getMimeType(), category, document.getKeywords() }; doc.set(fetch, data); } else { // persist a new document doc = new DocHandle(category, new byte[1], Patient.load(document.getPatientId()), document.getCreated(), document.getTitle(), document.getMimeType(), document.getKeywords()); } if (content != null) { doc.storeContent(IOUtils.toByteArray(content)); } return new DocHandleDocumentDTO(doc, STORE_ID); } catch (PersistenceException | IOException e) { throw new ElexisException("cannot save", e); } finally { if (content != null) { IOUtils.closeQuietly(content); } } } @Override public Optional<InputStream> loadContent(IDocument document){ DocHandle doc = DocHandle.load(document.getId()); if (doc.exists()) { try { byte[] buf = doc.getContentsAsBytes(); if (buf != null) { return Optional.of(new ByteArrayInputStream(buf)); } } catch (ElexisException e) { log.error("Cannot load contents of document id: " + document.getId(), e); } } return Optional.empty(); } @Override public IDocument createDocument(String patientId, String title, String categoryName){ DocHandleDocumentDTO docHandleDocumentDTO = new DocHandleDocumentDTO(STORE_ID); ICategory iCategory = categoryName != null ? new CategoryDocumentDTO(categoryName) : getCategoryDefault(); docHandleDocumentDTO.setCategory(iCategory); docHandleDocumentDTO.setPatientId(patientId); docHandleDocumentDTO.setTitle(title); return docHandleDocumentDTO; } @Override public ICategory getCategoryDefault(){ return new CategoryDocumentDTO(Constants.DEFAULT_CATEGORY); } @Override public Optional<IPersistentObject> getPersistenceObject(IDocument iDocument){ return Optional.of(DocHandle.load(iDocument.getId())); } @Override public ICategory createCategory(String name){ if (name != null) { if (findCategoriesByName(name).isEmpty()) { DocHandle.addMainCategory(name); } } return new CategoryDocumentDTO(name); } private List<ICategory> findCategoriesByName(String name){ Query<DocHandle> query = new Query<>(DocHandle.class); query.add(DocHandle.FLD_CAT, Query.EQUALS, name, true); query.add(DocHandle.FLD_MIMETYPE, Query.EQUALS, CATEGORY_MIMETYPE); List<DocHandle> docs = query.execute(); List<ICategory> iCategories = new ArrayList<>(); for (DocHandle docHandle : docs) { iCategories.add(new CategoryDocumentDTO(docHandle.getCategoryName())); } return iCategories; } @Override public void removeCategory(IDocument iDocument, String newCategory) throws IllegalStateException{ if (iDocument.getId() != null && iDocument.getCategory() != null) { // check if document to category references exists and ignore current iDocument ICategory oldCategory = iDocument.getCategory(); Query<DocHandle> query = new Query<>(DocHandle.class); query.add(DocHandle.FLD_CAT, Query.EQUALS, oldCategory.getName(), true); query.add(DocHandle.FLD_MIMETYPE, Query.NOT_EQUAL, CATEGORY_MIMETYPE); query.add(DocHandle.FLD_ID, Query.NOT_EQUAL, iDocument.getId()); List<DocHandle> docs = query.execute(); if (!docs.isEmpty()) { throw new IllegalStateException( "at least one document to category reference exists with id: " + docs.get(0).getId()); } DocHandle.removeCategory(oldCategory.getName(), newCategory); } } @Override public void renameCategory(ICategory category, String newCategory) throws IllegalStateException{ DocHandle.renameCategory(category.getName(), newCategory); } }