PageRenderTime 70ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/converge-server/modules/converge-ejb/src/main/java/dk/i2m/converge/ejb/facades/MetaDataFacadeBean.java

https://bitbucket.org/interactivemediamanagement/converge-1.x
Java | 578 lines | 434 code | 84 blank | 60 comment | 29 complexity | 9eafb587d0bcf654e9f47cb18a4174fa MD5 | raw file
  1. /*
  2. * Copyright (C) 2010 - 2011 Interactive Media Management
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. package dk.i2m.converge.ejb.facades;
  18. import dk.i2m.converge.core.content.ContentTag;
  19. import dk.i2m.converge.core.metadata.OpenCalaisMapping;
  20. import dk.i2m.converge.core.security.UserAccount;
  21. import dk.i2m.converge.core.DataNotFoundException;
  22. import dk.i2m.converge.core.metadata.ConceptOutput;
  23. import dk.i2m.converge.core.metadata.Subject;
  24. import dk.i2m.converge.ejb.services.DaoServiceLocal;
  25. import dk.i2m.converge.ejb.services.DirectoryException;
  26. import dk.i2m.converge.ejb.services.QueryBuilder;
  27. import dk.i2m.converge.ejb.services.UserNotFoundException;
  28. import dk.i2m.converge.ejb.services.UserServiceLocal;
  29. import dk.i2m.converge.nar.newsml.g2.power.Concept;
  30. import dk.i2m.converge.nar.newsml.g2.power.ConceptNameType;
  31. import dk.i2m.converge.nar.newsml.g2.power.Definition;
  32. import dk.i2m.converge.nar.newsml.g2.power.KnowledgeItem;
  33. import dk.i2m.converge.nar.newsml.g2.power.RelatedConceptType;
  34. import java.io.ByteArrayOutputStream;
  35. import java.io.IOException;
  36. import java.io.StringReader;
  37. import java.text.MessageFormat;
  38. import java.util.*;
  39. import java.util.logging.Level;
  40. import java.util.logging.Logger;
  41. import javax.annotation.Resource;
  42. import javax.ejb.EJB;
  43. import javax.ejb.SessionContext;
  44. import javax.ejb.Stateless;
  45. import javax.ejb.TransactionAttribute;
  46. import javax.ejb.TransactionAttributeType;
  47. import javax.xml.bind.JAXBContext;
  48. import javax.xml.bind.JAXBElement;
  49. import javax.xml.bind.JAXBException;
  50. import javax.xml.bind.Unmarshaller;
  51. import org.apache.poi.hssf.usermodel.HSSFHeader;
  52. import org.apache.poi.hssf.usermodel.HSSFSheet;
  53. import org.apache.poi.hssf.usermodel.HSSFWorkbook;
  54. import org.apache.poi.hssf.usermodel.*;
  55. import org.apache.poi.hssf.usermodel.HeaderFooter;
  56. import org.apache.poi.ss.usermodel.*;
  57. import org.apache.poi.ss.util.WorkbookUtil;
  58. /**
  59. * Session bean providing a facade for meta data.
  60. *
  61. * @author Allan Lykke Christensen
  62. */
  63. @Stateless
  64. public class MetaDataFacadeBean implements MetaDataFacadeLocal {
  65. private static final Logger LOG = Logger.getLogger(MetaDataFacadeBean.class.
  66. getName());
  67. @EJB private DaoServiceLocal daoService;
  68. @EJB private UserServiceLocal userService;
  69. @EJB private UserFacadeLocal userFacade;
  70. @Resource private SessionContext ctx;
  71. /** {@inheritDoc } */
  72. @Override
  73. public dk.i2m.converge.core.metadata.Concept create(
  74. dk.i2m.converge.core.metadata.Concept concept) {
  75. Calendar now = Calendar.getInstance();
  76. concept.setCreated(now);
  77. concept.setUpdated(now);
  78. concept.setCode(concept.getTypeId() + ":" + now.getTimeInMillis());
  79. try {
  80. UserAccount updaterUser = userService.findById(ctx.
  81. getCallerPrincipal().getName());
  82. concept.setUpdatedBy(updaterUser);
  83. } catch (UserNotFoundException ex) {
  84. // Concept was created through automated service, e.g. OpenCalais
  85. LOG.log(Level.FINE, "Updating user is unknown {0}", ctx.
  86. getCallerPrincipal().getName());
  87. } catch (DirectoryException ex) {
  88. LOG.log(Level.SEVERE, "Could not connect to directory server.", ex);
  89. }
  90. return daoService.create(concept);
  91. }
  92. /** {@inheritDoc } */
  93. @Override
  94. public void deleteConcept(Long id) {
  95. daoService.delete(dk.i2m.converge.core.metadata.Concept.class, id);
  96. }
  97. /** {@inheritDoc } */
  98. @Override
  99. public void delete(Class clazz, Long id) {
  100. daoService.delete(clazz, id);
  101. }
  102. /** {@inheritDoc } */
  103. @Override
  104. public dk.i2m.converge.core.metadata.Concept update(
  105. dk.i2m.converge.core.metadata.Concept concept) {
  106. Calendar now = Calendar.getInstance();
  107. concept.setUpdated(now);
  108. try {
  109. UserAccount updaterUser = userService.findById(ctx.
  110. getCallerPrincipal().getName());
  111. concept.setUpdatedBy(updaterUser);
  112. } catch (Exception ex) {
  113. LOG.log(Level.SEVERE, "Unknown user", ex);
  114. }
  115. return daoService.update(concept);
  116. }
  117. /** {@inheritDoc } */
  118. @Override
  119. public List<dk.i2m.converge.core.metadata.Concept> getConcepts() {
  120. return daoService.findAll(dk.i2m.converge.core.metadata.Concept.class);
  121. }
  122. /** {@inheritDoc } */
  123. @Override
  124. public List<dk.i2m.converge.core.metadata.Concept> findRecentConcepts(
  125. int count) {
  126. return daoService.findWithNamedQuery(
  127. dk.i2m.converge.core.metadata.Concept.FIND_RECENTLY_ADDED, count);
  128. }
  129. /** {@inheritDoc } */
  130. @Override
  131. public dk.i2m.converge.core.metadata.Concept findConceptById(Long id) throws
  132. DataNotFoundException {
  133. return daoService.findById(dk.i2m.converge.core.metadata.Concept.class,
  134. id);
  135. }
  136. /** {@inheritDoc } */
  137. @Override
  138. public dk.i2m.converge.core.metadata.Concept findConceptByName(String name)
  139. throws DataNotFoundException {
  140. Map params = QueryBuilder.with("name", name).parameters();
  141. return daoService.findObjectWithNamedQuery(
  142. dk.i2m.converge.core.metadata.Concept.class,
  143. dk.i2m.converge.core.metadata.Concept.FIND_BY_NAME, params);
  144. }
  145. /** {@inheritDoc } */
  146. @Override
  147. public List<Subject> findSubjectsByParent(Subject parent) {
  148. Map params = QueryBuilder.with("parent", parent).parameters();
  149. return daoService.findWithNamedQuery(Subject.FIND_BY_PARENT, params);
  150. }
  151. @Override
  152. public List<Subject> findTopLevelSubjects() {
  153. return daoService.findWithNamedQuery(Subject.FIND_PARENT_SUBJECTS);
  154. }
  155. /** {@inheritDoc } */
  156. @Override
  157. public dk.i2m.converge.core.metadata.Concept findConceptByCode(String code)
  158. throws DataNotFoundException {
  159. Map params = QueryBuilder.with("code", code).parameters();
  160. return daoService.findObjectWithNamedQuery(
  161. dk.i2m.converge.core.metadata.Concept.class,
  162. dk.i2m.converge.core.metadata.Concept.FIND_BY_CODE, params);
  163. }
  164. /** {@inheritDoc} */
  165. @TransactionAttribute(TransactionAttributeType.REQUIRED)
  166. @Override
  167. public int importKnowledgeItem(String xml, String language) {
  168. //TODO: Allow for importing other items than Subjects
  169. String languageVariant;
  170. if (language.indexOf("_") == -1) {
  171. languageVariant = language.replaceAll("-", "_");
  172. } else {
  173. languageVariant = language.replaceAll("_", "-");
  174. }
  175. try {
  176. StringReader reader = new StringReader(xml);
  177. int imported = 0;
  178. JAXBContext jaxbContext = JAXBContext.newInstance(
  179. KnowledgeItem.class);
  180. Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
  181. KnowledgeItem ki = (KnowledgeItem) unmarshaller.unmarshal(reader);
  182. for (Concept c : ki.getConceptSet().getConcept()) {
  183. Subject subject;
  184. String subjectCode = c.getConceptId().getQcode();
  185. String subjectTitle = "No translation for [" + language + "]";
  186. String subjectDefinition = "No translation for [" + language
  187. + "]";
  188. // Determine if the subject already exist in the database
  189. // Note: If a subject already exist in the database it should
  190. // be updated rather than ignored
  191. boolean update = false;
  192. try {
  193. subject = (Subject) findConceptByCode(subjectCode);
  194. update = true;
  195. } catch (DataNotFoundException e) {
  196. subject = new Subject();
  197. update = false;
  198. }
  199. for (ConceptNameType cn : c.getName()) {
  200. if (cn.getLang().equalsIgnoreCase(language) || cn.getLang().
  201. equalsIgnoreCase(languageVariant)) {
  202. subjectTitle = cn.getValue();
  203. }
  204. }
  205. for (Object obj : c.getDefinitionOrNoteOrFacet()) {
  206. if (obj instanceof Definition) {
  207. Definition def = (Definition) obj;
  208. if (def.getLang().equalsIgnoreCase(language) || def.
  209. getLang().equalsIgnoreCase(languageVariant)) {
  210. for (Object defContent : def.getContent()) {
  211. subjectDefinition = (String) defContent;
  212. }
  213. }
  214. }
  215. }
  216. Calendar now = Calendar.getInstance();
  217. subject.setCreated(now);
  218. subject.setUpdated(now);
  219. subject.setName(subjectTitle);
  220. subject.setDefinition(subjectDefinition);
  221. subject.setCode(subjectCode);
  222. boolean child = false;
  223. String parentCode = "";
  224. for (Object obj : c.getSameAsOrBroaderOrNarrower()) {
  225. JAXBElement element = (JAXBElement) obj;
  226. if (element.getName().getLocalPart().equalsIgnoreCase(
  227. "broader")) {
  228. RelatedConceptType related =
  229. (RelatedConceptType) element.getValue();
  230. child = true;
  231. parentCode = related.getQcode();
  232. }
  233. }
  234. if (child) {
  235. try {
  236. Subject parent = (Subject) findConceptByCode(parentCode);
  237. subject.getBroader().add(parent);
  238. } catch (DataNotFoundException dnfe) {
  239. LOG.log(Level.WARNING,
  240. "Specify broader concept (parent) with qcode: {0} could not be found",
  241. parentCode);
  242. }
  243. }
  244. if (update) {
  245. update(subject);
  246. } else {
  247. daoService.create(subject);
  248. }
  249. imported++;
  250. }
  251. return imported;
  252. } catch (JAXBException ex) {
  253. LOG.log(Level.SEVERE, "Could not import KnowledgeItem", ex);
  254. return 0;
  255. }
  256. }
  257. /** {@inheritDoc} */
  258. @Override
  259. public String[] getLanguagesAvailableForImport(String xml) {
  260. List<String> availableLanguages = new ArrayList<String>();
  261. try {
  262. StringReader reader = new StringReader(xml);
  263. JAXBContext jaxbContext = JAXBContext.newInstance(
  264. KnowledgeItem.class);
  265. Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
  266. KnowledgeItem ki = (KnowledgeItem) unmarshaller.unmarshal(reader);
  267. for (Concept c : ki.getConceptSet().getConcept()) {
  268. for (ConceptNameType cn : c.getName()) {
  269. availableLanguages.add(cn.getLang());
  270. }
  271. break;
  272. }
  273. } catch (JAXBException ex) {
  274. LOG.log(Level.SEVERE, "Could not import KnowledgeItem", ex);
  275. }
  276. return availableLanguages.toArray(new String[availableLanguages.size()]);
  277. }
  278. /** {@inheritDoc } */
  279. @Override
  280. public List<dk.i2m.converge.core.metadata.Concept> search(String search) {
  281. Map params =
  282. QueryBuilder.with("keyword", "%" + search + "%").parameters();
  283. return daoService.findWithNamedQuery(
  284. dk.i2m.converge.core.metadata.Concept.FIND_BY_NAME_OR_DEFINITION,
  285. params);
  286. }
  287. /** {@inheritDoc} */
  288. @Override
  289. public List<dk.i2m.converge.core.metadata.Concept> findConceptByType(
  290. Class type) {
  291. return daoService.findAll(type);
  292. }
  293. @Override
  294. public List<dk.i2m.converge.core.metadata.Concept> findConceptsByName(
  295. String conceptName, Class... types) {
  296. Map<String, Object> params = QueryBuilder.with("name", conceptName + "%").
  297. parameters();
  298. List<dk.i2m.converge.core.metadata.Concept> conceptMatches = daoService.
  299. findWithNamedQuery(
  300. dk.i2m.converge.core.metadata.Concept.FIND_BY_LIKE_NAME, params);
  301. List<dk.i2m.converge.core.metadata.Concept> matches =
  302. new ArrayList<dk.i2m.converge.core.metadata.Concept>();
  303. for (dk.i2m.converge.core.metadata.Concept c : conceptMatches) {
  304. for (Class type : types) {
  305. if (c.getClass().equals(type)) {
  306. matches.add(c);
  307. // } else {
  308. // logger.log(Level.INFO, "Concept ("+ c.getFullTitle() +") of class {0} is not equal to class {1}", new Object[]{c.getClass().getName(), type.getName()});
  309. }
  310. }
  311. }
  312. return matches;
  313. }
  314. @Override
  315. public ContentTag findOrCreateContentTag(String name) {
  316. Map<String, Object> params =
  317. QueryBuilder.with("name", name).parameters();
  318. ContentTag tag;
  319. try {
  320. tag = daoService.findObjectWithNamedQuery(ContentTag.class,
  321. ContentTag.FIND_BY_NAME, params);
  322. } catch (DataNotFoundException ex) {
  323. tag = daoService.create(new ContentTag(name));
  324. }
  325. return tag;
  326. }
  327. @Override
  328. public List<ContentTag> findContentTagLikeName(String name) {
  329. Map<String, Object> params = QueryBuilder.with("name", "%" + name + "%").
  330. parameters();
  331. return daoService.findWithNamedQuery(ContentTag.FIND_LIKE_NAME, params);
  332. }
  333. /**
  334. * Gets all the mappings between Open Calais and Concepts.
  335. * <p/>
  336. * @return {@link List} of mappings between Open Calais and Concepts
  337. */
  338. @Override
  339. public List<OpenCalaisMapping> getOpenCalaisMappings() {
  340. return daoService.findAll(OpenCalaisMapping.class);
  341. }
  342. @Override
  343. public OpenCalaisMapping create(OpenCalaisMapping mapping) {
  344. return daoService.create(mapping);
  345. }
  346. @Override
  347. public OpenCalaisMapping update(OpenCalaisMapping mapping) {
  348. return daoService.update(mapping);
  349. }
  350. @Override
  351. public void deleteOpenCalaisMapping(Long id) {
  352. daoService.delete(OpenCalaisMapping.class, id);
  353. }
  354. @Override
  355. public dk.i2m.converge.core.metadata.Concept findOpenCalaisMapping(
  356. String typeGroup, String field, String value) throws
  357. DataNotFoundException {
  358. Map<String, Object> params = QueryBuilder.with("typeGroup", typeGroup).
  359. and("field", field).and("value", value).parameters();
  360. List<OpenCalaisMapping> mappings =
  361. daoService.findWithNamedQuery(
  362. OpenCalaisMapping.FIND_BY_TYPE_GROUP_FIELD_AND_VALUE, params);
  363. if (mappings.isEmpty()) {
  364. throw new DataNotFoundException("No mapping for " + typeGroup
  365. + " with field " + field + " equal to " + value);
  366. }
  367. OpenCalaisMapping firstMatch = mappings.iterator().next();
  368. return firstMatch.getConcept();
  369. }
  370. /** {@inheritDoc } */
  371. @Override
  372. public byte[] exportConcepts(Class clazz, ConceptOutput format) {
  373. // TODO: Differentiate between different output
  374. // TODO: Differentiate between Concept types
  375. final String I18N_PREFIX = "MetaDataFacadeBean_exportConcepts_";
  376. ResourceBundle i18n;
  377. try {
  378. String uid = ctx.getCallerPrincipal().getName();
  379. UserAccount user = userFacade.findById(uid);
  380. Locale userLocale = user.getPreferredLocale();
  381. i18n = ResourceBundle.getBundle(
  382. "dk.i2m.converge.i18n.ServiceMessages", userLocale);
  383. } catch (DataNotFoundException ex) {
  384. i18n = ResourceBundle.getBundle(
  385. "dk.i2m.converge.i18n.ServiceMessages");
  386. }
  387. String lblSheetName = i18n.getString(I18N_PREFIX + "SHEET_NAME");
  388. String lblHeaderLeft = i18n.getString(I18N_PREFIX + "HEADER_LEFT");
  389. String lblHeaderRight = i18n.getString(I18N_PREFIX + "HEADER_RIGHT");
  390. String lblFooterLeft = i18n.getString(I18N_PREFIX + "FOOTER_LEFT");
  391. String lblFooterRight = i18n.getString(I18N_PREFIX + "FOOTER_RIGHT");
  392. String lblDateFormat = i18n.getString(I18N_PREFIX + "DATE_FORMAT");
  393. String lblRowHeaderId = i18n.getString(I18N_PREFIX + "ROW_HEADER_ID");
  394. String lblRowHeaderName =
  395. i18n.getString(I18N_PREFIX + "ROW_HEADER_NAME");
  396. String lblRowHeaderDefinition = i18n.getString(I18N_PREFIX
  397. + "ROW_HEADER_DEFINITION");
  398. HSSFWorkbook wb = new HSSFWorkbook();
  399. String sheetName = WorkbookUtil.createSafeSheetName(lblSheetName);
  400. Font storyFont = wb.createFont();
  401. storyFont.setFontHeightInPoints((short) 12);
  402. storyFont.setBoldweight(Font.BOLDWEIGHT_NORMAL);
  403. // Create style with borders
  404. CellStyle style = wb.createCellStyle();
  405. style.setBorderBottom(CellStyle.BORDER_THIN);
  406. style.setBottomBorderColor(IndexedColors.BLACK.getIndex());
  407. style.setBorderLeft(CellStyle.BORDER_THIN);
  408. style.setLeftBorderColor(IndexedColors.BLACK.getIndex());
  409. style.setBorderRight(CellStyle.BORDER_THIN);
  410. style.setRightBorderColor(IndexedColors.BLACK.getIndex());
  411. style.setBorderTop(CellStyle.BORDER_THIN);
  412. style.setTopBorderColor(IndexedColors.BLACK.getIndex());
  413. // Create style for date cells
  414. CreationHelper createHelper = wb.getCreationHelper();
  415. CellStyle dateStyle = wb.createCellStyle();
  416. dateStyle.setDataFormat(createHelper.createDataFormat().getFormat(
  417. lblDateFormat));
  418. dateStyle.setBorderBottom(CellStyle.BORDER_THIN);
  419. dateStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
  420. dateStyle.setBorderLeft(CellStyle.BORDER_THIN);
  421. dateStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
  422. dateStyle.setBorderRight(CellStyle.BORDER_THIN);
  423. dateStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());
  424. dateStyle.setBorderTop(CellStyle.BORDER_THIN);
  425. dateStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
  426. HSSFSheet overviewSheet = wb.createSheet(sheetName);
  427. // Create sheet header
  428. HSSFHeader sheetHeader = overviewSheet.getHeader();
  429. sheetHeader.setLeft(lblHeaderLeft);
  430. sheetHeader.setRight(lblHeaderRight);
  431. // Create sheet footer
  432. Footer footer = overviewSheet.getFooter();
  433. String footerLeft = MessageFormat.format(lblFooterLeft,
  434. new Object[]{HeaderFooter.page(), HeaderFooter.numPages()});
  435. String footerRight = MessageFormat.format(lblFooterRight,
  436. new Object[]{HeaderFooter.date(), HeaderFooter.time()});
  437. footer.setLeft(footerLeft);
  438. footer.setRight(footerRight);
  439. Row row = overviewSheet.createRow(0);
  440. row.createCell(0).setCellValue(""); // Id
  441. row.getCell(0).setCellStyle(style);
  442. row.createCell(1).setCellValue(lblRowHeaderName);
  443. row.getCell(1).setCellStyle(style);
  444. row.createCell(2).setCellValue(lblRowHeaderDefinition);
  445. row.getCell(2).setCellStyle(style);
  446. // Freeze the header row
  447. overviewSheet.createFreezePane(0, 1, 0, 1);
  448. int overviewSheetRow = 0;
  449. List<dk.i2m.converge.core.metadata.Concept> concepts =
  450. findConceptByType(clazz);
  451. for (dk.i2m.converge.core.metadata.Concept concept : concepts) {
  452. row = overviewSheet.createRow(overviewSheetRow++);
  453. row.createCell(0).setCellValue(concept.getId());
  454. row.createCell(1).setCellValue(concept.getFullTitle());
  455. row.createCell(2).setCellValue(concept.getDefinition());
  456. }
  457. // Auto-size
  458. for (int i = 0; i <= 2; i++) {
  459. overviewSheet.autoSizeColumn(i);
  460. }
  461. wb.setRepeatingRowsAndColumns(0, 0, 0, 0, 0);
  462. overviewSheet.setFitToPage(true);
  463. overviewSheet.setAutobreaks(true);
  464. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  465. try {
  466. wb.write(baos);
  467. } catch (IOException ex) {
  468. LOG.log(Level.SEVERE, null, ex);
  469. }
  470. return baos.toByteArray();
  471. }
  472. private void generateChildRows(HSSFSheet overviewSheet, CellStyle style,
  473. dk.i2m.converge.core.metadata.Concept concept, int rowNumber,
  474. int indent) {
  475. if (concept == null) {
  476. return;
  477. }
  478. int col = 0;
  479. HSSFRow row = overviewSheet.createRow(rowNumber++);
  480. for (col = 0; col <= indent; col++) {
  481. row.createCell(col).setCellValue(" ");
  482. row.getCell(col).setCellStyle(style);
  483. }
  484. // row.createCell(col+1).setCellValue(concept.getId());
  485. // row.getCell(col+1).setCellStyle(style);
  486. row.createCell(col + 1).setCellValue(concept.getName());
  487. row.getCell(col + 1).setCellStyle(style);
  488. //row.createCell(col+2).setCellValue(concept.getDefinition());
  489. //row.getCell(col+2).setCellStyle(style);
  490. for (dk.i2m.converge.core.metadata.Concept c : concept.getNarrower()) {
  491. generateChildRows(overviewSheet, style, c, rowNumber++, indent + 1);
  492. }
  493. }
  494. }