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.Map;
020import java.util.Optional;
021
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.avalon.framework.service.Serviceable;
025import org.apache.commons.lang3.StringUtils;
026
027import org.ametys.odf.program.AbstractProgram;
028import org.ametys.odf.program.Program;
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
035import com.google.common.base.Splitter;
036
037/**
038 * {@link AmetysObjectFactory} handling {@link ProgramPage}.
039 */
040public class ProgramPageFactory implements AmetysObjectFactory<ProgramPage>, Serviceable
041{
042    /** Ametys object resolver */
043    protected AmetysObjectResolver _resolver;
044    
045    OdfPageHandler _odfPageHandler;
046    
047    @Override
048    public void service(ServiceManager manager) throws ServiceException
049    {
050        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
051        _odfPageHandler = (OdfPageHandler) manager.lookup(OdfPageHandler.ROLE);
052    }
053    
054    @Override
055    public ProgramPage getAmetysObjectById(String id) throws AmetysRepositoryException
056    {
057        // Id is like program://_root?rootId=xxxx&programId=xxxx for Program
058        // Id is like program://path/to/subprogram?rootId=xxxx&programId=xxxx&parentId=xxxx for SubProgram
059        
060        String path = StringUtils.substringBetween(id, "://", "?");
061        String queryString = StringUtils.substringAfter(id, "?");
062        Map<String, String> ids = Splitter.on("&").withKeyValueSeparator("=").split(queryString);
063        
064        String rootId = ids.get("rootId");
065        String programId = ids.get("programId");
066        String parentId = ids.get("parentId");
067        
068        if ("_root".equals(path))
069        {
070            // Case of a program
071            path = null;
072        }
073        
074        Page root = _resolver.resolveById(rootId);
075        AbstractProgram program = _resolver.resolveById(programId); // program or subprogram
076        Program parent = StringUtils.isNotEmpty(parentId) ? _resolver.resolveById(parentId) : null;
077        
078        // Test program restriction
079        if (!_odfPageHandler.isValidRestriction(root, _getParentProgramOrSelf(parent, program)))
080        {
081            throw new UnknownAmetysObjectException("There's no program child page " + programId + " for site " + root.getSiteName());
082        }
083        
084        ProgramPage programPage = new ProgramPage(_resolver, _odfPageHandler, root, program, path, parent, null);
085        
086        try
087        {
088            // Test if the virtual page really exists
089            programPage.getPathInSitemap();
090        }
091        catch (UnknownAmetysObjectException e)
092        {
093            throw new UnknownAmetysObjectException("There's no program child page " + programId + " for site " + root.getSiteName(), e);
094        }
095        
096        return programPage;
097    }
098    
099    private Program _getParentProgramOrSelf(Program parent, AbstractProgram self)
100    {
101        return Optional.ofNullable(parent)
102            .orElseGet(() -> (Program) self);
103    }
104    
105    @Override
106    public String getScheme()
107    {
108        return "program";
109    }
110
111    @Override
112    public boolean hasAmetysObjectForId(String id) throws AmetysRepositoryException
113    {
114        int i = id.indexOf('?');
115            
116        String queryString = id.substring(i + 1);
117        Map<String, String> ids = Splitter.on("&").withKeyValueSeparator("=").split(queryString);
118        
119        String rootId = ids.get("rootId");
120        String programId = ids.get("programId");
121        String parentId = ids.get("parentId");
122        
123        if (!_resolver.hasAmetysObjectForId(rootId) || !_resolver.hasAmetysObjectForId(programId))
124        {
125            return false;
126        }
127        
128        Page root = _resolver.resolveById(rootId);
129        AbstractProgram program = _resolver.resolveById(programId); // program or subprogram
130        Program parent = StringUtils.isNotEmpty(parentId) ? _resolver.resolveById(parentId) : null;
131        Program parentProgramOrSelf = _getParentProgramOrSelf(parent, program);
132        
133        if (!_odfPageHandler.isValidRestriction(root, parentProgramOrSelf))
134        {
135            return false;
136        }
137        
138        return _odfPageHandler.getProgramLevel1Value(root, parentProgramOrSelf) != null && _odfPageHandler.getProgramLevel2Value(root, parentProgramOrSelf) != null;
139    }
140}