orbeon-bluedb-integration/integration-module/src/main/java/hycom/dao/FormDao.java

447 lines
15 KiB
Java

package hycom.dao;
import hycom.exceptions.DbException;
import hycom.model.Attachment;
import hycom.model.Document;
import hycom.model.Form;
import hycom.model.User;
import hycom.utils.AppUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.tomcat.util.http.fileupload.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* DAO for populated forms
*/
@Component
@RequestMapping("/logger")
public class FormDao extends BaseDao {
private static final Logger logger = LoggerFactory.getLogger(FormDao.class);
@Value("${orbeon.address}")
private String hostAddress;
@Value("${form.name.input}")
private String formName;
@Value("${form.category.select}")
private String formCategory;
@Value("${form.pillar.select}")
private String formPillar;
@Value("${form.directory.temp}")
private String tmpDir;
byte[] buffer = new byte[1024];
public List<Form> getForms(Integer offset, Integer limit, String fromDate, String toDate, String formNameSearch,
String category, String pillar, String name) throws DbException {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder
.append("SELECT ofd.document_id, s.send_date, ofd.form_version, ofd.id, ofd.app, ofd.form, ofda.count, name.val AS name, category.val AS category, pillar.val AS pillar \n" +
"FROM orbeon_form_data ofd\n" + "INNER JOIN submitted_forms s ON ofd.id = s.form_id \n" +
"LEFT JOIN (\n" + "SELECT document_id, COUNT(*) AS count FROM orbeon_form_data_attach \n" +
"GROUP BY document_id) ofda ON ofd.document_id = ofda.document_id\n" +
"LEFT JOIN (SELECT data_id, val FROM orbeon_i_control_text WHERE control LIKE '%" + formName +
"%') name ON ofd.id=name.data_id\n" +
"LEFT JOIN (SELECT data_id, val FROM orbeon_i_control_text WHERE control LIKE '%" + formCategory +
"%') category ON ofd.id=category.data_id\n" +
"LEFT JOIN (SELECT data_id, val FROM orbeon_i_control_text WHERE control LIKE '%" + formPillar +
"%') pillar ON ofd.id=pillar.data_id WHERE (1=1)");
if (!StringUtils.isEmpty(fromDate) && !fromDate.equals("*")) {
sqlBuilder.append(" AND s.send_date >= '").append(fromDate).append("'");
}
if (!StringUtils.isEmpty(toDate) && !toDate.equals("*")) {
sqlBuilder.append(" AND s.send_date <= '").append(toDate).append("'");
}
if (!StringUtils.isEmpty(formNameSearch) && !formNameSearch.equals("*")) {
sqlBuilder.append(" AND ofd.form LIKE '%").append(formNameSearch).append("%'");
}
if (!StringUtils.isEmpty(category) && !category.equals("*")) {
sqlBuilder.append(" AND category.val LIKE '%").append(category).append("%'");
}
if (!StringUtils.isEmpty(name) && !name.equals("*")) {
sqlBuilder.append(" AND name.val LIKE '%").append(name).append("%'");
}
if (!StringUtils.isEmpty(pillar) && !pillar.equals("*")) {
sqlBuilder.append(" AND pillar.val LIKE '%").append(pillar).append("%'");
}
sqlBuilder.append(" ORDER BY send_date DESC");
if (offset != null) {
sqlBuilder.append(" OFFSET ").append(offset);
}
if (limit != null) {
sqlBuilder.append(" LIMIT ").append(limit);
}
List<Form> forms = jdbcTemplate.query(sqlBuilder.toString(), (rs, i) -> {
String appName = rs.getString("app");
String formName = rs.getString("form");
String formId = rs.getString("document_id");
Form form = new Form();
form.setFormName(formName);
form.setLink(AppUtils.generateLink(hostAddress, appName, formName, formId));
form.setAttachment(rs.getInt("count") > 0);
form.setSendDate(rs.getTimestamp("send_date"));
form.setName(rs.getString("name"));
form.setCategory(rs.getString("category"));
form.setPillar(rs.getString("pillar"));
return form;
});
return forms;
}
public Long getFormsCount(String fromDate, String toDate, String formNameSearch, String category, String pillar, String name)
throws DbException {
StringBuilder sqlBuilder = new StringBuilder();
sqlBuilder.append("SELECT count(ofd.id) \n" + "FROM orbeon_form_data ofd\n" +
"INNER JOIN submitted_forms s ON ofd.id = s.form_id \n" + "LEFT JOIN (\n" +
"SELECT document_id, COUNT(*) AS count FROM orbeon_form_data_attach \n" +
"GROUP BY document_id) ofda ON ofd.document_id = ofda.document_id\n" +
"LEFT JOIN (SELECT data_id, val FROM orbeon_i_control_text WHERE control LIKE '%" + formName +
"%') name ON ofd.id=name.data_id\n" +
"LEFT JOIN (SELECT data_id, val FROM orbeon_i_control_text WHERE control LIKE '%" + formCategory +
"%') category ON ofd.id=category.data_id\n" +
"LEFT JOIN (SELECT data_id, val FROM orbeon_i_control_text WHERE control LIKE '%" + formPillar +
"%') pillar ON ofd.id=pillar.data_id WHERE (1=1)");
if (!StringUtils.isEmpty(fromDate) && !fromDate.equals("*")) {
sqlBuilder.append(" AND s.send_date >= '").append(fromDate).append("'");
}
if (!StringUtils.isEmpty(toDate) && !toDate.equals("*")) {
sqlBuilder.append(" AND s.send_date <= '").append(toDate).append("'");
}
if (!StringUtils.isEmpty(formNameSearch) && !formNameSearch.equals("*")) {
sqlBuilder.append(" AND ofd.form LIKE '%").append(formNameSearch).append("%'");
}
if (!StringUtils.isEmpty(category) && !category.equals("*")) {
sqlBuilder.append(" AND category.val LIKE '%").append(category).append("%'");
}
if (!StringUtils.isEmpty(name) && !name.equals("*")) {
sqlBuilder.append(" AND name.val LIKE '%").append(name).append("%'");
}
if (!StringUtils.isEmpty(pillar) && !pillar.equals("*")) {
sqlBuilder.append(" AND pillar.val LIKE '%").append(pillar).append("%'");
}
Long count = jdbcTemplate.queryForObject(sqlBuilder.toString(), (rs, i) -> {
return rs.getLong("count");
});
return count;
}
public List<User> getUsersContainsAttachments() throws DbException {
String sql = "SELECT DISTINCT att.username from orbeon_form_data_attach att \n" +
"INNER JOIN orbeon_form_data ofd ON ofd.document_id = att.document_id \n" +
"INNER JOIN submitted_forms sf ON sf.form_id = ofd.id\n" + "WHERE att.username IS NOT NULL";
List<User> users = jdbcTemplate.query(sql, (rs, i) -> {
User user = new User();
user.setUserName(rs.getString("username"));
user.setMember(true);
return user;
});
return users;
}
public String getAttachments(String userName) throws DbException {
String sql = "SELECT ofd.document_id, ofd.form_version, ofd.xml, ofd.app, ofd.form from orbeon_form_data ofd\n" +
"INNER JOIN submitted_forms sf ON sf.form_id = ofd.id\n" +
"WHERE EXISTS (SELECT 1 FROM orbeon_form_data_attach att WHERE att.document_id = ofd.document_id)\n" +
"AND ofd.username = '" + userName + "';";
List<Document> documents = jdbcTemplate.query(sql, (rs, i) -> {
String documentId = rs.getString("document_id");
String xmlFile = rs.getString("xml");
String appName = rs.getString("app");
String formName = rs.getString("form");
String formVersion = rs.getString("form_version");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = null;
try {
dBuilder = dbFactory.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(xmlFile.getBytes(StandardCharsets.UTF_8));
org.w3c.dom.Document doc = dBuilder.parse(stream);
doc.getDocumentElement().normalize();
Element element = doc.getDocumentElement();
NodeList nodeList = element.getChildNodes();
Document document = new Document();
document.setDocumentId(documentId);
document.setAppName(appName);
document.setFormName(formName);
document.setVersion(Long.parseLong(formVersion));
List<Attachment> attachments = new LinkedList<>();
attachments = populateList(nodeList, attachments);
document.setAttachments(attachments);
return document;
}
catch (ParserConfigurationException | IOException | SAXException e) {
e.printStackTrace();
}
return null;
});
if (!CollectionUtils.isEmpty(documents)) {
File directory = new File(tmpDir + "/" + userName);
if (!directory.exists()) {
directory.mkdir();
}
}
for (Document document : documents) {
for (Attachment attachment : document.getAttachments()) {
String sql2 =
"SELECT file_content FROM orbeon_form_data_attach WHERE file_name = '" + attachment.getFileEncodedName() +
"' ";
jdbcTemplate.query(sql2, (rs, i) -> {
try {
InputStream inputStream = rs.getBinaryStream("file_content");
OutputStream outputStream =
new FileOutputStream(tmpDir + "/" + userName + "/" + attachment.getFileName());
int bytesRead = -1;
byte[] buffer = new byte[1024];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
inputStream.close();
outputStream.close();
}
catch (IOException e) {
e.getMessage();
}
return null;
});
}
try {
FileOutputStream fos = new FileOutputStream(tmpDir + "/" + userName + ".zip");
ZipOutputStream zos = new ZipOutputStream(fos);
File folder = new File(tmpDir + "/" + userName);
for (File file : folder.listFiles()) {
ZipEntry ze = new ZipEntry(file.getName());
zos.putNextEntry(ze);
FileInputStream in = new FileInputStream(file.getPath());
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
in.close();
zos.closeEntry();
}
zos.close();
}
catch (IOException e) {
logger.error("Cannot remove attachments for :" );
}
return tmpDir + "/" + userName + ".zip";
}
return null;
}
public void removeAttachments(String userName) throws DbException {
File folder = new File(tmpDir + "/" + userName);
File zipFile = new File(tmpDir + "/" + userName + ".zip");
try {
FileUtils.deleteDirectory(folder);
}
catch (IOException e) {
logger.error("Cannot remove temp directory for user {} : {}", userName, e.getMessage());
}
zipFile.delete();
String deleteAttachmentsSql =
"DELETE FROM orbeon_form_data_attach AS ofda USING orbeon_form_data AS ofd WHERE ofda.document_id = ofd.document_id AND EXISTS (SELECT 1 FROM submitted_forms sf WHERE sf.form_id = ofd.id) AND ofd.username = '" +
userName + "'; ";
String updateAttachmentsSql = "UPDATE submitted_forms sf SET attachments_moved = TRUE where form_id IN (\n" +
"SELECT sf.form_id FROM submitted_forms sf \n" + "inner JOIN orbeon_form_data ofd ON sf.form_id = ofd.id \n" +
"WHERE ofd.username = '" + userName + "');";
try {
int i = jdbcTemplate.update(deleteAttachmentsSql);
int j = jdbcTemplate.update(updateAttachmentsSql);
logger.info("There are {} deleted attachments for user: {}", i, userName);
}
catch (Exception e) {
logger.error("Cannot remove attachments for user {} : {}", userName, e.getMessage());
}
}
/**
* Populete list of attachments for xml file node elements
*
* @param nodeList node list from xml file
*
* @param attachments list to populate
*
* @return populated list of attachments
*/
private List<Attachment> populateList(NodeList nodeList, List<Attachment> attachments) {
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
if (node.hasAttributes() && ((Element) node).hasAttribute("filename")) {
String fileName = ((Element) node).getAttribute("filename");
String mediaType = ((Element) node).getAttribute("mediatype");
String fileEncodedName = getFileEncodedName(node.getTextContent());
System.out.println(((Element) node).getAttribute("size"));
Attachment attachment = new Attachment();
attachment.setFileName(fileName);
attachment.setMediaType(mediaType);
attachment.setFileEncodedName(fileEncodedName);
attachments.add(attachment);
}
else {
if (node.getChildNodes().getLength() > 0) {
populateList(node.getChildNodes(), attachments);
}
else {
continue;
}
}
}
else {
continue;
}
}
return attachments;
}
/**
* Returns filename from xml node
*
* @param nodeContent node with file element
*
* @return filename
*/
private String getFileEncodedName(String nodeContent) {
int lastIndex = nodeContent.lastIndexOf("/");
return nodeContent.substring(lastIndex + 1);
}
public List<Form> getForms() throws DbException {
return getForms(null, null, null, null, null, null, null, null);
}
public Form getForm(int formId) throws DbException {
String sql = "SELECT app, form FROM orbeon_form_data WHERE id = " + formId;
return jdbcTemplate.query(sql, rs -> {
if (rs.next()) {
Form form = new Form();
form.setFormName(rs.getString("app"));
form.setName(rs.getString("form"));
return form;
}
return null;
});
}
public void submitForm(String id) throws DbException {
String sql = "INSERT INTO submitted_forms (form_id, send_date) VALUES ((SELECT id FROM orbeon_form_data ofd\n" +
"INNER JOIN (\n" + "SELECT app, form, document_id, MAX(last_modified_time) AS max_last_modified\n" +
"FROM orbeon_form_data o GROUP BY app, form, document_id) forms ON ofd.app = forms.app AND ofd.form = forms.form\n" +
"WHERE ofd.document_id = '" + id + "'\n" +
"AND ofd.last_modified_time = forms.max_last_modified), CURRENT_TIMESTAMP)";
jdbcTemplate.update(sql);
}
public void deleteSubmittedForm(String documentId) {
String sql = "DELETE FROM submitted_forms WHERE id IN (SELECT submitted_forms.id FROM submitted_forms INNER JOIN orbeon_form_data ON submitted_forms.form_id = orbeon_form_data.id WHERE document_id ='" + documentId + "')";
jdbcTemplate.update(sql);
}
public Boolean hasRemovedAttachments(String documentId) throws DbException {
String sql = "SELECT sf.id FROM submitted_forms sf INNER JOIN orbeon_form_data ofd ON sf.form_id = ofd.id AND sf.attachments_moved = TRUE AND ofd.document_id = '" + documentId + "';";
return jdbcTemplate.query(sql, rs -> {
if (rs.next()) {
return true;
}
return false;
});
}
public boolean isFormSubmitted(String documentId) throws DbException {
String sql = "SELECT sf.id from submitted_forms sf INNER JOIN orbeon_form_data ofd ON sf.form_id = ofd.id WHERE ofd.document_id = '" + documentId + "';";
return jdbcTemplate.query(sql, rs -> {
if (rs.next()) {
return true;
}
return false;
});
}
}