/* * * Copyright 2005 AgileTec s.r.l. (http://www.agiletec.it) All rights reserved. * * This file is part of jAPS software. * jAPS is a free software; * you can redistribute it and/or modify it * under the terms of the GNU General Public License (GPL) as published by the Free Software Foundation; version 2. * * See the file License for the specific language governing permissions * and limitations under the License * * * * Copyright 2005 AgileTec s.r.l. (http://www.agiletec.it) All rights reserved. * */ package com.agiletec.aps.system.services.page.showlet; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import com.agiletec.aps.system.ApsSystemUtils; import com.agiletec.aps.system.RequestContext; import com.agiletec.aps.system.SystemConstants; import com.agiletec.aps.system.services.authorization.IAuthorizationManager; import com.agiletec.aps.system.services.page.IPage; import com.agiletec.aps.system.services.page.IPageManager; import com.agiletec.aps.system.services.user.UserDetails; /** * Classe di supporto per l'interpretazione delle espressioni che specificano sottoinsiemi * di pagine. Utilizzata dal tag per la generazione di navigatori; il risultato * dell'interpretazione è una lista di oggetti NavigatorTarget, che wrappano * pagine del portale e possono essere utilizzati dai sub-tag. Le espressioni per * la specificazione delle pagine da selezionare possono essere assolute o relative o miste, * in riferimento alla pagina visualizzata (pagina corrente) e sono definite in base * alla struttura ad albero delle pagine del portale (ogni pagina è un nodo).<BR> * Le <b>espressioni</b> supportate seguono la seguente sintassi:<br> * <code>expr1+expr2+ ... +exprn</code><br> * dove ogni espressione rappresenta un insieme di pagine e il segno + è l'operatore * di unione di insiemi.<br> * Ogni espressione in forma di stringa ha la forma:<br> * <code>page_spec</code><br> * oppure:<br> * <code>page_spec.operator</code><br> * dove <code>page_spec</code> è una funzione di selezione di una singola pagina e * <code>.operator</code> è un operatore che seleziona un sottoinsieme di pagine correlate alla * pagina cui è applicato.<br><br> * Solo nel caso dell'operatore "Subtree" gli oggetti NavigatorTarget restituiti * hanno associato un valore significativo del livello nel sottoalbero; in tutti gli altri * casi il livello ha valore zero. * @author M.Diana */ public class NavigatorParser implements INavigatorParser { @Override public List<NavigatorExpression> getExpressions(String spec) { List<NavigatorExpression> navExpressions = new ArrayList<NavigatorExpression>(); if (null != spec && spec.length() > 0) { String[] expressions = spec.split("\\+"); for (int i=0; i<expressions.length; i++) { String expression = expressions[i].trim(); if (expression.length() > 0) { NavigatorExpression navExpression = new NavigatorExpression(expression); navExpressions.add(navExpression); } } } return navExpressions; } @Override public String getSpec(List<NavigatorExpression> expressions) { if (null == expressions || expressions.size()==0) return ""; StringBuffer buffer = new StringBuffer(); boolean first = true; Iterator<NavigatorExpression> iter = expressions.iterator(); while (iter.hasNext()) { NavigatorExpression navigatorExpression = iter.next(); if (!first) buffer.append(" ").append(EXPRESSION_SEPARATOR).append(" "); buffer.append(navigatorExpression.toString()); first = false; } return buffer.toString(); } /** * Crea e restituisce una lista di oggetti NavigatorTarget, che wrappano * pagine del portale e possono essere utilizzati dai sub-tag. * @param spec L'espressione usata la specificazione delle pagine * da selezionare; possono essere assolute o relative o miste. * @param reqCtx Il contesto della richiesta corrente. * @return La lista di oggetti NavigatorTarget. */ @Override public List<NavigatorTarget> parseSpec(String spec, RequestContext reqCtx) { IPage currentPage = (IPage) reqCtx.getExtraParam(SystemConstants.EXTRAPAR_CURRENT_PAGE); UserDetails currentUser = (UserDetails) reqCtx.getRequest().getSession().getAttribute(SystemConstants.SESSIONPARAM_CURRENT_USER); return this.parseSpec(spec, currentPage, currentUser); } /** * Crea e restituisce una lista di oggetti NavigatorTarget, che wrappano * pagine del portale e possono essere utilizzati dai sub-tag. * @param spec L'espressione usata la specificazione delle pagine * da selezionare; possono essere assolute o relative o miste. * @param currentPage La pagina corrente dove il tag è inserito. * @param currentUser L'utente corrente. * @return La lista di oggetti NavigatorTarget. */ @Override public List<NavigatorTarget> parseSpec(String spec, IPage currentPage, UserDetails currentUser) { List<NavigatorTarget> targets = new ArrayList<NavigatorTarget>(); if (null != spec && spec.length() > 0) { String[] expressions = spec.split("\\"+EXPRESSION_SEPARATOR); for (int i=0; i<expressions.length; i++) { String expression = expressions[i].trim(); if (expression.length() > 0) { NavigatorExpression navExpression = new NavigatorExpression(expression); targets = this.parseSubSpec(navExpression, currentPage, targets, currentUser); } } } return targets; } private List<NavigatorTarget> parseSubSpec(NavigatorExpression navExpression, IPage page, List<NavigatorTarget> targets, UserDetails user) { int specId = navExpression.getSpecId(); IPage basePage = null; if (specId == NavigatorExpression.SPEC_CURRENT_PAGE_ID) { basePage = page; } else if (specId == NavigatorExpression.SPEC_PARENT_PAGE_ID) { int limit = 0; do { basePage = page.getParent(); limit++; } while((!basePage.isShowable() || !this.isUserAllowed(user, basePage)) && limit < 20); } else if (specId == NavigatorExpression.SPEC_SUPER_ID) { if (navExpression.getSpecSuperLevel() < 0) { throw new RuntimeException("Level 'SUPER' not specified : Page " + page.getCode()); } basePage = page; for (int i = 1; i <= navExpression.getSpecSuperLevel(); i++) { basePage = basePage.getParent(); } int limit = 0; while ((!basePage.isShowable() || !this.isUserAllowed(user, basePage)) && limit < 20) { basePage = basePage.getParent(); limit++; } } else if (specId == NavigatorExpression.SPEC_ABS_ID) { basePage = page; if (navExpression.getSpecAbsLevel() < 0) { throw new RuntimeException("Level 'ABS' not specified : Page " + page.getCode()); } int absLevel = navExpression.getSpecAbsLevel(); List<IPage> candidates = new ArrayList<IPage>(); int limit = 0; if (basePage.isShowable() && isUserAllowed(user, basePage)) { candidates.add(0, basePage); } while (basePage != basePage.getParent() && limit < 20) { basePage = basePage.getParent(); if (basePage.isShowable() && isUserAllowed(user, basePage)) { candidates.add(0, basePage); } limit ++; } if (absLevel >= candidates.size()) { absLevel = candidates.size() - 1; } basePage = (IPage) candidates.get(absLevel); } else if (specId == NavigatorExpression.SPEC_PAGE_ID) { if (null == navExpression.getSpecCode()) { throw new RuntimeException("Page Code not specified : Page " + page.getCode()); } String code = navExpression.getSpecCode(); IPage basePageTemp = this.getPageManager().getPage(code); if (null == basePageTemp) { ApsSystemUtils.getLogger().severe("Invalid Page Specification (null): Code " + code + " - Pagina " + page.getCode()); return targets; } if (basePageTemp.isShowable() && this.isUserAllowed(user, basePageTemp)) { basePage = basePageTemp; } } if (null == basePage) { return targets; } targets = this.processBasePage(navExpression, basePage, targets, user); return targets; } private List<NavigatorTarget> processBasePage(NavigatorExpression navExpression, IPage basePage, List<NavigatorTarget> targets, UserDetails user) { int operatorId = navExpression.getOperatorId(); if (operatorId < 0) { targets.add(new NavigatorTarget(basePage, 0)); } else { if (operatorId == NavigatorExpression.OPERATOR_CHILDREN_ID) { IPage children[] = basePage.getChildren(); for(int i = 0; i < children.length; i++) { if(children[i].isShowable() && isUserAllowed(user, children[i])) { targets.add(new NavigatorTarget(children[i], 0)); } } } else if (operatorId == NavigatorExpression.OPERATOR_PATH_ID) { IPage page = basePage; int index = targets.size(); int limit = 0; if (page.isShowable() && this.isUserAllowed(user, page)) { targets.add(index, new NavigatorTarget(page, 0)); } while (!page.isRoot() && limit < 20) { page = page.getParent(); if(page.isShowable() && this.isUserAllowed(user, page)) { targets.add(index, new NavigatorTarget(page, 0)); } limit++; } } else if (operatorId == NavigatorExpression.OPERATOR_SUBTREE_ID) { int depth = navExpression.getOperatorSubtreeLevel(); if (depth < 0) { throw new RuntimeException("Operator level 'SUBTREE' not specified"); } targets = this.putSubTree(basePage, 0, depth, targets, user); } else { targets = null; } } return targets; } private List<NavigatorTarget> putSubTree(IPage page, int level, int depth, List<NavigatorTarget> targets, UserDetails currentUser) { if (page.isShowable() && this.isUserAllowed(currentUser, page)) { targets.add(new NavigatorTarget(page, level)); if (level < depth) { IPage[] children = page.getChildren(); for(int i = 0; i < children.length; i++) { targets = this.putSubTree(children[i], level + 1, depth, targets, currentUser); } } } return targets; } private boolean isUserAllowed(UserDetails user, IPage page) { return this.getAuthManager().isAuth(user, page); } protected IPageManager getPageManager() { return _pageManager; } public void setPageManager(IPageManager pageManager) { this._pageManager = pageManager; } protected IAuthorizationManager getAuthManager() { return _authManager; } public void setAuthManager(IAuthorizationManager authManager) { this._authManager = authManager; } private IPageManager _pageManager; private IAuthorizationManager _authManager; }