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 /** 038 * Create a second level page. 039 * @param root the odf root page. 040 * @param level1Key the parent first level code (name) 041 * @param name the page's name. 042 * @param title the page's title. 043 * @param firstLevelPage The parent first level page. 044 * @return The <code>SecondLevelPage</code> created 045 */ 046 public SecondLevelPage createSecondLevelPage(Page root, String level1Key, String name, String title, FirstLevelPage firstLevelPage) 047 { 048 return new SecondLevelPage(root, getConfiguration(), this, level1Key, name, title, firstLevelPage); 049 } 050 051 @Override 052 public SecondLevelPage getAmetysObjectById(String id) throws AmetysRepositoryException 053 { 054 String[] levels = _extractLevels(id); 055 String level1Code = levels[0]; 056 String level2Code = levels[1]; 057 Page rootPage = _extractRoot(id); 058 059 return _findSecondLevelValueEntry(rootPage, level2Code) 060 .map(entry -> _toSecondLevelPage(rootPage, level1Code, entry)) 061 .orElseThrow(() -> 062 new UnknownAmetysObjectException("There's no virtual child page named " + level2Code + " for parent " + rootPage)); 063 064 } 065 066 private Page _extractRoot(String id) 067 { 068 String rootId = StringUtils.substringAfter(id, "?rootId="); 069 return _resolver.resolveById(rootId); 070 } 071 072 private String[] _extractLevels(String id) 073 { 074 String levelParts = StringUtils.substringBetween(id, "://", "?"); 075 076 return Arrays.stream(StringUtils.split(levelParts, '/')) 077 .map(_odfPageHandler::decodeLevelValue) 078 .toArray(String[]::new); 079 } 080 081 private Optional<Entry<String, LevelValue>> _findSecondLevelValueEntry(Page rootPage, String levelCode) 082 { 083 Map<String, LevelValue> secondLevelValues = _odfPageHandler.getLevel2Values(rootPage); 084 return _findSecondLevelValueEntry(secondLevelValues, levelCode); 085 } 086 087 private Optional<Entry<String, LevelValue>> _findSecondLevelValueEntry(Map<String, LevelValue> secondLevelValues, String levelCode) 088 { 089 return secondLevelValues.entrySet().stream() 090 // entry = (code, title) 091 .filter(entry -> entry.getKey().equals(levelCode)) 092 .findFirst(); 093 } 094 095 private SecondLevelPage _toSecondLevelPage(Page rootPage, String level1Code, Map.Entry<String, LevelValue> secondLevelValueEntry) 096 { 097 String level2Code = secondLevelValueEntry.getKey(); 098 String title = secondLevelValueEntry.getValue().getValue(); 099 100 return createSecondLevelPage(rootPage, level1Code, level2Code, title, null); 101 } 102 103 @Override 104 public String getScheme() 105 { 106 return "odfLevel2"; 107 } 108 109 @Override 110 public boolean hasAmetysObjectForId(String id) throws AmetysRepositoryException 111 { 112 String[] levels = _extractLevels(id); 113 Page root = _extractRoot(id); 114 115 return _hasSecondLevelValue(root, levels[1]); 116 } 117 118 private boolean _hasSecondLevelValue(Page rootPage, String level2Code) throws AmetysRepositoryException 119 { 120 // FIXME should use page cache, because can return true when page does 121 // not exist. Maybe done like this for performance reasons? 122 Map<String, LevelValue> secondLevelValues = _odfPageHandler.getLevel2Values(rootPage); 123 return secondLevelValues.containsKey(level2Code); 124 } 125}