001/* 002 * Copyright 2010 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.plugins.repository.metadata.jcr; 017 018import javax.jcr.Node; 019import javax.jcr.RepositoryException; 020import javax.jcr.lock.Lock; 021import javax.jcr.lock.LockManager; 022 023import org.apache.commons.lang3.ArrayUtils; 024 025import org.ametys.plugins.repository.AmetysObjectResolver; 026import org.ametys.plugins.repository.AmetysRepositoryException; 027import org.ametys.plugins.repository.RepositoryConstants; 028import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata; 029import org.ametys.plugins.repository.metadata.ModifiableFolder; 030import org.ametys.plugins.repository.metadata.ModifiableRichText; 031import org.ametys.plugins.repository.metadata.RichText; 032import org.ametys.plugins.repository.metadata.UnknownMetadataException; 033 034/** 035 * JCR implementation of a {@link RichText}, based on the ametys:richText nodetype.<br> 036 */ 037public class JCRRichText extends JCRResource implements ModifiableRichText 038{ 039 040 /** The annotations node name. */ 041 private static final String _ANNOTATIONS_NODE_NAME = "annotations"; 042 043 private Node _rootDataNode; 044 private AmetysObjectResolver _resolver; 045 private boolean _lockAlreadyChecked; 046 047 /** 048 * Constructor 049 * @param node the JCR Node backing this {@link JCRRichText} 050 * @param resolver The resolver, used to resolve object collections. 051 * @throws AmetysRepositoryException if an error occurs 052 */ 053 public JCRRichText(Node node, AmetysObjectResolver resolver) throws AmetysRepositoryException 054 { 055 super(node); 056 057 _resolver = resolver; 058 059 try 060 { 061 _rootDataNode = node.getNode("data"); 062 } 063 catch (RepositoryException e) 064 { 065 throw new AmetysRepositoryException(e); 066 } 067 } 068 069 public ModifiableFolder getAdditionalDataFolder() 070 { 071 return new JCRFolder(_rootDataNode); 072 } 073 074 @Override 075 public String[] getAnnotationNames() throws AmetysRepositoryException 076 { 077 try 078 { 079 ModifiableCompositeMetadata annotations = getAnnotationsNode(false); 080 081 return annotations.getMetadataNames(); 082 } 083 catch (UnknownMetadataException e) 084 { 085 // Ignore, just return an empty array. 086 } 087 088 return new String[0]; 089 } 090 091 @Override 092 public String[] getAnnotationValues(String name) throws AmetysRepositoryException 093 { 094 try 095 { 096 ModifiableCompositeMetadata annotations = getAnnotationsNode(false); 097 if (annotations.hasMetadata(name)) 098 { 099 return annotations.getStringArray(name); 100 } 101 } 102 catch (UnknownMetadataException e) 103 { 104 // Ignore, just return an empty array. 105 } 106 107 return new String[0]; 108 } 109 110 @Override 111 public void addAnnotation(String name, String value) throws AmetysRepositoryException 112 { 113 String[] currentValues = getAnnotationValues(name); 114 getAnnotationsNode(true).setMetadata(name, ArrayUtils.add(currentValues, value)); 115 } 116 117 @Override 118 public void addAnnotation(String name, String[] values) throws AmetysRepositoryException 119 { 120 String[] currentValues = getAnnotationValues(name); 121 getAnnotationsNode(true).setMetadata(name, ArrayUtils.addAll(currentValues, values)); 122 } 123 124 @Override 125 public void removeAnnotations() throws AmetysRepositoryException 126 { 127 try 128 { 129 _checkLock(); 130 if (getNode().hasNode(_ANNOTATIONS_NODE_NAME)) 131 { 132 getNode().getNode(_ANNOTATIONS_NODE_NAME).remove(); 133 } 134 } 135 catch (RepositoryException e) 136 { 137 throw new AmetysRepositoryException(e); 138 } 139 } 140 141 @Override 142 public void removeAnnotation(String name) throws AmetysRepositoryException 143 { 144 ModifiableCompositeMetadata annotations = getAnnotationsNode(true); 145 if (annotations.hasMetadata(name)) 146 { 147 annotations.removeMetadata(name); 148 } 149 } 150 151 /** 152 * Get the annotations container node. 153 * @param createNew <code>true</code> to create the node if it doesn't exist, <code>false</code> otherwise. 154 * @return The annotation container node. 155 * @throws UnknownMetadataException If the node doesn't exist and createNew is false. 156 * @throws AmetysRepositoryException If a repository error occurs. 157 */ 158 protected ModifiableCompositeMetadata getAnnotationsNode(boolean createNew) throws UnknownMetadataException, AmetysRepositoryException 159 { 160 try 161 { 162 if (getNode().hasNode(_ANNOTATIONS_NODE_NAME)) 163 { 164 Node node = getNode().getNode(_ANNOTATIONS_NODE_NAME); 165 return new JCRCompositeMetadata(node, _resolver); 166 } 167 else if (createNew) 168 { 169 _checkLock(); 170 Node node = getNode().addNode(_ANNOTATIONS_NODE_NAME, "ametys:compositeMetadata"); 171 return new JCRCompositeMetadata(node, _resolver); 172 } 173 else 174 { 175 throw new UnknownMetadataException("No annotation found"); 176 } 177 } 178 catch (RepositoryException e) 179 { 180 throw new AmetysRepositoryException(e); 181 } 182 } 183 184 private void _checkLock() throws RepositoryException 185 { 186 Node node = getNode(); 187 if (!_lockAlreadyChecked && node.isLocked()) 188 { 189 LockManager lockManager = node.getSession().getWorkspace().getLockManager(); 190 191 Lock lock = lockManager.getLock(node.getPath()); 192 Node lockHolder = lock.getNode(); 193 194 lockManager.addLockToken(lockHolder.getProperty(RepositoryConstants.METADATA_LOCKTOKEN).getString()); 195 _lockAlreadyChecked = true; 196 } 197 } 198 199}