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.odfweb.repository; 018 019import java.util.Arrays; 020import java.util.Map; 021import java.util.Optional; 022import java.util.Map.Entry; 023 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.avalon.framework.service.Serviceable; 027import org.apache.commons.lang3.StringUtils; 028 029import org.ametys.plugins.repository.AmetysObjectFactory; 030import org.ametys.plugins.repository.AmetysObjectResolver; 031import org.ametys.plugins.repository.AmetysRepositoryException; 032import org.ametys.plugins.repository.UnknownAmetysObjectException; 033import org.ametys.web.repository.page.Page; 034 035/** 036 * {@link AmetysObjectFactory} handling {@link SecondLevelPage}. 037 */ 038public class SecondLevelPageFactory implements AmetysObjectFactory<SecondLevelPage>, Serviceable 039{ 040 private AmetysObjectResolver _resolver; 041 private OdfPageHandler _odfPageHandler; 042 private ODFPageCache _pageCache; 043 044 @Override 045 public void service(ServiceManager manager) throws ServiceException 046 { 047 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 048 _odfPageHandler = (OdfPageHandler) manager.lookup(OdfPageHandler.ROLE); 049 _pageCache = (ODFPageCache) manager.lookup(ODFPageCache.ROLE); 050 } 051 052 @Override 053 public SecondLevelPage getAmetysObjectById(String id) throws AmetysRepositoryException 054 { 055 String[] levels = _extractLevels(id); 056 String level1Code = levels[0]; 057 String level2Code = levels[1]; 058 Page rootPage = _extractRoot(id); 059 060 return _findSecondLevelValueEntry(rootPage, level2Code) 061 .map(entry -> _toSecondLevelPage(rootPage, level1Code, entry)) 062 .orElseThrow(() -> 063 new UnknownAmetysObjectException("There's no virtual child page named " + level2Code + " for parent " + rootPage)); 064 065 } 066 067 private Page _extractRoot(String id) 068 { 069 String rootId = StringUtils.substringAfter(id, "?rootId="); 070 return _resolver.resolveById(rootId); 071 } 072 073 private String[] _extractLevels(String id) 074 { 075 String levelParts = StringUtils.substringBetween(id, "://", "?"); 076 077 return Arrays.stream(StringUtils.split(levelParts, '/')) 078 .map(_odfPageHandler::decodeLevelValue) 079 .toArray(String[]::new); 080 } 081 082 private Optional<Entry<String, String>> _findSecondLevelValueEntry(Page rootPage, String levelCode) 083 { 084 Map<String, String> secondLevelValues = _odfPageHandler.getLevel2Values(rootPage); 085 return _findSecondLevelValueEntry(secondLevelValues, levelCode); 086 } 087 088 private Optional<Entry<String, String>> _findSecondLevelValueEntry(Map<String, String> secondLevelValues, String levelCode) 089 { 090 return secondLevelValues.entrySet().stream() 091 // entry = (code, title) 092 .filter(entry -> entry.getKey().equals(levelCode)) 093 .findFirst(); 094 } 095 096 private SecondLevelPage _toSecondLevelPage(Page rootPage, String level1Code, Map.Entry<String, String> secondLevelValueEntry) 097 { 098 String level2Code = secondLevelValueEntry.getKey(); 099 String title = secondLevelValueEntry.getValue(); 100 101 return new SecondLevelPage(_resolver, _pageCache, rootPage, level1Code, level2Code, title, _odfPageHandler); 102 } 103 104 @Override 105 public String getScheme() 106 { 107 return "odfLevel2"; 108 } 109 110 @Override 111 public boolean hasAmetysObjectForId(String id) throws AmetysRepositoryException 112 { 113 String[] levels = _extractLevels(id); 114 Page root = _extractRoot(id); 115 116 return _hasSecondLevelValue(root, levels[1]); 117 } 118 119 private boolean _hasSecondLevelValue(Page rootPage, String level2Code) throws AmetysRepositoryException 120 { 121 // FIXME should use page cache, because can return true when page does 122 // not exist. Maybe done like this for performance reasons? 123 Map<String, String> secondLevelValues = _odfPageHandler.getLevel2Values(rootPage); 124 return secondLevelValues.containsKey(level2Code); 125 } 126 127 ODFPageCache getODFPageCache() 128 { 129 return _pageCache; 130 } 131}