1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.services.cms.folksonomy.impl;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.Comparator;
22 import java.util.HashMap;
23 import java.util.HashSet;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.Map.Entry;
28 import java.util.Set;
29 import java.util.TreeSet;
30
31 import javax.jcr.ItemExistsException;
32 import javax.jcr.ItemNotFoundException;
33 import javax.jcr.Node;
34 import javax.jcr.NodeIterator;
35 import javax.jcr.PathNotFoundException;
36 import javax.jcr.RepositoryException;
37 import javax.jcr.Session;
38 import javax.jcr.query.Query;
39 import javax.jcr.query.QueryManager;
40 import javax.jcr.query.QueryResult;
41
42 import org.apache.commons.lang.StringUtils;
43 import org.picocontainer.Startable;
44
45 import org.exoplatform.container.component.ComponentPlugin;
46 import org.exoplatform.container.xml.InitParams;
47 import org.exoplatform.services.cache.CacheService;
48 import org.exoplatform.services.cache.ExoCache;
49 import org.exoplatform.services.cms.folksonomy.NewFolksonomyService;
50 import org.exoplatform.services.cms.jcrext.activity.ActivityCommonService;
51 import org.exoplatform.services.cms.link.LinkManager;
52 import org.exoplatform.services.jcr.core.ManageableRepository;
53 import org.exoplatform.services.jcr.ext.app.SessionProviderService;
54 import org.exoplatform.services.jcr.ext.common.SessionProvider;
55 import org.exoplatform.services.jcr.ext.distribution.DataDistributionManager;
56 import org.exoplatform.services.jcr.ext.distribution.DataDistributionMode;
57 import org.exoplatform.services.jcr.ext.distribution.DataDistributionType;
58 import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
59 import org.exoplatform.services.listener.ListenerService;
60 import org.exoplatform.services.log.ExoLogger;
61 import org.exoplatform.services.log.Log;
62 import org.exoplatform.services.wcm.core.NodetypeConstant;
63 import org.exoplatform.services.wcm.utils.WCMCoreUtils;
64
65
66
67
68
69
70
71 public class NewFolksonomyServiceImpl implements NewFolksonomyService, Startable {
72
73 private static final String USER_FOLKSONOMY_ALIAS = "userPrivateFolksonomy";
74
75 private static final String GROUPS_ALIAS = "groupsPath";
76
77 private static final String TAG_STYLE_ALIAS = "exoTagStylePath";
78
79 private static final String PUBLIC_TAG_NODE_PATH = "exoPublicTagNode";
80
81 private static final String EXO_TRASH_FOLDER = "exo:trashFolder";
82
83 private static final String EXO_HIDDENABLE = "exo:hiddenable";
84
85 private static final String TAG_PERMISSION_LIST = "tagPermissionList";
86
87 private static final String CACHE_NAME = "ecms.FolksonomyService";
88
89 private static final Log LOG = ExoLogger.getLogger(NewFolksonomyServiceImpl.class.getName());
90
91 private NodeHierarchyCreator nodeHierarchyCreator;
92
93 private LinkManager linkManager;
94
95 private InitParams initParams_;
96
97 private List<TagStylePlugin> plugin_ = new ArrayList<TagStylePlugin>();
98
99 private List<TagPermissionPlugin> tagPermissionPlugin_ = new ArrayList<TagPermissionPlugin>();
100
101 private ExoCache<String, List<String>> tagPermissionList;
102
103 private Map<String, String> sitesTagPath = new HashMap<String, String>();
104
105 private ListenerService listenerService;
106
107 private ActivityCommonService activityService;
108
109
110 private DataDistributionType dataDistributionType;
111
112 public NewFolksonomyServiceImpl(InitParams initParams,
113 NodeHierarchyCreator nodeHierarchyCreator,
114 LinkManager linkManager,
115 DataDistributionManager dataDistributionManager,
116 SessionProviderService sessionProviderService,
117 CacheService cacheService) throws Exception {
118 this.nodeHierarchyCreator = nodeHierarchyCreator;
119 this.linkManager = linkManager;
120 this.initParams_ = initParams;
121 listenerService = WCMCoreUtils.getService(ListenerService.class);
122 this.activityService = WCMCoreUtils.getService(ActivityCommonService.class);
123 this.tagPermissionList = cacheService.getCacheInstance(CACHE_NAME);
124
125 if (initParams != null && initParams.getValueParam("tagDistributionMode") != null) {
126 String strTagDistributionMode = initParams.getValueParam("tagDistributionMode").getValue();
127 if ("none".equals(strTagDistributionMode)) {
128 dataDistributionType = dataDistributionManager.getDataDistributionType(DataDistributionMode.NONE);
129 } else if ("readable".equals(strTagDistributionMode)) {
130 dataDistributionType = dataDistributionManager.getDataDistributionType(DataDistributionMode.READABLE);
131 } else if ("optimized".equals(strTagDistributionMode)) {
132 dataDistributionType = dataDistributionManager.getDataDistributionType(DataDistributionMode.OPTIMIZED);
133 }
134 } else {
135 dataDistributionType = dataDistributionManager.getDataDistributionType(DataDistributionMode.READABLE);
136 }
137 }
138
139
140
141
142
143
144 public void start() {
145 try {
146 init();
147 } catch (Exception e) {
148 if (LOG.isErrorEnabled()) {
149 LOG.error("===>>>>Exception when init FolksonomySerice", e);
150 }
151 }
152 }
153
154
155
156
157 public void stop() {
158 tagPermissionList.clearCache();
159 }
160
161
162
163
164
165
166 public void addPrivateTag(String[] tagsName,
167 Node documentNode,
168 String workspace,
169 String userName) throws Exception {
170 Node userFolksonomyNode = getUserFolksonomyFolder(userName);
171 userFolksonomyNode.getSession().save();
172 Node targetNode = getTargetNode(documentNode);
173 boolean firstTagFlag = true;
174 StringBuffer tagValue = new StringBuffer();
175 for (String tag : tagsName) {
176 try {
177
178 Node tagNode = getTagNode(userFolksonomyNode, tag);
179
180 addTag(tagNode, targetNode);
181 userFolksonomyNode.getSession().save();
182 if (firstTagFlag) {
183 firstTagFlag = false;
184 tagValue.append(tag);
185 }else {
186 tagValue.append(",").append(tag);
187 }
188
189 } catch (Exception e) {
190 if (LOG.isErrorEnabled()) {
191 LOG.error("can't add tag '" + tag + "' to node: " + targetNode.getPath() + " for user: "
192 + userName);
193 }
194 }
195 }
196 broadcastActivityTag(documentNode, tagValue.toString());
197 }
198 private void broadcastActivityTag(Node documentNode, String tagValue ) {
199 if (listenerService!=null && activityService !=null) {
200 try {
201 if (activityService.isAcceptedNode(documentNode) ||
202 documentNode.getPrimaryNodeType().getName().equals(NodetypeConstant.NT_FILE)) {
203 listenerService.broadcast(ActivityCommonService.TAG_ADDED_ACTIVITY, documentNode, tagValue);
204 }
205 } catch (Exception e) {
206 if (LOG.isErrorEnabled()) {
207 LOG.error("Can not notify Tag Added Activity because of: " + e.getMessage());
208 }
209 }
210 }
211 }
212
213
214
215
216 public void addGroupsTag(String[] tagsName,
217 Node documentNode,
218 String workspace,
219 String[] roles) throws Exception {
220 Node targetNode = getTargetNode(documentNode);
221 for (String group : roles) {
222 Node groupFolksonomyNode = getGroupFolksonomyFolder(group, workspace);
223 for (String tag : tagsName) {
224 try {
225
226 Node tagNode = getTagNode(groupFolksonomyNode, tag);
227
228
229 addTag(tagNode, targetNode);
230
231 groupFolksonomyNode.getSession().save();
232 } catch (Exception e) {
233 if (LOG.isErrorEnabled()) {
234 LOG.error("can't add tag '" + tag + "' to node: " + targetNode.getPath() + " for group: "
235 + group);
236 }
237 }
238 }
239 }
240 }
241
242
243
244
245 public void addPublicTag(String treePath,
246 String[] tagsName,
247 Node documentNode,
248 String workspace) throws Exception {
249 Node publicFolksonomyTreeNode = getNode(workspace, treePath);
250 Node targetNode = getTargetNode(documentNode);
251 boolean firstTagFlag = true;
252 StringBuffer tagValue = new StringBuffer();
253
254 for (String tag : tagsName) {
255 try {
256
257 Node tagNode = getTagNode(publicFolksonomyTreeNode, tag);
258
259 addTag(tagNode, targetNode);
260 publicFolksonomyTreeNode.getSession().save();
261 if (firstTagFlag) {
262 firstTagFlag = false;
263 tagValue.append(tag);
264 }else {
265 tagValue.append(",").append(tag);
266 }
267 } catch (Exception e) {
268 if (LOG.isErrorEnabled()) {
269 LOG.error("can't add tag '" + tag + "' to node: " + targetNode.getPath()
270 + " in public folksonomy tree!");
271 }
272 }
273 }
274 broadcastActivityTag(documentNode, tagValue.toString());
275 }
276
277 private Node getTargetNode(Node showingNode) throws Exception {
278 Node targetNode = null;
279 if (linkManager.isLink(showingNode)) {
280 try {
281 targetNode = linkManager.getTarget(showingNode);
282 } catch (ItemNotFoundException e) {
283 targetNode = showingNode;
284 }
285 } else {
286 targetNode = showingNode;
287 }
288 return targetNode;
289 }
290
291
292
293
294 public void addSiteTag(String siteName,
295 String[] tagsName,
296 Node node,
297 String workspace) throws Exception {
298 if (sitesTagPath.get(getRepoName()) == null) {
299 createSiteTagPath();
300 }
301 addPublicTag(sitesTagPath.get(getRepoName()) + "/" + siteName,
302 tagsName,
303 node,
304 workspace);
305 }
306
307
308
309
310 @Override
311 public List<Node> getAllDocumentsByTagsAndPath(String selectedPath,
312 Set<String> tagPaths,
313 String workspace,
314 SessionProvider sessionProvider) throws Exception {
315 if (StringUtils.isBlank(selectedPath)) {
316 throw new IllegalArgumentException("Parent path is empty");
317 }
318 if (tagPaths == null || tagPaths.isEmpty()) {
319 throw new IllegalArgumentException("Tags is empty");
320 }
321
322
323 String selectedParentPath = selectedPath;
324 if (selectedPath.endsWith("/")) {
325 selectedPath = selectedPath.substring(0, selectedPath.length() - 1);
326 } else {
327 selectedParentPath += "/";
328 }
329
330 List<Node> ret = new ArrayList<Node>();
331 Set<String> nodesPaths = new HashSet<>();
332 boolean firstSearch = true;
333 Iterator<String> tagPathsIterator = tagPaths.iterator();
334 while (tagPathsIterator.hasNext()) {
335 String tagPath = (String) tagPathsIterator.next();
336 Node tagNode = getNode(workspace, tagPath, sessionProvider);
337 if (tagNode == null) {
338 tagPathsIterator.remove();
339 continue;
340 }
341 NodeIterator nodeIter = tagNode.getNodes();
342
343 Set<String> singleTagNodesPaths = new HashSet<>();
344 while (nodeIter.hasNext()) {
345 Node node = nodeIter.nextNode();
346 if (linkManager.isLink(node)) {
347 Node targetNode = null;
348 try {
349 targetNode = linkManager.getTarget(node);
350 } catch (Exception e) {
351 if (LOG.isWarnEnabled()) {
352 LOG.warn(e.getMessage());
353 }
354 }
355 if (targetNode != null && !((Node) targetNode.getAncestor(1)).isNodeType(EXO_TRASH_FOLDER)
356 && targetNode.getSession().getWorkspace().getName().equals(workspace)
357 && (targetNode.getPath().equals(selectedPath) || targetNode.getPath().startsWith(selectedParentPath))) {
358 if (firstSearch) {
359 ret.add(targetNode);
360 }
361 singleTagNodesPaths.add(targetNode.getPath());
362 }
363 }
364 }
365 if (firstSearch) {
366 nodesPaths.addAll(singleTagNodesPaths);
367 } else {
368 nodesPaths.retainAll(singleTagNodesPaths);
369 }
370 firstSearch = false;
371 }
372 Iterator<Node> nodesIterator = ret.iterator();
373 while (nodesIterator.hasNext()) {
374 Node node = nodesIterator.next();
375 if (!nodesPaths.contains(node.getPath())) {
376 nodesIterator.remove();
377 }
378 }
379 return ret;
380 }
381
382
383
384
385 public List<Node> getAllDocumentsByTag(String tagPath,
386 String workspace,
387 SessionProvider sessionProvider) throws Exception {
388 List<Node> ret = new ArrayList<Node>();
389 Node tagNode = getNode(workspace, tagPath, sessionProvider);
390 if (tagNode == null) {
391 return Collections.emptyList();
392 }
393 NodeIterator nodeIter = tagNode.getNodes();
394
395 while (nodeIter.hasNext()) {
396 Node node = nodeIter.nextNode();
397 if (linkManager.isLink(node)) {
398 Node targetNode = null;
399 try {
400 targetNode = linkManager.getTarget(node);
401 } catch (Exception e) {
402 if (LOG.isWarnEnabled()) {
403 LOG.warn(e.getMessage());
404 }
405 }
406 if (targetNode != null && !((Node) targetNode.getAncestor(1)).isNodeType(EXO_TRASH_FOLDER)) {
407 ret.add(targetNode);
408 }
409 }
410 }
411 return ret;
412 }
413
414
415
416
417 public List<Node> getAllGroupTags(String[] roles, String workspace) throws Exception {
418 Set<Node> tagSet = new TreeSet<Node>(new NodeComparator());
419 for (String group : roles) {
420 Node groupFolksonomyNode = getGroupFolksonomyFolder(group, workspace);
421 List<Node> tagNodes = queryTagNodes(groupFolksonomyNode);
422 for(Node tag : tagNodes) {
423 if (!((Node) tag.getAncestor(1)).isNodeType(EXO_TRASH_FOLDER)) {
424 tagSet.add(tag);
425 }
426 }
427 }
428 return new ArrayList<Node>(tagSet);
429 }
430
431 private List<Node> queryTagNodes(Node rootNode) throws Exception {
432 List<Node> ret = new ArrayList<Node>();
433 StringBuilder queryStr = new StringBuilder().append("select * from ").append(EXO_TAGGED).append(" where jcr:path like '").
434 append(rootNode.getPath()).append("/%'");
435 Query query = rootNode.getSession().getWorkspace().getQueryManager().createQuery(queryStr.toString(), Query.SQL);
436 for (NodeIterator iter = query.execute().getNodes(); iter.hasNext();) {
437 ret.add(iter.nextNode());
438 }
439 Collections.sort(ret, new NodeComparator());
440 return ret;
441 }
442
443
444
445
446 public List<Node> getAllGroupTags(String role, String workspace) throws Exception {
447 List<Node> tagSet = new ArrayList<Node>();
448 Node groupFolksonomyNode = getGroupFolksonomyFolder(role, workspace);
449 for (Node tagNode : queryTagNodes(groupFolksonomyNode)) {
450 tagSet.add(tagNode);
451 }
452 return tagSet;
453 }
454
455
456
457
458 public List<Node> getAllPrivateTags(String userName) throws Exception {
459 Node userFolksonomyNode = getUserFolksonomyFolder(userName);
460 if (userFolksonomyNode == null) {
461 return Collections.emptyList();
462 }
463 return queryTagNodes(userFolksonomyNode);
464 }
465
466
467
468
469 public List<Node> getAllPublicTags(String treePath, String workspace) throws Exception {
470 Node publicFolksonomyTreeNode = getNode(workspace, treePath);
471 return queryTagNodes(publicFolksonomyTreeNode);
472 }
473
474
475
476
477 public List<Node> getAllSiteTags(String siteName, String workspace) throws Exception {
478 if (sitesTagPath.get(getRepoName()) == null) {
479 createSiteTagPath();
480 }
481 return getAllPublicTags(sitesTagPath.get(getRepoName()) + "/" + siteName, workspace);
482 }
483
484 private String getRepoName() {
485 try {
486 String repositoryName = WCMCoreUtils.getRepository().getConfiguration().getName();
487 if (LOG.isDebugEnabled()) {
488 LOG.debug("The repository name is: " + repositoryName);
489 }
490 return repositoryName;
491 } catch (NullPointerException e) {
492 String repositoryName = System.getProperty("gatein.tenant.repository.name");
493 if (repositoryName != null) {
494 return repositoryName;
495 }
496 if (LOG.isErrorEnabled()) {
497 LOG.error("Repository exception occurs:", e);
498 }
499 return null;
500 }
501 }
502
503
504
505
506 public List<Node> getAllTagStyle(String workspace) throws Exception {
507 String tagStylesPath = nodeHierarchyCreator.getJcrPath(TAG_STYLE_ALIAS);
508 Node tagStylesNode = getNode(workspace, tagStylesPath);
509 return getChildNodes(tagStylesNode);
510 }
511
512
513
514
515 public String getTagStyle(String tagStylePath, String workspace) throws Exception {
516 Node tagStyleNode = getNode(workspace, tagStylePath);
517 return tagStyleNode.getProperty(HTML_STYLE_PROP).getString();
518 }
519
520
521
522
523
524
525 public void addTagStylePlugin(ComponentPlugin plugin) {
526 if (plugin instanceof TagStylePlugin) {
527 plugin_.add((TagStylePlugin) plugin);
528 }
529 }
530
531
532
533
534
535
536 public void init() throws Exception {
537 for (TagStylePlugin plugin : plugin_) {
538 try {
539 plugin.init();
540 } catch (Exception e) {
541 if (LOG.isErrorEnabled()) {
542 LOG.error("can not init tag style: ", e);
543 }
544 }
545 }
546 initTagPermissionListCache();
547 }
548
549
550
551
552
553 public void initTagPermissionListCache() throws Exception {
554 List<String> _tagPermissionList = new ArrayList<String>();
555 for (TagPermissionPlugin plugin : tagPermissionPlugin_) {
556 try {
557 _tagPermissionList.addAll(plugin.initPermission());
558 } catch (Exception e) {
559 if (LOG.isErrorEnabled()) {
560 LOG.error("can not init tag permission: ", e);
561 }
562 }
563 }
564 tagPermissionList.clearCache();
565 tagPermissionList.put(TAG_PERMISSION_LIST, _tagPermissionList);
566 }
567
568
569
570
571 @Deprecated
572 public Node modifyTagName(String tagPath, String newTagName, String workspace) throws Exception {
573 Node oldTagNode = getNode(workspace, tagPath);
574 if (oldTagNode.getParent().hasNode(newTagName))
575 throw new ItemExistsException("node " + newTagName + " has already existed!");
576
577 StringBuilder newPath = new StringBuilder(oldTagNode.getParent().getPath()).append('/')
578 .append(newTagName);
579
580 ManageableRepository manageableRepository = WCMCoreUtils.getRepository();
581
582 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
583 Session session = sessionProvider.getSession(workspace, manageableRepository);
584 session.move(tagPath, newPath.toString());
585 session.save();
586 return getNode(workspace, newPath.toString());
587 }
588
589
590
591
592 public Node modifyPublicTagName(String tagPath, String newTagName, String workspace, String treePath) throws Exception {
593 Node oldTagNode = getNode(workspace, tagPath);
594 Node publicFolksonomyTreeNode = getNode(workspace, treePath);
595 Node newTagNode = null;
596 try {
597 newTagNode = dataDistributionType.getDataNode(publicFolksonomyTreeNode, newTagName);
598 throw new ItemExistsException("node " + newTagName + " has already existed!");
599 } catch (PathNotFoundException e) {
600
601 newTagNode = dataDistributionType.getOrCreateDataNode(publicFolksonomyTreeNode, newTagName);
602 }
603 newTagNode.addMixin(EXO_TAGGED);
604 if (oldTagNode.hasProperty(EXO_TOTAL)) {
605 newTagNode.setProperty(EXO_TOTAL, oldTagNode.getProperty(EXO_TOTAL).getValue());
606 }
607
608 Map<String, String> pathMap = new HashMap<String, String>();
609 for (NodeIterator iter = oldTagNode.getNodes(); iter.hasNext();) {
610 Node node = iter.nextNode();
611 pathMap.put(node.getPath(), newTagNode.getPath() + "/" + node.getName());
612 }
613
614 Session session = newTagNode.getSession();
615 for (Entry<String, String> entry : pathMap.entrySet()) {
616 session.move(entry.getKey(), entry.getValue());
617 }
618 oldTagNode.remove();
619 session.save();
620 return newTagNode;
621 }
622
623
624
625
626
627 public void removeTag(String tagPath, String workspace) throws Exception {
628 Node tagNode = getNode(workspace, tagPath);
629 NodeIterator nodeIterator = tagNode.getNodes();
630 Exception e = null;
631 if (nodeIterator.hasNext()) {
632 while (nodeIterator.hasNext()) {
633 try {
634 Node document = linkManager.getTarget(nodeIterator.nextNode());
635 removeTagOfDocument(tagPath, document, workspace);
636 }catch(Exception exception){
637 if(e!=null) {
638 e.addSuppressed(exception);
639 }else{
640 e = exception;
641 }
642 }
643 }
644 } else {
645 tagNode.remove();
646 tagNode.getSession().save();
647 }
648 if(e!=null) throw e;
649 }
650
651
652
653
654 public void removeTagOfDocument(String tagPath, Node document, String workspace) throws Exception {
655 Node tagNode = getNode(workspace, tagPath);
656 NodeIterator nodeIter = tagNode.getNodes();
657 StringBuffer removedTags = new StringBuffer();
658 String tagName ;
659 boolean isFirstFlag = true;
660 while (nodeIter.hasNext()) {
661 Node link = nodeIter.nextNode();
662 if (linkManager.isLink(link)) {
663 Node targetNode = null;
664 try {
665 targetNode = linkManager.getTarget(link);
666 } catch (RepositoryException e) {
667 if (LOG.isWarnEnabled()) {
668 LOG.warn(e.getMessage());
669 }
670 }
671 if (document.isSame(targetNode)) {
672 tagName = tagNode.getName();
673 if (isFirstFlag) {
674 removedTags.append(tagName);
675 isFirstFlag = false;
676 }else {
677 removedTags.append(ActivityCommonService.VALUE_SEPERATOR).append(tagName);
678 }
679 link.remove();
680
681 long total = tagNode.getProperty(EXO_TOTAL).getLong();
682 tagNode.setProperty(EXO_TOTAL, total - 1);
683 Node parentNode = tagNode.getParent();
684 if (tagNode.getProperty(EXO_TOTAL).getLong() == 0L)
685 tagNode.remove();
686 parentNode.getSession().save();
687 break;
688 }
689 }
690 }
691 if (listenerService!=null && activityService!=null) {
692 try {
693 if (activityService.isAcceptedNode(document) || (document.getPrimaryNodeType().getName().equals(NodetypeConstant.NT_FILE)
694 && activityService.isBroadcastNTFileEvents(document))) {
695 listenerService.broadcast(ActivityCommonService.TAG_REMOVED_ACTIVITY, document, removedTags.toString());
696 }
697 } catch (Exception e) {
698 if (LOG.isErrorEnabled()) {
699 LOG.error("Can not notify RemoveTag Activity because of: " + e.getMessage());
700 }
701 }
702 }
703 }
704
705
706
707
708 public void updateTagStyle(String styleName, String tagRange, String htmlStyle, String workspace) throws Exception {
709 String tagStylesPath = nodeHierarchyCreator.getJcrPath(TAG_STYLE_ALIAS);
710 Node tagStylesNode = getNode(workspace, tagStylesPath);
711 Node styleNode = tagStylesNode.getNode(styleName);
712 styleNode.setProperty(TAG_RATE_PROP, tagRange);
713 styleNode.setProperty(HTML_STYLE_PROP, htmlStyle);
714 tagStylesNode.getSession().save();
715 }
716
717
718
719
720 public void addTagStyle(String styleName, String tagRange, String htmlStyle, String workspace) throws Exception {
721 String tagStylesPath = nodeHierarchyCreator.getJcrPath(TAG_STYLE_ALIAS);
722 Node tagStylesNode = getNode(workspace, tagStylesPath);
723 Node styleNode = tagStylesNode.addNode(styleName, EXO_TAGSTYLE);
724 styleNode.addMixin("exo:privilegeable");
725 styleNode.setProperty(TAG_RATE_PROP, tagRange);
726 styleNode.setProperty(HTML_STYLE_PROP, htmlStyle);
727 tagStylesNode.getSession().save();
728 }
729
730
731
732
733 public void removeTagsOfNodeRecursively(Node node,
734 String workspace,
735 String username,
736 String groups) throws Exception {
737 int[] scopes = new int[] { PRIVATE, PUBLIC, GROUP, SITE };
738 Map<Integer, String> map = new HashMap<Integer, String>();
739 map.put(PUBLIC, "");
740 map.put(PRIVATE, username);
741 map.put(GROUP, groups);
742 map.put(SITE, "");
743 for (int scope : scopes) {
744 for (Node child : getAllNodes(node)) {
745 List<Node> tags = getLinkedTagsOfDocumentByScope(scope, map.get(scope), child, workspace);
746 for (Node tag : tags)
747 removeTagOfDocument(tag.getPath(), child, workspace);
748 }
749 }
750 }
751
752 private List<Node> getAllNodes(Node node) throws Exception {
753 List<Node> ret = new ArrayList<Node>();
754 getAllNodes(node, ret);
755 return ret;
756 }
757
758 private void getAllNodes(Node node, List<Node> list) throws Exception {
759 list.add(node);
760 for (NodeIterator iter = node.getNodes(); iter.hasNext();) {
761 getAllNodes(iter.nextNode(), list);
762 }
763 }
764
765 private List<Node> getChildNodes(Node node) throws Exception {
766 List<Node> ret = new ArrayList<Node>();
767 NodeIterator nodeIter = node.getNodes();
768 while (nodeIter.hasNext()) {
769 ret.add(nodeIter.nextNode());
770 }
771 Collections.sort(ret, new NodeComparator());
772 return ret;
773 }
774
775 private Node getGroupFolksonomyFolder(String group, String workspace) throws Exception {
776 String groupsPath = nodeHierarchyCreator.getJcrPath(GROUPS_ALIAS);
777 String folksonomyPath = "ApplicationData/Tags";
778 Node groupsNode = getNode(workspace, groupsPath);
779 return groupsNode.getNode(group.substring(1)).getNode(folksonomyPath);
780 }
781
782 private Node getUserFolksonomyFolder(String userName) throws Exception {
783
784 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
785 Node userNode = nodeHierarchyCreator.getUserNode(sessionProvider, userName);
786 String folksonomyPath = nodeHierarchyCreator.getJcrPath(USER_FOLKSONOMY_ALIAS);
787 if (folksonomyPath == null || !userNode.hasNode(folksonomyPath)) {
788 return null;
789 }
790 return userNode.getNode(folksonomyPath);
791 }
792
793 private Node getNode(String workspace, String path) throws Exception {
794 return getNode(workspace, path, WCMCoreUtils.getSystemSessionProvider());
795 }
796
797 private Node getNode(String workspace, String path, SessionProvider sessionProvider) throws Exception {
798 ManageableRepository manageableRepository = WCMCoreUtils.getRepository();
799 Session session = sessionProvider.getSession(workspace, manageableRepository);
800
801 return session.itemExists(path) ? ((Node) session.getItem(path)) : null;
802 }
803
804 private boolean existSymlink(Node parentNode, Node targetNode) throws Exception {
805 NodeIterator nodeIter = parentNode.getNodes();
806 while (nodeIter.hasNext()) {
807 Node link = nodeIter.nextNode();
808 Node pointTo = null;
809 try {
810 if (linkManager.isLink(link))
811 pointTo = linkManager.getTarget(link, true);
812 } catch (ItemNotFoundException e) {
813 continue;
814 } catch (Exception e) {
815 if (LOG.isWarnEnabled()) {
816 LOG.warn(e.getMessage());
817 }
818 }
819 if (targetNode != null && targetNode.isSame(pointTo))
820 return true;
821 }
822 return false;
823 }
824
825 private static class NodeComparator implements Comparator<Node> {
826 public int compare(Node o1, Node o2) {
827 try {
828 if (o1.isSame(o2))
829 return 0;
830 int pathComparison = o1.getPath().compareTo(o2.getPath());
831 return (pathComparison == 0) ? 1 : pathComparison;
832 } catch (RepositoryException e) {
833 return 1;
834 }
835 }
836 }
837
838 public List<Node> getLinkedTagsOfDocument(Node documentNode, String workspace) throws Exception {
839
840 Set<Node> ret = new HashSet<Node>();
841
842 StringBuilder queryStr = new StringBuilder("SELECT * FROM ").append(EXO_TAGGED);
843 ManageableRepository manageableRepository = WCMCoreUtils.getRepository();
844
845 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
846 QueryManager queryManager = sessionProvider.getSession(workspace, manageableRepository)
847 .getWorkspace()
848 .getQueryManager();
849 Query query = queryManager.createQuery(queryStr.toString(), Query.SQL);
850 QueryResult queryResult = query.execute();
851 NodeIterator nodeIter = queryResult.getNodes();
852 while (nodeIter.hasNext()) {
853 Node tagNode = nodeIter.nextNode();
854 if (existSymlink(tagNode, documentNode))
855 ret.add(tagNode);
856 }
857 return new ArrayList<Node>(ret);
858 }
859
860 public List<Node> getLinkedTagsOfDocumentByScope(int scope,
861 String value,
862 Node documentNode,
863 String workspace) throws Exception {
864
865 List<Node> ret = new ArrayList<Node>();
866 if (scope == PRIVATE) {
867 Node userFolksonomyNode = getUserFolksonomyFolder(value);
868 for (Node tagNode : queryTagNodes(userFolksonomyNode)) {
869 if (existSymlink(tagNode, documentNode))
870 ret.add(tagNode);
871 }
872 }
873
874 else if (scope == PUBLIC) {
875 String publicTagNodePath = nodeHierarchyCreator.getJcrPath(PUBLIC_TAG_NODE_PATH);
876 Node publicFolksonomyTreeNode = getNode(workspace, publicTagNodePath);
877 for (Node tagNode : queryTagNodes(publicFolksonomyTreeNode)) {
878 if (existSymlink(tagNode, documentNode))
879 ret.add(tagNode);
880 }
881 }
882
883 else if (scope == GROUP) {
884 String[] roles = value.split(";");
885 for (String group : roles) {
886 if (group.length() < 1)
887 continue;
888 Node groupFolksonomyNode = getGroupFolksonomyFolder(group, workspace);
889 for (Node tagNode : queryTagNodes(groupFolksonomyNode)) {
890 if (existSymlink(tagNode, documentNode))
891 ret.add(tagNode);
892 }
893 }
894 }
895 Collections.sort(ret, new NodeComparator());
896 return ret;
897 }
898
899
900
901
902
903
904 public void addTagPermissionPlugin(ComponentPlugin plugin) {
905 if (plugin instanceof TagPermissionPlugin)
906 tagPermissionPlugin_.add((TagPermissionPlugin) plugin);
907 }
908
909
910
911
912 public void addTagPermission(String usersOrGroups) {
913 List<String> _tagPermissionList = tagPermissionList.get(TAG_PERMISSION_LIST);
914 if (_tagPermissionList!=null && !_tagPermissionList.contains(usersOrGroups)) {
915 _tagPermissionList.add(usersOrGroups);
916 tagPermissionList.put(TAG_PERMISSION_LIST, _tagPermissionList);
917 } else if (_tagPermissionList == null) {
918 _tagPermissionList = new ArrayList<String>();
919 _tagPermissionList.add(usersOrGroups);
920 tagPermissionList.put(TAG_PERMISSION_LIST, _tagPermissionList);
921 }
922 }
923
924
925
926
927 public void removeTagPermission(String usersOrGroups) {
928 List<String> _tagPermissionList = tagPermissionList.get(TAG_PERMISSION_LIST);
929 if(_tagPermissionList!=null && _tagPermissionList.contains(usersOrGroups)) {
930 _tagPermissionList.remove(usersOrGroups);
931 tagPermissionList.put(TAG_PERMISSION_LIST, _tagPermissionList);
932 }
933 }
934
935
936
937
938 public List<String> getTagPermissionList() {
939 return tagPermissionList.get(TAG_PERMISSION_LIST);
940 }
941
942
943
944
945 public boolean canEditTag(int scope, List<String> memberships) {
946 if (scope == PUBLIC) {
947 List<String> _tagPermissionList = tagPermissionList.get(TAG_PERMISSION_LIST);
948 if (_tagPermissionList == null || _tagPermissionList.size() == 0) {
949 return false;
950 }
951 for (String membership : memberships) {
952 if (_tagPermissionList.contains(membership))
953 return true;
954 if (membership.contains(":")) {
955 if (_tagPermissionList.contains("*" + membership.substring(membership.indexOf(":"))))
956 return true;
957 }
958 }
959 return false;
960 }
961 return true;
962 }
963
964
965
966
967 public List<String> getAllTagNames(String workspace, int scope, String value) throws Exception {
968 List<String> ret = new ArrayList<String>();
969 List<Node> tags = new ArrayList<Node>();
970 switch (scope) {
971 case PUBLIC:
972 tags = getAllPublicTags(value, workspace);
973 break;
974 case PRIVATE:
975 tags = getAllPrivateTags(value);
976 break;
977 case GROUP:
978 tags = value.indexOf(";") >= 0 ? getAllGroupTags(value.split(";"), workspace)
979 : getAllGroupTags(value, workspace);
980 break;
981 case SITE:
982 tags = getAllSiteTags(value, workspace);
983 }
984 for (Node tag : tags)
985 ret.add(tag.getName());
986 Collections.sort(ret);
987 return ret;
988 }
989
990 private void createSiteTagPath() throws Exception {
991 if (sitesTagPath.get(getRepoName()) == null) {
992
993 ManageableRepository manageableRepository = WCMCoreUtils.getRepository();
994
995 SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
996 Session session = sessionProvider.getSession(initParams_.getValueParam("workspace")
997 .getValue(), manageableRepository);
998
999 String[] paths = initParams_.getValueParam("path").getValue().split("/");
1000 Node currentNode = session.getRootNode();
1001 int depth = 0;
1002 for (String path : paths) {
1003 if (path.length() > 0) {
1004 Node cnode = currentNode.hasNode(path) ? currentNode.getNode(path)
1005 : currentNode.addNode(path);
1006 currentNode = cnode;
1007 if (depth++ == 0)
1008 if (!currentNode.isNodeType(EXO_HIDDENABLE))
1009 currentNode.addMixin(EXO_HIDDENABLE);
1010 }
1011 }
1012 session.save();
1013 sitesTagPath.put(getRepoName(), currentNode.getPath());
1014 }
1015 }
1016
1017 private Node getTagNode(Node folksonomyHome, String tagName) throws Exception {
1018 Node tagNode = dataDistributionType.getOrCreateDataNode(folksonomyHome, tagName);
1019 if (!tagNode.isNodeType(EXO_TAGGED)) {
1020 tagNode.addMixin(EXO_TAGGED);
1021 tagNode.setProperty(EXO_TOTAL, 0);
1022 }
1023 return tagNode;
1024 }
1025
1026 private void addTag(Node tagNode, Node targetNode) throws Exception {
1027 if (!existSymlink(tagNode, targetNode)) {
1028 linkManager.createLink(tagNode, targetNode);
1029 long total = tagNode.getProperty(EXO_TOTAL).getLong();
1030 tagNode.setProperty(EXO_TOTAL, total + 1);
1031 }
1032 }
1033
1034
1035
1036
1037 public DataDistributionType getDataDistributionType() {
1038 return this.dataDistributionType;
1039 }
1040
1041 }