447 lines
15 KiB
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;
|
|
});
|
|
}
|
|
|
|
}
|