001/*
002 * (C) Copyright 2010 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Anahide Tchertchian
016 */
017package org.nuxeo.ecm.platform.forms.layout.demo.jsf;
018
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023import java.util.regex.Matcher;
024import java.util.regex.Pattern;
025
026import org.apache.commons.lang.StringUtils;
027import org.nuxeo.common.utils.URIUtils;
028import org.nuxeo.ecm.core.api.DocumentLocation;
029import org.nuxeo.ecm.core.api.impl.DocumentLocationImpl;
030import org.nuxeo.ecm.platform.url.DocumentViewImpl;
031import org.nuxeo.ecm.platform.url.api.DocumentView;
032import org.nuxeo.ecm.platform.url.service.AbstractDocumentViewCodec;
033
034/**
035 * Provides clean urls without conversation id to handle navigation inside the layout demo.
036 *
037 * @author Anahide Tchertchian
038 */
039public class LayoutDemoURLCodec extends AbstractDocumentViewCodec {
040
041    // prefix/view_id/(tab/subtab)?requestParams
042
043    public static final String GET_URL_PATTERN = "/" // slash
044            + "([a-zA-Z_0-9\\-\\.]*)?" // view id (group 1)
045            + "(/([a-zA-Z_0-9\\-]*))?" // tab id (group 3) (optional)
046            + "(/([a-zA-Z_0-9\\-]*))?" // sub tab id (group 4) (optional)
047            + "(/)?" // final slash (optional)
048            + "(\\?(.*)?)?"; // query (group 8) (optional)
049
050    public static final String URL_PATTERN = "/" // slash
051            + "([\\w\\.]+)" // server name (group 1)
052            + "(?:/(.*))?" // path (group 2) (optional)
053            + "@([\\w\\-\\.]+)" // view id (group 3)
054            + "/?" // final slash (optional)
055            + "(?:\\?(.*)?)?"; // query (group 4) (optional)
056
057    // prefix/outcome/in/several/parts/template.faces?requestParams
058    public static final String POST_URL_PATTERN = "/([a-zA-Z_0-9\\-\\./]*)?(.faces)(/)?(\\?(.*)?)?";
059
060    public static final String LAYOUT_PREVIEW_FRAME_VIEW_ID = "layoutPreviewFrame";
061
062    public static final String DEFAULT_VIEW_ID = "layoutDemoIntroduction";
063
064    public String getUrlFromDocumentView(DocumentView docView) {
065        DocumentLocation docLoc = docView.getDocumentLocation();
066        if (docLoc != null) {
067            List<String> items = new ArrayList<String>();
068            items.add(getPrefix());
069            String viewId = docView.getViewId();
070            if (viewId != null) {
071                items.add(viewId);
072            } else {
073                items.add(DEFAULT_VIEW_ID);
074            }
075            Map<String, String> docViewParams = docView.getParameters();
076            Map<String, String> params = new HashMap<String, String>();
077            if (docViewParams != null) {
078                params.putAll(docViewParams);
079                params.remove("conversationId");
080                if (params.containsKey("tabId")) {
081                    items.add(params.get("tabId"));
082                    params.remove("tabId");
083                    if (params.containsKey("subTabId")) {
084                        items.add(params.get("subTabId"));
085                        params.remove("subTabId");
086                    }
087                }
088            }
089            String uri = StringUtils.join(items, "/");
090            return URIUtils.addParametersToURIQuery(uri, params);
091        }
092        return null;
093    }
094
095    /**
096     * Extracts view id and parameters, for both get and post methods
097     */
098    public DocumentView getDocumentViewFromUrl(String url) {
099        // strip url of any jsessionid param
100        int jsessionidIndex = url.indexOf(";jsessionid");
101        if (jsessionidIndex != -1) {
102            url = url.substring(0, jsessionidIndex);
103        }
104
105        // try POST pattern
106        Pattern pattern = Pattern.compile(getPrefix() + POST_URL_PATTERN);
107        Matcher m = pattern.matcher(url);
108        if (m.matches()) {
109            if (m.groupCount() >= 1) {
110
111                // for debug
112                // for (int i = 1; i < m.groupCount() + 1; i++) {
113                // System.err.println(i + ": " + m.group(i));
114                // }
115
116                // get other parameters
117
118                Map<String, String> params = null;
119
120                if (m.groupCount() > 4) {
121                    String query = m.group(5);
122                    params = URIUtils.getRequestParameters(query);
123                    if (params != null) {
124                        params.remove("conversationId");
125                    }
126                }
127
128                final DocumentLocation docLoc = new DocumentLocationImpl(null, null);
129
130                return new DocumentViewImpl(docLoc, null, params);
131            }
132        }
133        // try GET pattern
134        pattern = Pattern.compile(getPrefix() + GET_URL_PATTERN);
135        m = pattern.matcher(url);
136        if (m.matches()) {
137            if (m.groupCount() >= 1) {
138
139                // for debug
140                // for (int i = 1; i < m.groupCount() + 1; i++) {
141                // System.err.println(i + ": " + m.group(i));
142                // }
143
144                String viewId = m.group(1);
145                if (viewId == null || "".equals(viewId)) {
146                    viewId = DEFAULT_VIEW_ID;
147                }
148
149                Map<String, String> params = new HashMap<String, String>();
150
151                String tabId = m.group(3);
152                if (tabId != null && !"".equals(tabId)) {
153                    params.put("tabId", tabId);
154                }
155
156                String subTabId = m.group(5);
157                if (subTabId != null && !"".equals(subTabId)) {
158                    params.put("subTabId", subTabId);
159                }
160
161                // get other parameters
162
163                if (m.groupCount() > 3) {
164                    String query = m.group(8);
165                    Map<String, String> queryParams = URIUtils.getRequestParameters(query);
166                    if (queryParams != null) {
167                        queryParams.remove("conversationId");
168                        params.putAll(queryParams);
169                    }
170                }
171
172                final DocumentLocation docLoc = new DocumentLocationImpl(null, null);
173
174                return new DocumentViewImpl(docLoc, viewId, params);
175            }
176        }
177
178        return null;
179    }
180
181    public static boolean isPreview(String viewId) {
182        if (LAYOUT_PREVIEW_FRAME_VIEW_ID.equals(viewId)) {
183            return true;
184        }
185        return false;
186    }
187
188}