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;
020
021import org.apache.commons.lang3.StringUtils;
022
023import org.ametys.odf.program.AbstractProgram;
024import org.ametys.odf.program.Program;
025import org.ametys.plugins.repository.AmetysObjectFactory;
026import org.ametys.plugins.repository.AmetysRepositoryException;
027import org.ametys.plugins.repository.UnknownAmetysObjectException;
028import org.ametys.web.repository.page.Page;
029
030import com.google.common.base.Splitter;
031
032/**
033 * {@link AmetysObjectFactory} handling {@link ProgramPage}.
034 */
035public class ProgramPageFactory extends AbstractOdfPageFactory implements AmetysObjectFactory<ProgramPage>
036{
037    @Override
038    public ProgramPage getAmetysObjectById(String id) throws AmetysRepositoryException
039    {
040        // Id is like program://_root?rootId=xxxx&programId=xxxx for Program
041        // Id is like program://path/to/subprogram?rootId=xxxx&programId=xxxx&parentId=xxxx for SubProgram
042        
043        String path = StringUtils.substringBetween(id, "://", "?");
044        String queryString = StringUtils.substringAfter(id, "?");
045        Map<String, String> ids = Splitter.on("&").withKeyValueSeparator("=").split(queryString);
046        
047        String rootId = ids.get("rootId");
048        String programId = ids.get("programId");
049        String parentId = ids.get("parentId");
050        
051        if ("_root".equals(path))
052        {
053            // Case of a program
054            path = null;
055        }
056        
057        Page root = _resolver.resolveById(rootId);
058        AbstractProgram program = _resolver.resolveById(programId); // program or subprogram
059        Program parent = StringUtils.isNotEmpty(parentId) ? _resolver.resolveById(parentId) : null;
060        Program parentProgramOrSelf = _getParentProgramOrSelf(parent, program);
061        
062        // The identifier is invalid
063        if (parentProgramOrSelf == null)
064        {
065            throw new UnknownAmetysObjectException("The object '" + program.getId() + "' is not a Program and its given parent is null.");
066        }
067        
068        // Test program restriction
069        if (!_odfPageHandler.isValidRestriction(root, parentProgramOrSelf))
070        {
071            throw new UnknownAmetysObjectException("There's no program child page " + programId + " for site " + root.getSiteName());
072        }
073        
074        ProgramPage programPage = new ProgramPage(this, root, program, path, parent, null);
075        
076        try
077        {
078            // Test if the virtual page really exists
079            programPage.getPathInSitemap();
080        }
081        catch (UnknownAmetysObjectException e)
082        {
083            throw new UnknownAmetysObjectException("There's no program child page " + programId + " for site " + root.getSiteName(), e);
084        }
085        
086        return programPage;
087    }
088    
089    private Program _getParentProgramOrSelf(Program parent, AbstractProgram self) throws UnknownAmetysObjectException
090    {
091        if (parent != null)
092        {
093            return parent;
094        }
095        
096        // In old identifiers, a subprogram target doesn't need the parentId, so if we don't have a parent, it can be an old target with a subprogram
097        if (self instanceof Program)
098        {
099            return (Program) self;
100        }
101        
102        return null;
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        // The identifier is invalid
134        if (parentProgramOrSelf == null)
135        {
136            return false;
137        }
138        
139        if (!_odfPageHandler.isValidRestriction(root, parentProgramOrSelf))
140        {
141            return false;
142        }
143        
144        if (StringUtils.isNotBlank(_odfPageHandler.getLevel2Metadata(root)))
145        {
146            return _odfPageHandler.getProgramLevel1Value(root, parentProgramOrSelf) != null && _odfPageHandler.getProgramLevel2Value(root, parentProgramOrSelf) != null;
147        }
148        else if (StringUtils.isNotBlank(_odfPageHandler.getLevel1Metadata(root)))
149        {
150            return _odfPageHandler.getProgramLevel1Value(root, parentProgramOrSelf) != null;
151        }
152        
153        return true;
154    }
155}