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