001: package org.contineo.web.document;
002:
003: import org.apache.commons.lang.StringUtils;
004: import org.apache.commons.lang.builder.ReflectionToStringBuilder;
005: import org.apache.commons.logging.Log;
006: import org.apache.commons.logging.LogFactory;
007:
008: import org.contineo.core.document.CheckinDocUtil;
009: import org.contineo.core.document.Document;
010: import org.contineo.core.document.History;
011: import org.contineo.core.document.Version;
012: import org.contineo.core.document.dao.DocumentDAO;
013: import org.contineo.core.document.dao.HistoryDAO;
014: import org.contineo.core.i18n.DateBean;
015: import org.contineo.core.searchengine.SearchDocument;
016: import org.contineo.core.searchengine.crawler.Indexer;
017: import org.contineo.core.searchengine.dao.SearchDocumentDAO;
018: import org.contineo.core.security.Menu;
019: import org.contineo.core.security.dao.MenuDAO;
020: import org.contineo.core.text.parser.Parser;
021: import org.contineo.core.text.parser.ParserFactory;
022: import org.contineo.core.util.IconSelector;
023:
024: import org.contineo.util.Context;
025: import org.contineo.util.config.SettingsConfig;
026:
027: import org.contineo.web.SessionManagement;
028: import org.contineo.web.i18n.Messages;
029: import org.contineo.web.navigation.PageContentBean;
030: import org.contineo.web.upload.InputFileBean;
031:
032: import java.io.File;
033: import java.io.FileInputStream;
034:
035: import java.util.Date;
036: import java.util.Set;
037:
038: import javax.faces.application.Application;
039: import javax.faces.application.FacesMessage;
040: import javax.faces.context.FacesContext;
041:
042: /**
043: * Base form for document editing
044: *
045: * @author Marco Meschieri
046: * @version $Id: DocumentEditForm.java,v 1.9 2006/09/03 16:24:37 marco Exp $
047: * @since 3.0
048: */
049: public class DocumentEditForm {
050: protected static Log log = LogFactory
051: .getLog(DocumentEditForm.class);
052: private String docName;
053: private int menuParent;
054: private int menuSort = 0;
055: private String source;
056: private String sourceAuthor;
057: private Date sourceDate;
058: private Date docDate;
059: private String sourceType;
060: private String coverage;
061: private String language;
062: private String keywords;
063: private String versionDesc;
064: private String filename;
065: private Menu menu;
066: private String[] menuGroup;
067: private DocumentRecord record;
068: private boolean readOnly = false;
069: private DocumentNavigation documentNavigation;
070:
071: public DocumentEditForm() {
072: reset();
073: }
074:
075: public void reset() {
076: docName = "";
077: menuParent = -1;
078: menuSort = 0;
079: source = "";
080: sourceAuthor = "";
081: sourceDate = new Date();
082: docDate = new Date();
083: sourceType = "";
084: coverage = "";
085: language = "";
086: keywords = "";
087: versionDesc = "";
088: filename = "";
089: menu = null;
090: menuGroup = null;
091: }
092:
093: public void init(DocumentRecord record) {
094: this .record = record;
095: this .menu = record.getMenu();
096:
097: Document doc = record.getDocument();
098: setDocName(doc.getDocName());
099:
100: setMenuParent(doc.getMenu().getMenuParent());
101: setSource(doc.getSource());
102: setSourceAuthor(doc.getSourceAuthor());
103:
104: if (StringUtils.isNotEmpty(doc.getSourceDate())) {
105: setSourceDate(DateBean.dateFromCompactString(doc
106: .getSourceDate()));
107: }
108:
109: if (StringUtils.isNotEmpty(doc.getDocDate())) {
110: setDocDate(DateBean.dateFromCompactString(doc.getDocDate()));
111: }
112:
113: setLanguage(doc.getLanguage());
114: setKeywords(doc.getKeywordsString());
115: setCoverage(doc.getCoverage());
116: setSourceType(doc.getSourceType());
117:
118: String[] groupNames = record.getMenu().getMenuGroupNames();
119: setMenuGroup(groupNames);
120: }
121:
122: /**
123: * @return Returns the docName.
124: */
125: public String getDocName() {
126: return docName;
127: }
128:
129: /**
130: * @return Returns the menuParent.
131: */
132: public int getMenuParent() {
133: return menuParent;
134: }
135:
136: /**
137: * @return Returns the menuSort.
138: */
139: public int getMenuSort() {
140: return menuSort;
141: }
142:
143: /**
144: * @return Returns the source.
145: */
146: public String getSource() {
147: return source;
148: }
149:
150: /**
151: * @return Returns the sourceAuthor.
152: */
153: public String getSourceAuthor() {
154: return sourceAuthor;
155: }
156:
157: /**
158: * @return Returns the sourceDate.
159: */
160: public Date getSourceDate() {
161: return sourceDate;
162: }
163:
164: /**
165: * @return Returns the sourceType.
166: */
167: public String getSourceType() {
168: return sourceType;
169: }
170:
171: /**
172: * @return Returns the coverage.
173: */
174: public String getCoverage() {
175: return coverage;
176: }
177:
178: /**
179: * @return Returns the language.
180: */
181: public String getLanguage() {
182: return language;
183: }
184:
185: /**
186: * @return Returns the keywords.
187: */
188: public String getKeywords() {
189: return keywords;
190: }
191:
192: /**
193: * @return Returns the versionDesc.
194: */
195: public String getVersionDesc() {
196: return versionDesc;
197: }
198:
199: /**
200: * @return Returns the menuGroup.
201: */
202: public String[] getMenuGroup() {
203: return menuGroup;
204: }
205:
206: /**
207: * @param docName The docName to set.
208: */
209: public void setDocName(String name) {
210: docName = name;
211: }
212:
213: /**
214: * @param menuParent The menuParent to set.
215: */
216: public void setMenuParent(int parent) {
217: menuParent = parent;
218: }
219:
220: /**
221: * @param menuSort The menuSort to set.
222: */
223: public void setMenuSort(int sort) {
224: menuSort = sort;
225: }
226:
227: /**
228: * @param source The source to set.
229: */
230: public void setSource(String src) {
231: source = src;
232: }
233:
234: /**
235: * @param sourceAuthor The sourceAuthor to set.
236: */
237: public void setSourceAuthor(String author) {
238: sourceAuthor = author;
239: }
240:
241: /**
242: * @param sourceDate The sourceDate to set.
243: */
244: public void setSourceDate(Date date) {
245: sourceDate = date;
246: }
247:
248: /**
249: * @param sourceType The sourceType to set.
250: */
251: public void setSourceType(String type) {
252: sourceType = type;
253: }
254:
255: /**
256: * @param coverage The coverage to set.
257: */
258: public void setCoverage(String cover) {
259: coverage = cover;
260: }
261:
262: /**
263: * @param language The language to set.
264: */
265: public void setLanguage(String lang) {
266: language = lang;
267: }
268:
269: /**
270: * @param keywords The keywords to set.
271: */
272: public void setKeywords(String words) {
273: keywords = words;
274: }
275:
276: /**
277: * @return Returns the filename.
278: */
279: public String getFilename() {
280: return filename;
281: }
282:
283: /**
284: * @param filename The filename to set.
285: */
286: public void setFilename(String filename) {
287: this .filename = filename;
288: }
289:
290: /**
291: * @return Returns the menu.
292: */
293: public Menu getMenu() {
294: return menu;
295: }
296:
297: /**
298: * @param menu The menu to set.
299: */
300: public void setMenu(Menu menu) {
301: this .menu = menu;
302: }
303:
304: /**
305: * @param versionDesc The versionDesc to set.
306: */
307: public void setVersionDesc(String desc) {
308: versionDesc = desc;
309: }
310:
311: /**
312: * @param menuGroups The menuGroup to set.
313: */
314: public void setMenuGroup(String[] group) {
315: menuGroup = group;
316: }
317:
318: public Date getDocDate() {
319: return docDate;
320: }
321:
322: public void setDocDate(Date docDate) {
323: this .docDate = docDate;
324: }
325:
326: public String toString() {
327: return (new ReflectionToStringBuilder(this ) {
328: protected boolean accept(java.lang.reflect.Field f) {
329: return super .accept(f);
330: }
331: }).toString();
332: }
333:
334: /**
335: * Saves data into a new Document. Saves the information provided in the
336: * document form. That also includes updating the search index for example.
337: * This method is invoked in the document's upload wizard
338: */
339: public String save() {
340: if (SessionManagement.isValid()) {
341: try {
342: MenuDAO mdao = (MenuDAO) Context.getInstance().getBean(
343: MenuDAO.class);
344: DocumentDAO ddao = (DocumentDAO) Context.getInstance()
345: .getBean(DocumentDAO.class);
346:
347: String userName = SessionManagement.getUsername();
348: Menu parent = documentNavigation.getSelectedDir()
349: .getMenu();
350:
351: if (mdao.isWriteEnable(parent.getMenuId(), userName)) {
352: Document doc = new Document();
353: Version vers = new Version();
354:
355: // extract file extension of the new file and select a file
356: // icon based on the extension
357: FacesContext facesContext = FacesContext
358: .getCurrentInstance();
359: InputFileBean inputFile = ((InputFileBean) facesContext
360: .getApplication().createValueBinding(
361: "#{inputFile}").getValue(
362: FacesContext.getCurrentInstance()));
363: String filename = inputFile.getFileName();
364: String ext = filename.substring(filename
365: .lastIndexOf(".") + 1);
366: String name = getDocName();
367:
368: if (StringUtils.isNotEmpty(name)) {
369: menu.setMenuText(name);
370: } else {
371: menu.setMenuText(filename.substring(0, filename
372: .lastIndexOf(".")));
373: }
374:
375: String icon = IconSelector.selectIcon(ext);
376: menu.setMenuIcon(icon.toString());
377:
378: menu.setMenuSort(getMenuSort());
379: menu.setMenuType(Menu.MENUTYPE_FILE);
380:
381: menu.setMenuRef(filename);
382:
383: updateGroups(menu);
384: mdao.store(menu);
385:
386: doc.setMenu(menu);
387:
388: if ((name != null) && !name.equals("")) {
389: doc.setDocName(name);
390: } else {
391: doc.setDocName(filename.substring(0, filename
392: .lastIndexOf(".")));
393: }
394:
395: doc.setDocDate(DateBean.toCompactString());
396: doc.setSourceDate(DateBean
397: .toCompactString(sourceDate));
398: doc.setDocPublisher(userName);
399: doc.setDocStatus(Document.DOC_CHECKED_IN);
400: doc.setDocType(filename.substring(filename
401: .lastIndexOf(".") + 1));
402: doc.setDocVersion("1.0");
403: doc.setSource(getSource());
404: doc.setSourceAuthor(getSourceAuthor());
405:
406: String dateStr = DateBean
407: .toCompactString(getSourceDate());
408:
409: if (dateStr != null) {
410: doc.setSourceDate(dateStr);
411: }
412:
413: doc.setSourceType(getSourceType());
414: doc.setCoverage(getCoverage());
415: doc.setLanguage(getLanguage());
416:
417: /* insert initial version 1.0 */
418: vers.setVersion("1.0");
419: vers.setVersionComment(getVersionDesc());
420: vers.setVersionDate(DateBean.toCompactString());
421:
422: vers.setVersionUser(userName);
423: doc.addVersion(vers);
424:
425: /* create keywords for the document */
426: Set<String> keywords = ddao
427: .toKeywords(getKeywords());
428: doc.setKeywords(keywords);
429:
430: boolean stored = ddao.store(doc);
431:
432: /* create history entry */
433: History history = new History();
434: history.setDocId(doc.getDocId());
435: history.setDate(DateBean.toCompactString());
436: history.setUsername(userName);
437: history.setEvent(History.STORED);
438:
439: HistoryDAO historyDAO = (HistoryDAO) Context
440: .getInstance().getBean(HistoryDAO.class);
441: historyDAO.store(history);
442:
443: String menupath = menu.getMenuPath();
444: SettingsConfig settings = (SettingsConfig) Context
445: .getInstance()
446: .getBean(SettingsConfig.class);
447: String path = new StringBuilder(settings
448: .getValue("docdir")).append(menupath)
449: .append(File.separator).append(
450: String.valueOf(menu.getMenuId()))
451: .append(File.separator).toString();
452:
453: /* create search index entry */
454: String lang = doc.getLanguage();
455:
456: Indexer index = (Indexer) Context.getInstance()
457: .getBean(Indexer.class);
458: int luceneId = index.addFile(new File(
459: new StringBuilder(path).append(
460: File.separator).append(
461: menu.getMenuRef()).toString()),
462: doc, inputFile.getContent(), lang);
463: SearchDocument searchDoc = new SearchDocument();
464: searchDoc.setLuceneId(luceneId);
465: searchDoc.setMenuId(menu.getMenuId());
466:
467: if (lang.equals("de")) {
468: searchDoc.setIndex("german");
469: } else if (lang.equals("fr")) {
470: searchDoc.setIndex("french");
471: } else if (lang.equals("es")) {
472: searchDoc.setIndex("spanish");
473: } else if (lang.equals("it")) {
474: searchDoc.setIndex("italian");
475: } else {
476: searchDoc.setIndex("english");
477: }
478:
479: SearchDocumentDAO searchDocDao = (SearchDocumentDAO) Context
480: .getInstance().getBean(
481: SearchDocumentDAO.class);
482: searchDocDao.store(searchDoc);
483:
484: //Update file size
485: mdao.store(menu);
486:
487: /* create messages */
488: if (!stored) {
489: Messages
490: .addMessage(
491: FacesMessage.SEVERITY_ERROR,
492: Messages
493: .getMessage("errors.action.savedoc"),
494: Messages
495: .getMessage("errors.action.savedoc"));
496: } else {
497: Messages
498: .addMessage(
499: FacesMessage.SEVERITY_INFO,
500: Messages
501: .getMessage("msg.jsp.docstored"),
502: Messages
503: .getMessage("msg.jsp.docstored"));
504: }
505: }
506: } catch (Exception e) {
507: log.error(e.getMessage(), e);
508: Messages.addMessage(FacesMessage.SEVERITY_ERROR, e
509: .getMessage(), e.getMessage());
510: }
511:
512: return null;
513: } else {
514: return "login";
515: }
516: }
517:
518: /**
519: * Updates data into a Document. Saves the information provided in the
520: * document form. That also includes updating the search index for example.
521: * This method is invoked for document's editing
522: */
523: public String update() {
524: FacesContext facesContext = FacesContext.getCurrentInstance();
525: DocumentNavigation navigation = ((DocumentNavigation) facesContext
526: .getApplication().createValueBinding(
527: "#{documentNavigation}").getValue(
528: FacesContext.getCurrentInstance()));
529: MenuDAO mdao = (MenuDAO) Context.getInstance().getBean(
530: MenuDAO.class);
531: DocumentDAO ddao = (DocumentDAO) Context.getInstance().getBean(
532: DocumentDAO.class);
533: HistoryDAO historyDAO = (HistoryDAO) Context.getInstance()
534: .getBean(HistoryDAO.class);
535:
536: if (SessionManagement.isValid()) {
537: try {
538: Document doc = record.getDocument();
539: Menu menu = mdao.findByPrimaryKey(doc.getMenuId());
540:
541: String name = getDocName();
542:
543: if (StringUtils.isNotEmpty(name)) {
544: menu.setMenuText(name);
545: }
546:
547: mdao.store(menu);
548:
549: doc.setMenu(menu);
550: doc.setDocName(name);
551: doc.setSource(getSource());
552: doc.setSourceAuthor(getSourceAuthor());
553: doc.setSourceDate(DateBean
554: .toCompactString(getSourceDate()));
555: doc.setSourceType(getSourceType());
556: doc.setCoverage(getCoverage());
557:
558: // Intercept language changes
559: String oldLang = doc.getLanguage();
560: doc.setLanguage(getLanguage());
561:
562: doc.clearKeywords();
563:
564: Set<String> keywords = ddao.toKeywords(getKeywords());
565: boolean stored = ddao.store(doc);
566: doc.setKeywords(keywords);
567: stored = ddao.store(doc);
568:
569: /* create history entry */
570: String username = SessionManagement.getUsername();
571: History history = new History();
572: history.setDocId(doc.getDocId());
573: history.setDate(DateBean.toCompactString());
574: history.setUsername(username);
575: history.setEvent(History.CHANGED);
576: historyDAO.store(history);
577:
578: /* create messages */
579: if (!stored) {
580: Messages
581: .addLocalizedError("errors.action.changedoc");
582: } else {
583: Messages.addLocalizedInfo("msg.action.changedoc");
584: }
585:
586: // Launch document re-indexing
587: reindexDocument(doc, oldLang);
588: } catch (Exception e) {
589: log.error(e.getMessage(), e);
590: Messages.addError(e.getMessage());
591: }
592:
593: navigation
594: .setSelectedPanel(new PageContentBean("documents"));
595: navigation.refresh();
596:
597: return null;
598: } else {
599: return "login";
600: }
601: }
602:
603: /**
604: * Executes a document's checkin creating a new version
605: */
606: public String checkin() {
607: Application application = FacesContext.getCurrentInstance()
608: .getApplication();
609: InputFileBean fileForm = ((InputFileBean) application
610: .createValueBinding("#{inputFile}").getValue(
611: FacesContext.getCurrentInstance()));
612:
613: if (SessionManagement.isValid()) {
614: String username = SessionManagement.getUsername();
615: String versionDesc = fileForm.getDescription();
616: Document document = record.getDocument();
617: File file = fileForm.getFile();
618:
619: if (document.getDocStatus() == Document.DOC_CHECKED_OUT) {
620: if (file != null) {
621: // check that we have a valid file for storing as new
622: // version
623: String fileName = fileForm.getFileName();
624: String type = fileForm.getVersionType();
625:
626: // determines the kind of version to create
627: Version.VERSION_TYPE versionType;
628:
629: if (type.equals("release")) {
630: versionType = Version.VERSION_TYPE.NEW_RELEASE;
631: } else if (type.equals("subversion")) {
632: versionType = Version.VERSION_TYPE.NEW_SUBVERSION;
633: } else {
634: versionType = Version.VERSION_TYPE.OLD_VERSION;
635: }
636:
637: try {
638: // checkin the document; throws an exception if
639: // something goes wrong
640: CheckinDocUtil.checkinDocument(document
641: .getDocId(), new FileInputStream(file),
642: fileName, username, versionType,
643: versionDesc);
644:
645: /* create positive log message */
646: Messages.addLocalizedInfo("msg.action.savedoc");
647: fileForm.reset();
648: } catch (Exception e) {
649: log.error(e.getMessage(), e);
650: Messages
651: .addLocalizedError("errors.action.savedoc");
652: }
653: } else {
654: Messages.addLocalizedError("errors.nofile");
655: }
656: }
657: } else {
658: return "login";
659: }
660:
661: DocumentNavigation documentNavigation = ((DocumentNavigation) application
662: .createValueBinding("#{documentNavigation}").getValue(
663: FacesContext.getCurrentInstance()));
664: documentNavigation.setSelectedPanel(new PageContentBean(
665: "documents"));
666:
667: return null;
668: }
669:
670: /**
671: * Assigns the correct group associations on the passed menu
672: */
673: private void updateGroups(Menu menu) {
674: // by default add read and write privileges to admin group
675: String[] docGroup = getMenuGroup();
676: boolean hasAdmin = false;
677:
678: for (int i = 0; i < docGroup.length; i++) {
679: if (docGroup[i].equals("admin")) {
680: hasAdmin = true;
681:
682: break;
683: }
684: }
685:
686: if (!hasAdmin) {
687: String[] docGroupAdmin = new String[docGroup.length + 1];
688: docGroupAdmin[0] = "admin";
689:
690: for (int i = 0; i < docGroup.length; i++) {
691: docGroupAdmin[i + 1] = docGroup[i];
692: }
693:
694: menu.setMenuGroup(docGroupAdmin);
695: } else {
696: menu.setMenuGroup(docGroup);
697: }
698: }
699:
700: private void reindexDocument(Document doc, String originalLanguage)
701: throws Exception {
702: /* get search index entry */
703: String lang = doc.getLanguage();
704:
705: // Extract the content from the file
706: StringBuffer content = getDocumentContent(doc);
707:
708: Indexer indexer = (Indexer) Context.getInstance().getBean(
709: Indexer.class);
710:
711: // Remove the document from the index
712: indexer.deleteFile(String.valueOf(doc.getMenuId()),
713: originalLanguage);
714:
715: // Add the document to the index (lucene 2.0 doesn't support the update
716: // operation)
717: File file = getDocumentFile(doc);
718: int luceneId = indexer.addFile(file, doc, content, lang);
719:
720: // Update the reference to the luceneId
721: SearchDocumentDAO searchDocDao = (SearchDocumentDAO) Context
722: .getInstance().getBean(SearchDocumentDAO.class);
723: searchDocDao.deleteByMenuId(doc.getMenuId());
724:
725: SearchDocument searchDoc = new SearchDocument();
726: searchDoc.setLuceneId(luceneId);
727: searchDoc.setMenuId(doc.getMenuId());
728:
729: if (lang.equals("de")) {
730: searchDoc.setIndex("german");
731: } else if (lang.equals("fr")) {
732: searchDoc.setIndex("french");
733: } else if (lang.equals("es")) {
734: searchDoc.setIndex("spanish");
735: } else if (lang.equals("it")) {
736: searchDoc.setIndex("italian");
737: } else {
738: searchDoc.setIndex("english");
739: }
740:
741: // Store the search document into the index
742: searchDocDao.store(searchDoc);
743: }
744:
745: private File getDocumentFile(Document doc) {
746: MenuDAO menuDao = (MenuDAO) Context.getInstance().getBean(
747: MenuDAO.class);
748: SettingsConfig conf = (SettingsConfig) Context.getInstance()
749: .getBean(SettingsConfig.class);
750: Menu menu = menuDao.findByPrimaryKey(doc.getMenuId());
751: String path = conf.getValue("docdir") + "/";
752: path += (menu.getMenuPath() + "/" + menu.getMenuId());
753:
754: String filename = menu.getMenuRef();
755:
756: return new File(path, filename);
757: }
758:
759: private StringBuffer getDocumentContent(Document doc) {
760: StringBuffer content = null;
761:
762: File file = getDocumentFile(doc);
763:
764: // Parses the file where it is already stored
765: Parser parser = ParserFactory.getParser(file);
766:
767: // and gets some fields
768: if (parser != null) {
769: content = parser.getContent();
770: }
771:
772: if (content == null) {
773: content = new StringBuffer("");
774: }
775:
776: return content;
777: }
778:
779: public DocumentRecord getRecord() {
780: return record;
781: }
782:
783: public boolean isReadOnly() {
784: return readOnly;
785: }
786:
787: public void setReadOnly(boolean readOnly) {
788: this .readOnly = readOnly;
789: }
790:
791: public void setDocumentNavigation(
792: DocumentNavigation documentNavigation) {
793: this.documentNavigation = documentNavigation;
794: }
795: }
|