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