001/*
002 * (C) Copyright 2012 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.styleguide;
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
036 *
037 * @since 5.7
038 */
039public class StyleGuideURLCodec extends AbstractDocumentViewCodec {
040
041    public static final String DEFAULT_VIEW_ID = "style_guide";
042
043    // prefix/menu_id/(tab/subtab)?requestParams
044    public static final String GET_URL_PATTERN = "/" // slash
045            + "([a-zA-Z_0-9\\-\\.]*)?" // menu tab id (group 1)
046            + "(/([a-zA-Z_0-9\\-]*))?" // tab id (group 3) (optional)
047            + "(/([a-zA-Z_0-9\\-]*))?" // sub tab id (group 4) (optional)
048            + "(/)?" // final slash (optional)
049            + "(\\?(.*)?)?"; // query (group 8) (optional)
050
051    // prefix/outcome/in/several/parts/template.faces?requestParams
052    public static final String POST_URL_PATTERN = "/style_guide.faces(/)?(\\?(.*)?)?";
053
054    public String getUrlFromDocumentView(DocumentView docView) {
055        DocumentLocation docLoc = docView.getDocumentLocation();
056        if (docLoc != null) {
057            List<String> items = new ArrayList<String>();
058            items.add(getPrefix());
059            String viewId = docView.getViewId();
060            if (viewId != null) {
061                items.add(viewId);
062            } else {
063                items.add(DEFAULT_VIEW_ID);
064            }
065            Map<String, String> docViewParams = docView.getParameters();
066            Map<String, String> params = new HashMap<String, String>();
067            if (docViewParams != null) {
068                params.putAll(docViewParams);
069                params.remove("conversationId");
070                if (params.containsKey("tabId")) {
071                    items.add(params.get("tabId"));
072                    params.remove("tabId");
073                    if (params.containsKey("subTabId")) {
074                        items.add(params.get("subTabId"));
075                        params.remove("subTabId");
076                    }
077                }
078            }
079            String uri = StringUtils.join(items, "/");
080            return URIUtils.addParametersToURIQuery(uri, params);
081        }
082        return null;
083    }
084
085    /**
086     * Extracts view id and parameters, for both get and post methods
087     */
088    public DocumentView getDocumentViewFromUrl(String url) {
089        // strip url of any jsessionid param
090        int jsessionidIndex = url.indexOf(";jsessionid");
091        if (jsessionidIndex != -1) {
092            url = url.substring(0, jsessionidIndex);
093        }
094
095        // try POST pattern -> FIXME this is not enough information to restore
096        // a tab
097        Pattern pattern = Pattern.compile(getPrefix() + POST_URL_PATTERN);
098        Matcher m = pattern.matcher(url);
099        if (m.matches()) {
100            if (m.groupCount() >= 1) {
101
102                // for debug
103                // for (int i = 1; i < m.groupCount() + 1; i++) {
104                // System.err.println(i + ": " + m.group(i));
105                // }
106
107                // get other parameters
108
109                Map<String, String> params = null;
110
111                if (m.groupCount() > 4) {
112                    String query = m.group(5);
113                    params = URIUtils.getRequestParameters(query);
114                    if (params != null) {
115                        params.remove("conversationId");
116                    }
117                }
118
119                final DocumentLocation docLoc = new DocumentLocationImpl(null, null);
120
121                return new DocumentViewImpl(docLoc, null, params);
122            }
123        }
124        // try GET pattern
125        pattern = Pattern.compile(getPrefix() + GET_URL_PATTERN);
126        m = pattern.matcher(url);
127        if (m.matches()) {
128            if (m.groupCount() >= 1) {
129
130                // for debug
131                // for (int i = 1; i < m.groupCount() + 1; i++) {
132                // System.err.println(i + ": " + m.group(i));
133                // }
134
135                Map<String, String> params = new HashMap<String, String>();
136                String menuId = m.group(1);
137                if (menuId != null && !"".equals(menuId)) {
138                    params.put("menuId", menuId);
139                }
140
141                String tabId = m.group(3);
142                if (tabId != null && !"".equals(tabId)) {
143                    params.put("tabId", tabId);
144                }
145
146                String subTabId = m.group(5);
147                if (subTabId != null && !"".equals(subTabId)) {
148                    params.put("subTabId", subTabId);
149                }
150
151                // get other parameters
152
153                if (m.groupCount() > 3) {
154                    String query = m.group(8);
155                    Map<String, String> queryParams = URIUtils.getRequestParameters(query);
156                    if (queryParams != null) {
157                        queryParams.remove("conversationId");
158                        params.putAll(queryParams);
159                    }
160                }
161
162                final DocumentLocation docLoc = new DocumentLocationImpl(null, null);
163
164                return new DocumentViewImpl(docLoc, DEFAULT_VIEW_ID, params);
165            }
166        }
167
168        return null;
169    }
170
171}