001/* 002 * Copyright 2012 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.tag.jcr; 017 018import java.util.Collections; 019import java.util.HashSet; 020import java.util.Set; 021 022import javax.jcr.Node; 023import javax.jcr.PathNotFoundException; 024import javax.jcr.RepositoryException; 025import javax.jcr.Value; 026import javax.jcr.ValueFactory; 027 028import org.ametys.plugins.repository.AmetysRepositoryException; 029import org.ametys.plugins.repository.RepositoryConstants; 030import org.ametys.plugins.repository.jcr.DefaultAmetysObject; 031import org.ametys.plugins.repository.jcr.JCRAmetysObject; 032 033/** 034 * Helper class which provides methods to manage tags on {@link JCRAmetysObject}s. 035 */ 036public final class TaggableAmetysObjectHelper 037{ 038 /** Constant for tags metadata. */ 039 public static final String DEFAULT_METADATA_TAGS = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":tags"; 040 041 private TaggableAmetysObjectHelper() 042 { 043 // Hide the default constructor. 044 } 045 046 /** 047 * Retrieve the tags of a {@link JCRAmetysObject}. 048 * @param object the {@link JCRAmetysObject} to tag. 049 * @return the object tags. 050 * @throws AmetysRepositoryException if failed to tag Ametys object 051 */ 052 public static Set<String> getTags(JCRAmetysObject object) throws AmetysRepositoryException 053 { 054 return getTags(object, DEFAULT_METADATA_TAGS); 055 } 056 057 /** 058 * Retrieve the tags of a {@link JCRAmetysObject}. 059 * @param object the {@link JCRAmetysObject} to tag. 060 * @param metadataName The name of the metadata holding the tags 061 * @return the object tags. 062 * @throws AmetysRepositoryException if failed to tag Ametys object 063 */ 064 public static Set<String> getTags(JCRAmetysObject object, String metadataName) throws AmetysRepositoryException 065 { 066 try 067 { 068 Node node = getNode(object); 069 Value[] values = node.getProperty(metadataName).getValues(); 070 Set<String> tags = new HashSet<>(values.length); 071 072 for (Value value : values) 073 { 074 tags.add(value.getString()); 075 } 076 077 return tags; 078 } 079 catch (PathNotFoundException e) 080 { 081 return Collections.emptySet(); 082 } 083 catch (RepositoryException e) 084 { 085 throw new AmetysRepositoryException("Unable to get tags property " + metadataName, e); 086 } 087 } 088 089 /** 090 * Tag a {@link JCRAmetysObject}. 091 * @param object the {@link JCRAmetysObject} to tag. 092 * @param tag the tag to put on the object. 093 * @throws AmetysRepositoryException if an error occurs. 094 */ 095 public static void tag(JCRAmetysObject object, String tag) throws AmetysRepositoryException 096 { 097 tag(object, tag, DEFAULT_METADATA_TAGS); 098 } 099 100 /** 101 * Tag a {@link JCRAmetysObject}. 102 * @param object the {@link JCRAmetysObject} to tag. 103 * @param tag the tag to put on the object. 104 * @param metadataName The name of the metadata holding the tags 105 * @throws AmetysRepositoryException if an error occurs. 106 */ 107 public static void tag(JCRAmetysObject object, String tag, String metadataName) throws AmetysRepositoryException 108 { 109 try 110 { 111 Node node = getNode(object); 112 Value[] values = new Value[0]; 113 114 if (node.hasProperty(metadataName)) 115 { 116 values = node.getProperty(metadataName).getValues(); 117 } 118 119 Set<String> tags = new HashSet<>(values.length + 1); 120 121 for (Value value : values) 122 { 123 tags.add(value.getString()); 124 } 125 126 if (tags.add(tag)) 127 { 128 ValueFactory valueFactory = node.getSession().getValueFactory(); 129 Set<Value> newValues = new HashSet<>(tags.size()); 130 131 for (String currentTag : tags) 132 { 133 newValues.add(valueFactory.createValue(currentTag)); 134 } 135 136 node.setProperty(metadataName, newValues.toArray(new Value[newValues.size()])); 137 } 138 } 139 catch (RepositoryException e) 140 { 141 throw new AmetysRepositoryException("Unable to set tags property", e); 142 } 143 } 144 145 /** 146 * Remove a tag on a {@link JCRAmetysObject}. 147 * @param object the {@link JCRAmetysObject} to tag. 148 * @param tag the tag to remove on the object. 149 * @throws AmetysRepositoryException if an error occurs. 150 */ 151 public static void untag(JCRAmetysObject object, String tag) throws AmetysRepositoryException 152 { 153 untag(object, tag, DEFAULT_METADATA_TAGS); 154 } 155 156 /** 157 * Remove a tag on a {@link JCRAmetysObject}. 158 * @param object the {@link JCRAmetysObject} to tag. 159 * @param tag the tag to remove on the object. 160 * @param metadataName The name of the metadata holding the tags 161 * @throws AmetysRepositoryException if an error occurs. 162 */ 163 public static void untag(JCRAmetysObject object, String tag, String metadataName) throws AmetysRepositoryException 164 { 165 try 166 { 167 Node node = getNode(object); 168 Value[] values = new Value[0]; 169 170 if (node.hasProperty(metadataName)) 171 { 172 values = node.getProperty(metadataName).getValues(); 173 } 174 175 Set<String> tags = new HashSet<>(values.length + 1); 176 177 for (Value value : values) 178 { 179 tags.add(value.getString()); 180 } 181 182 if (tags.remove(tag)) 183 { 184 ValueFactory valueFactory = node.getSession().getValueFactory(); 185 Set<Value> newValues = new HashSet<>(tags.size()); 186 187 for (String currentTag : tags) 188 { 189 newValues.add(valueFactory.createValue(currentTag)); 190 } 191 192 node.setProperty(metadataName, newValues.toArray(new Value[newValues.size()])); 193 } 194 } 195 catch (RepositoryException e) 196 { 197 throw new AmetysRepositoryException("Unable to set tags property", e); 198 } 199 } 200 201 /** 202 * Get an object's base node. 203 * @param object the object which node to get. 204 * @return the object's base node. 205 */ 206 protected static Node getNode(JCRAmetysObject object) 207 { 208 Node node = null; 209 210 if (object instanceof DefaultAmetysObject) 211 { 212 node = ((DefaultAmetysObject) object).getBaseNode(); 213 } 214 else 215 { 216 node = object.getNode(); 217 } 218 219 return node; 220 } 221 222}