001/* 002 * Copyright 2016 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.userdirectory.observation; 018 019import java.util.Map; 020 021import org.apache.avalon.framework.context.ContextException; 022import org.apache.avalon.framework.context.Contextualizable; 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.avalon.framework.service.Serviceable; 026import org.apache.cocoon.environment.Context; 027import org.apache.commons.lang3.ArrayUtils; 028 029import org.ametys.cms.ObservationConstants; 030import org.ametys.cms.contenttype.ContentTypesHelper; 031import org.ametys.cms.repository.Content; 032import org.ametys.core.observation.Event; 033import org.ametys.core.observation.Observer; 034import org.ametys.plugins.repository.AmetysObjectIterable; 035import org.ametys.plugins.repository.AmetysObjectResolver; 036import org.ametys.plugins.repository.query.expression.Expression; 037import org.ametys.plugins.repository.query.expression.VirtualFactoryExpression; 038import org.ametys.plugins.userdirectory.OrganisationChartPageHandler; 039import org.ametys.plugins.userdirectory.UserDirectoryPageHandler; 040import org.ametys.plugins.userdirectory.page.OrgUnitPage; 041import org.ametys.plugins.userdirectory.page.OrgUnitZoneItem; 042import org.ametys.plugins.userdirectory.page.OrganisationChartPageResolver; 043import org.ametys.plugins.userdirectory.page.UserDirectoryPageResolver; 044import org.ametys.plugins.userdirectory.page.UserZoneItem; 045import org.ametys.plugins.userdirectory.page.VirtualOrganisationChartPageFactory; 046import org.ametys.plugins.userdirectory.page.VirtualUserDirectoryPageFactory; 047import org.ametys.runtime.plugin.component.AbstractLogEnabled; 048import org.ametys.web.cache.pageelement.PageElementCache; 049import org.ametys.web.repository.page.Page; 050import org.ametys.web.repository.page.PageQueryHelper; 051 052/** 053 * Abstract {@link Observer} for observing validation of User content. 054 */ 055public abstract class AbstractContentObserver extends AbstractLogEnabled implements Observer, Serviceable, Contextualizable 056{ 057 /** The context. */ 058 protected org.apache.avalon.framework.context.Context _context; 059 /** Cocoon context. */ 060 protected Context _cocoonContext; 061 /** Ametys object resolver. */ 062 protected AmetysObjectResolver _resolver; 063 /** The content type helper */ 064 protected ContentTypesHelper _contentTypeHelper; 065 /** The page element cache */ 066 protected PageElementCache _zoneItemCache; 067 /** The resolver for user directory pages */ 068 protected UserDirectoryPageResolver _userDirectoryPageResolver; 069 /** The resolver for ud orgunits pages */ 070 protected OrganisationChartPageResolver _organisationChartPageResolver; 071 072 @Override 073 public void contextualize(org.apache.avalon.framework.context.Context context) throws ContextException 074 { 075 _context = context; 076 _cocoonContext = (Context) context.get(org.apache.cocoon.Constants.CONTEXT_ENVIRONMENT_CONTEXT); 077 } 078 079 @Override 080 public void service(ServiceManager manager) throws ServiceException 081 { 082 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 083 _contentTypeHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE); 084 _zoneItemCache = (PageElementCache) manager.lookup(PageElementCache.ROLE + "/zoneItem"); 085 _userDirectoryPageResolver = (UserDirectoryPageResolver) manager.lookup(UserDirectoryPageResolver.ROLE); 086 _organisationChartPageResolver = (OrganisationChartPageResolver) manager.lookup(OrganisationChartPageResolver.ROLE); 087 } 088 089 @Override 090 public void observe(Event event, Map<String, Object> transientVars) 091 { 092 try 093 { 094 Content content = _getTarget(event); 095 if (_isUserContent(content)) 096 { 097 AmetysObjectIterable<Page> rootPages = _getUserRootPages (); 098 if (!rootPages.iterator().hasNext()) 099 { 100 getLogger().debug("There's no user root page, nothing to invalidate"); 101 return; 102 } 103 104 for (Page rootPage : rootPages) 105 { 106 String cType = rootPage.getMetadataHolder().getString(UserDirectoryPageHandler.CONTENT_TYPE_METADATA_NAME, null); 107 if (ArrayUtils.contains(content.getTypes(), cType)) 108 { 109 _internalObserve(event, rootPage, content); 110 } 111 } 112 } 113 else if (_isOrgUnitContent(content)) 114 { 115 AmetysObjectIterable<Page> rootPages = _getOrgUnitRootPages (); 116 if (!rootPages.iterator().hasNext()) 117 { 118 getLogger().debug("There's no orgUnit root page, nothing to invalidate"); 119 return; 120 } 121 122 for (Page rootPage : rootPages) 123 { 124 _internalObserve(event, rootPage, content); 125 } 126 } 127 } 128 catch (Exception e) 129 { 130 getLogger().error("Unable to observe event: " + event, e); 131 } 132 } 133 134 /** 135 * Do the actual work. 136 * @param event the observation event. 137 * @param rootUsersPage the page holding the virtual user pages 138 * @param userContent a list containing all impacted user contents. 139 */ 140 protected abstract void _internalObserve(Event event, Page rootUsersPage, Content userContent); 141 142 /** 143 * Get the user root pages 144 * @return the user root pages 145 */ 146 protected AmetysObjectIterable<Page> _getUserRootPages () 147 { 148 Expression expression = new VirtualFactoryExpression(VirtualUserDirectoryPageFactory.class.getName()); 149 String query = PageQueryHelper.getPageXPathQuery(null, null, null, expression, null); 150 151 return _resolver.query(query); 152 } 153 154 /** 155 * Get the orgUnit root pages 156 * @return the orgUnit root pages 157 */ 158 protected AmetysObjectIterable<Page> _getOrgUnitRootPages () 159 { 160 Expression expression = new VirtualFactoryExpression(VirtualOrganisationChartPageFactory.class.getName()); 161 String query = PageQueryHelper.getPageXPathQuery(null, null, null, expression, null); 162 163 return _resolver.query(query); 164 } 165 166 /** 167 * Retrieve the target of the observer 168 * @param event The event 169 * @return The target 170 * @throws Exception if failed to get content 171 */ 172 protected Content _getTarget(Event event) throws Exception 173 { 174 return (Content) event.getArguments().get(ObservationConstants.ARGS_CONTENT); 175 } 176 177 /** 178 * Return true if the content is a user content 179 * @param content the content 180 * @return true if the content is a user content 181 */ 182 protected boolean _isUserContent(Content content) 183 { 184 return content != null && _contentTypeHelper.isInstanceOf(content, UserDirectoryPageHandler.ABSTRACT_USER_CONTENT_TYPE); 185 } 186 187 /** 188 * Return true if the content is a orgUnit content 189 * @param content the content 190 * @return true if the content is a orgUnit content 191 */ 192 protected boolean _isOrgUnitContent(Content content) 193 { 194 return content != null && _contentTypeHelper.isInstanceOf(content, OrganisationChartPageHandler.ORGUNIT_CONTENT_TYPE); 195 } 196 197 /** 198 * Remove zone item cache 199 * @param rootPage the root page 200 * @param content the content 201 * @param workspace the workspace 202 */ 203 protected void _removeZoneItemCache(Page rootPage, Content content, String workspace) 204 { 205 if (_isUserContent(content)) 206 { 207 String userPageId = _userDirectoryPageResolver.getUserPageId(rootPage, content); 208 String zoneItemId = UserZoneItem.getZoneItemId(userPageId); 209 210 _zoneItemCache.removeItem(workspace, rootPage.getSiteName(), "CONTENT", zoneItemId); 211 } 212 else if (_isOrgUnitContent(content)) 213 { 214 OrgUnitPage orgUnitPage = _organisationChartPageResolver.getOrgUnitPage(rootPage, content); 215 if (orgUnitPage != null) 216 { 217 String zoneItemId = OrgUnitZoneItem.getZoneItemId(orgUnitPage.getId()); 218 _zoneItemCache.removeItem(workspace, rootPage.getSiteName(), "CONTENT", zoneItemId); 219 } 220 } 221 } 222}