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.web.repository.page.jcr; 017 018import java.util.List; 019 020import javax.jcr.Node; 021import javax.jcr.RepositoryException; 022 023import org.slf4j.Logger; 024import org.slf4j.LoggerFactory; 025 026import org.ametys.cms.repository.Content; 027import org.ametys.cms.repository.DefaultContent; 028import org.ametys.plugins.repository.AmetysObject; 029import org.ametys.plugins.repository.AmetysRepositoryException; 030import org.ametys.plugins.repository.CopiableAmetysObject; 031import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 032import org.ametys.plugins.repository.RepositoryConstants; 033import org.ametys.plugins.repository.RepositoryIntegrityViolationException; 034import org.ametys.plugins.repository.data.holder.ModifiableModelAwareDataHolder; 035import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder; 036import org.ametys.plugins.repository.data.holder.impl.DefaultModifiableModelAwareDataHolder; 037import org.ametys.plugins.repository.data.holder.impl.DefaultModifiableModelLessDataHolder; 038import org.ametys.plugins.repository.data.repositorydata.ModifiableRepositoryData; 039import org.ametys.plugins.repository.data.repositorydata.impl.JCRRepositoryData; 040import org.ametys.plugins.repository.jcr.JCRAmetysObject; 041import org.ametys.plugins.repository.jcr.SimpleAmetysObject; 042import org.ametys.plugins.repository.metadata.ModifiableCompositeMetadata; 043import org.ametys.web.repository.content.WebContent; 044import org.ametys.web.repository.page.ModifiableZone; 045import org.ametys.web.repository.page.ModifiableZoneItem; 046import org.ametys.web.repository.page.Zone; 047 048/** 049 * implementation of a {@link ModifiableZoneItem}. 050 */ 051public class DefaultZoneItem extends SimpleAmetysObject<DefaultZoneItemFactory> implements ModifiableZoneItem, CopiableAmetysObject 052{ 053 /** Constant for title metadata. */ 054 public static final String METADATA_TYPE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":type"; 055 /** Constant for service metadata. */ 056 public static final String METADATA_SERVICE = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":service"; 057 /** Constant for content metadata. */ 058 public static final String METADATA_CONTENT = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":content"; 059 /** Constant service parameters node type. */ 060 public static final String SERVICE_PARAM_NODETYPE = RepositoryConstants.NAMESPACE_PREFIX + ":compositeMetadata"; 061 062 /** 063 * Constant for "metadata set name" metadata. 064 * @deprecated Use {@link #METADATA_VIEW_NAME} instead 065 */ 066 @Deprecated 067 public static final String METADATA_METADATASET_NAME = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":metadataSetName"; 068 069 /** 070 * Constant for view name metadata. 071 * TODO NEWATTRIBUTEAPI_SERVICE: Change the name of this metadata to viewName (there may be a lot of impacts..) 072 */ 073 public static final String METADATA_VIEW_NAME = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":metadataSetName"; 074 075 private static final Logger __LOGGER = LoggerFactory.getLogger(DefaultZoneItem.class); 076 077 /** 078 * Creates a {@link DefaultZoneItem}. 079 * 080 * @param node the node backing this {@link AmetysObject}. 081 * @param parentPath the parent path in the Ametys hierarchy. 082 * @param factory the {@link DefaultZoneItemFactory} which creates the AmetysObject. 083 */ 084 public DefaultZoneItem(Node node, String parentPath, DefaultZoneItemFactory factory) 085 { 086 super(node, parentPath, factory); 087 } 088 089 public ZoneType getType() throws AmetysRepositoryException 090 { 091 try 092 { 093 return ZoneType.valueOf(getNode().getProperty(METADATA_TYPE).getString()); 094 } 095 catch (RepositoryException e) 096 { 097 throw new AmetysRepositoryException("Unable to get type property", e); 098 } 099 } 100 101 public void setType(ZoneType type) throws AmetysRepositoryException 102 { 103 try 104 { 105 getNode().setProperty(METADATA_TYPE, type.name()); 106 } 107 catch (RepositoryException e) 108 { 109 throw new AmetysRepositoryException("Unable to set type property", e); 110 } 111 } 112 113 public <C extends Content> C getContent() throws AmetysRepositoryException 114 { 115 try 116 { 117 return _getFactory().<C>resolveAmetysObject(getNode().getProperty(METADATA_CONTENT).getNode()); 118 } 119 catch (RepositoryException e) 120 { 121 throw new AmetysRepositoryException("Unable to get content property", e); 122 } 123 } 124 125 public <C extends Content> void setContent(C content) throws AmetysRepositoryException 126 { 127 try 128 { 129 // FIXME stop using getNode that is JCR but use AmetysObject API... if it seems cool to you 130 getNode().setProperty(METADATA_CONTENT, ((JCRAmetysObject) content).getNode()); 131 } 132 catch (RepositoryException e) 133 { 134 throw new AmetysRepositoryException("Unable to set content property", e); 135 } 136 } 137 138 @Override 139 public String getMetadataSetName() throws AmetysRepositoryException 140 { 141 return getViewName(); 142 } 143 144 public String getViewName() throws AmetysRepositoryException 145 { 146 try 147 { 148 if (getNode().hasProperty(METADATA_VIEW_NAME)) 149 { 150 return getNode().getProperty(METADATA_VIEW_NAME).getString(); 151 } 152 return null; 153 } 154 catch (RepositoryException e) 155 { 156 throw new AmetysRepositoryException("Unable to get view name property.", e); 157 } 158 } 159 160 @Override 161 public void setMetadataSetName(String metadataSetName) throws AmetysRepositoryException 162 { 163 setViewName(metadataSetName); 164 } 165 166 @Override 167 public void setViewName(String viewName) throws AmetysRepositoryException 168 { 169 try 170 { 171 getNode().setProperty(METADATA_VIEW_NAME, viewName); 172 } 173 catch (RepositoryException e) 174 { 175 throw new AmetysRepositoryException("Unable to set view name property.", e); 176 } 177 } 178 179 @Override 180 public String getServiceId() throws AmetysRepositoryException 181 { 182 try 183 { 184 return getNode().getProperty(METADATA_SERVICE).getString(); 185 } 186 catch (RepositoryException e) 187 { 188 throw new AmetysRepositoryException("Unable to get service property", e); 189 } 190 } 191 192 @Override 193 public void setServiceId(String serviceId) throws AmetysRepositoryException 194 { 195 try 196 { 197 getNode().setProperty(METADATA_SERVICE, serviceId); 198 } 199 catch (RepositoryException e) 200 { 201 throw new AmetysRepositoryException("Unable to set service property", e); 202 } 203 } 204 205 public ModifiableModelAwareDataHolder getServiceParameters() throws AmetysRepositoryException 206 { 207 JCRRepositoryData zoneItemRepositoryData = new JCRRepositoryData(getNode()); 208 209 JCRRepositoryData repositoryData = null; 210 if (zoneItemRepositoryData.hasValue(SERVICE_PARAMETERS_DATA_NAME)) 211 { 212 repositoryData = (JCRRepositoryData) zoneItemRepositoryData.getRepositoryData(SERVICE_PARAMETERS_DATA_NAME); 213 } 214 else 215 { 216 repositoryData = (JCRRepositoryData) zoneItemRepositoryData.addRepositoryData(SERVICE_PARAMETERS_DATA_NAME, SERVICE_PARAM_NODETYPE); 217 } 218 219 return new DefaultModifiableModelAwareDataHolder(repositoryData, _getFactory().getService(getServiceId())); 220 } 221 222 public ModifiableModelLessDataHolder getDataHolder() 223 { 224 ModifiableRepositoryData repositoryData = new JCRRepositoryData(getNode()); 225 return new DefaultModifiableModelLessDataHolder(_getFactory().getPageDataTypeExtensionPoint(), repositoryData); 226 } 227 228 @Override 229 public ModifiableCompositeMetadata getMetadataHolder() 230 { 231 __LOGGER.warn("The getMetadataHolder method of DefaultPage is deprecated. Use the getDataHolder instead. StackTrace: ", new Exception()); 232 return super.getMetadataHolder(); 233 } 234 235 @Override 236 public ModifiableZoneItem copyTo(ModifiableTraversableAmetysObject parent, String name, List<String> restrictTo) throws AmetysRepositoryException 237 { 238 return copyTo (parent, name); 239 } 240 241 @Override 242 public ModifiableZoneItem copyTo(ModifiableTraversableAmetysObject parent, String name) throws AmetysRepositoryException 243 { 244 if (parent instanceof DefaultZone) 245 { 246 ModifiableZone parentZone = (ModifiableZone) parent; 247 ModifiableZoneItem cZoneItem = parentZone.addZoneItem(); 248 249 ZoneType type = getType(); 250 cZoneItem.setType(type); 251 252 if (ZoneType.SERVICE.equals(type)) 253 { 254 cZoneItem.setServiceId(getServiceId()); 255 getServiceParameters().copyTo(cZoneItem.getServiceParameters()); 256 } 257 else 258 { 259 Content content = getContent(); 260 if (content instanceof WebContent) 261 { 262 WebContent webContent = (WebContent) content; 263 if (getZone().getPage().getSiteName().equals(webContent.getSiteName())) 264 { 265 if (webContent instanceof DefaultContent) 266 { 267 Content cContent = ((DefaultContent) webContent).copyTo(webContent.getSite().getRootContents(), null); 268 cZoneItem.setContent(cContent); 269 270 // Update references to AmetysObject in RichText 271 _getFactory().getCopySiteComponent().updateLinksInRichText(getZone().getPage(), cZoneItem.getZone().getPage(), content, cContent); 272 } 273 } 274 else 275 { 276 // Copy reference 277 cZoneItem.setContent(getContent()); 278 } 279 } 280 else 281 { 282 // Copy reference 283 cZoneItem.setContent(getContent()); 284 } 285 286 String metadataSetName = getMetadataSetName(); 287 if (metadataSetName != null) 288 { 289 cZoneItem.setMetadataSetName(metadataSetName); 290 } 291 } 292 293 return cZoneItem; 294 } 295 else 296 { 297 throw new AmetysRepositoryException("Can not copy a zone item " + getId() + " of type DefaultZoneItem to something that is not a DefaultZone " + parent.getId()); 298 } 299 } 300 301 @Override 302 public boolean canMoveTo(AmetysObject newParent) throws AmetysRepositoryException 303 { 304 return newParent instanceof DefaultZone; 305 } 306 307 @Override 308 public void moveTo(AmetysObject newParent, boolean renameIfExist) throws AmetysRepositoryException, RepositoryIntegrityViolationException 309 { 310 if (!canMoveTo(newParent)) 311 { 312 throw new AmetysRepositoryException("Can not move a zone item " + getId() + " of type DefaultZoneItem to something that is not a DefaultZone " + newParent.getId()); 313 } 314 315 Node node = getNode(); 316 317 try 318 { 319 DefaultZone newParentZone = (DefaultZone) newParent; 320 321 // Move node 322 node.getSession().move(node.getPath(), newParentZone.getNode().getPath() + "/" + DefaultZone.ZONEITEMS_NODE_NAME + "/" + node.getName()); 323 } 324 catch (RepositoryException e) 325 { 326 throw new AmetysRepositoryException("Can not move DefaultZoneItem " + getId() + " to DefaultZone " + newParent.getId(), e); 327 } 328 } 329 330 @Override 331 public void orderBefore(AmetysObject siblingObject) throws AmetysRepositoryException 332 { 333 if (siblingObject != null && !(siblingObject instanceof JCRAmetysObject)) 334 { 335 throw new AmetysRepositoryException(String.format("Unable to order zone item '%s' before sibling '%s' (sibling is not a JCRAmetysObject)", this.getId(), siblingObject.getId())); 336 } 337 338 Node node = getNode(); 339 Node siblingNode = siblingObject != null ? ((JCRAmetysObject) siblingObject).getNode() : null; 340 341 try 342 { 343 node.getParent().orderBefore(node.getName() + "[" + node.getIndex() + "]", siblingNode != null ? siblingNode.getName() + "[" + siblingNode.getIndex() + "]" : null); 344 } 345 catch (RepositoryException e) 346 { 347 throw new AmetysRepositoryException(String.format("Unable to order zone item '%s' before sibling '%s'", this.getId(), siblingObject != null ? siblingObject.getId() : ""), e); 348 } 349 } 350 351 @Override 352 public Zone getZone() 353 { 354 return getParent().getParent(); 355 } 356}