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 */ 016 017package org.ametys.plugins.repository.jcr; 018 019import javax.jcr.Node; 020import javax.jcr.RepositoryException; 021import javax.jcr.nodetype.ConstraintViolationException; 022 023import org.apache.jackrabbit.util.Text; 024 025import org.ametys.plugins.repository.AbstractAmetysObject; 026import org.ametys.plugins.repository.AmetysObject; 027import org.ametys.plugins.repository.AmetysRepositoryException; 028import org.ametys.plugins.repository.RepositoryIntegrityViolationException; 029import org.ametys.plugins.repository.metadata.CompositeMetadata; 030import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata; 031import org.ametys.plugins.repository.metadata.jcr.JCRCompositeMetadata; 032 033/** 034 * Default implementation of an {@link AmetysObject}, backed by a JCR node.<br> 035 * This implementation heavily relies on its {@link SimpleAmetysObjectFactory} counterpart. 036 * @param <F> the actual type of factory. 037 */ 038public class SimpleAmetysObject<F extends SimpleAmetysObjectFactory> extends AbstractAmetysObject implements JCRAmetysObject 039{ 040 /** The corresponding {@link SimpleAmetysObjectFactory} */ 041 private F _factory; 042 043 private Node _node; 044 045 private String _name; 046 private String _parentPath; 047 048 /** 049 * Creates an {@link SimpleAmetysObject}. 050 * @param node the node backing this {@link AmetysObject} 051 * @param parentPath the parentPath in the Ametys hierarchy 052 * @param factory the DefaultTraversableAmetysObjectFactory which created the AmetysObject 053 */ 054 public SimpleAmetysObject(Node node, String parentPath, F factory) 055 { 056 _node = node; 057 _parentPath = parentPath; 058 _factory = factory; 059 060 try 061 { 062 _name = Text.unescapeIllegalJcrChars(_node.getName()); 063 } 064 catch (RepositoryException e) 065 { 066 throw new AmetysRepositoryException("Unable to get node name", e); 067 } 068 } 069 070 /** 071 * Retrieves the factory. 072 * @return the factory. 073 */ 074 protected F _getFactory() 075 { 076 return _factory; 077 } 078 079 public String getName() throws AmetysRepositoryException 080 { 081 return _name; 082 } 083 084 /** 085 * Returns the root {@link CompositeMetadata} of this {@link AmetysObject}. 086 * @return the root {@link CompositeMetadata} of this {@link AmetysObject} 087 * @deprecated use getRepositoryData instead 088 */ 089 @Deprecated 090 public ModifiableCompositeMetadata getMetadataHolder() 091 { 092 return new JCRCompositeMetadata(getNode(), _getFactory()._getResolver()); 093 } 094 095 public String getParentPath() throws AmetysRepositoryException 096 { 097 if (_parentPath == null) 098 { 099 _parentPath = getParent().getPath(); 100 } 101 102 return _parentPath; 103 } 104 105 /** 106 * Invalidates cached parent path. 107 */ 108 protected void _invalidateParentPath() 109 { 110 _parentPath = null; 111 } 112 113 /** 114 * Recompute the name from the Node.<br> 115 * To be used when the node name changesd internally. 116 */ 117 protected void _invalidateName() 118 { 119 try 120 { 121 _name = Text.unescapeIllegalJcrChars(getNode().getName()); 122 } 123 catch (RepositoryException e) 124 { 125 throw new AmetysRepositoryException(e); 126 } 127 } 128 129 public String getPath() throws AmetysRepositoryException 130 { 131 return getParentPath() + "/" + getName(); 132 } 133 134 public Node getNode() 135 { 136 return _node; 137 } 138 139 public String getId() 140 { 141 try 142 { 143 return _factory.getScheme() + "://" + _node.getIdentifier(); 144 } 145 catch (RepositoryException e) 146 { 147 throw new AmetysRepositoryException("Unable to get node UUID", e); 148 } 149 } 150 151 @Override 152 public void rename(String newName) throws AmetysRepositoryException 153 { 154 try 155 { 156 NodeHelper.rename(getNode(), newName); 157 _name = Text.unescapeIllegalJcrChars(getNode().getName()); 158 } 159 catch (RepositoryException e) 160 { 161 throw new AmetysRepositoryException(e); 162 } 163 } 164 165 public void remove() throws AmetysRepositoryException, RepositoryIntegrityViolationException 166 { 167 try 168 { 169 getNode().remove(); 170 } 171 catch (ConstraintViolationException e) 172 { 173 throw new RepositoryIntegrityViolationException(e); 174 } 175 catch (RepositoryException e) 176 { 177 throw new AmetysRepositoryException(e); 178 } 179 } 180 181 @SuppressWarnings("unchecked") 182 public <A extends AmetysObject> A getParent() throws AmetysRepositoryException 183 { 184 return (A) _factory.getParent(this); 185 } 186 187 @Override 188 public boolean needsSave() throws AmetysRepositoryException 189 { 190 try 191 { 192 return _node.getSession().hasPendingChanges(); 193 } 194 catch (RepositoryException e) 195 { 196 throw new AmetysRepositoryException(e); 197 } 198 } 199 200 public void saveChanges() throws AmetysRepositoryException 201 { 202 try 203 { 204 getNode().getSession().save(); 205 } 206 catch (javax.jcr.RepositoryException e) 207 { 208 throw new AmetysRepositoryException("Unable to save changes", e); 209 } 210 } 211 212 @Override 213 public void revertChanges() throws AmetysRepositoryException 214 { 215 try 216 { 217 getNode().refresh(false); 218 } 219 catch (javax.jcr.RepositoryException e) 220 { 221 throw new AmetysRepositoryException("Unable to revert changes.", e); 222 } 223 } 224 225}