View Javadoc
1   /**
2    * This file Copyright (c) 2012-2014 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.ui.api.location;
35  
36  import info.magnolia.context.MgnlContext;
37  
38  import java.io.UnsupportedEncodingException;
39  import java.net.URLDecoder;
40  import java.util.StringTokenizer;
41  
42  import org.apache.commons.lang3.StringUtils;
43  import org.slf4j.Logger;
44  import org.slf4j.LoggerFactory;
45  
46  /**
47   * Default location implementation. Follows the pattern: {@code appType:appName:subAppId;some/parameter}.
48   */
49  public class DefaultLocation implements Location {
50  
51      private static Logger log = LoggerFactory.getLogger(DefaultLocation.class);
52  
53      private String appType;
54  
55      private String appName;
56  
57      private String subAppId;
58  
59      private String parameter;
60  
61      public DefaultLocation() {
62      }
63  
64      public DefaultLocation(String appType, String appName) {
65          this(appType, appName, "");
66      }
67  
68      public DefaultLocation(String appType, String appName, String subAppId) {
69          this(appType, appName, subAppId, "");
70      }
71  
72      public DefaultLocation(String appType, String appName, String subAppId, String parameter) {
73          this.appType = decodeFragment(appType);
74          this.appName = decodeFragment(appName);
75          this.subAppId = decodeFragment(subAppId);
76          this.parameter = decodeFragment(parameter);
77      }
78  
79      /**
80       * @throws IllegalArgumentException if the passed fragment is null or empty.
81       */
82      public DefaultLocation(String fragment) {
83          if (StringUtils.isBlank(fragment)) {
84              throw new IllegalArgumentException("Fragment cannot be empty or null");
85          }
86          parseLocation(fragment);
87      }
88  
89      private void parseLocation(String fragment) {
90          String[] split = StringUtils.split(fragment, ";");
91          setAppParams(split[0]);
92          if (split.length == 2) {
93              this.parameter = decodeFragment(split[1]);
94          }
95      }
96  
97      private void setAppParams(String appParams) {
98          StringTokenizer tokenizer = new StringTokenizer(appParams, ":");
99          this.appType = decodeFragment((tokenizer.hasMoreTokens()) ? tokenizer.nextToken() : "");
100         this.appName = decodeFragment((tokenizer.hasMoreTokens()) ? tokenizer.nextToken() : "");
101         this.subAppId = decodeFragment((tokenizer.hasMoreTokens()) ? tokenizer.nextToken() : "");
102     }
103 
104     @Override
105     public String getAppType() {
106         return appType;
107     }
108 
109     @Override
110     public String getAppName() {
111         return appName;
112     }
113 
114     @Override
115     public String getSubAppId() {
116         return subAppId;
117     }
118 
119     @Override
120     public String getParameter() {
121         return parameter;
122     }
123 
124     public void setParameter(String parameter) {
125         this.parameter = decodeFragment(parameter);
126     }
127 
128     public void setSubAppId(String subAppId) {
129         this.subAppId = decodeFragment(subAppId);
130     }
131 
132     public void setAppType(String appType) {
133         this.appType = decodeFragment(appType);
134     }
135 
136     public void setAppName(String appName) {
137         this.appName = decodeFragment(appName);
138     }
139 
140     @Override
141     public boolean equals(Object o) {
142         if (this == o) {
143             return true;
144         }
145 
146         if ((o == null) || !(o instanceof  DefaultLocation)) {
147             return false;
148         }
149 
150         DefaultLocation that = (DefaultLocation) o;
151 
152         if (appType != null ? !appType.equals(that.appType) : that.appType != null) {
153             return false;
154         }
155         if (appName != null ? !appName.equals(that.appName) : that.appName != null) {
156             return false;
157         }
158         if (subAppId != null ? !subAppId.equals(that.subAppId) : that.subAppId != null) {
159             return false;
160         }
161         if (parameter != null ? !parameter.equals(that.parameter) : that.parameter != null) {
162             return false;
163         }
164 
165         return true;
166     }
167 
168     @Override
169     public int hashCode() {
170         int result = appType != null ? appType.hashCode() : 0;
171         result = 31 * result + (appName != null ? appName.hashCode() : 0);
172         result = 31 * result + (subAppId != null ? subAppId.hashCode() : 0);
173         result = 31 * result + (parameter != null ? parameter.hashCode() : 0);
174         return result;
175     }
176 
177     @Override
178     public String toString() {
179         StringBuilder sb = new StringBuilder();
180         if (appType != null && appType.length() != 0) {
181             sb.append(appType);
182             if (appName != null && appName.length() != 0) {
183                 sb.append(":").append(appName);
184             }
185             if (subAppId != null && subAppId.length() != 0) {
186                 sb.append(":").append(subAppId);
187             }
188             if (parameter != null && parameter.length() != 0) {
189                 sb.append(";").append(parameter);
190             }
191         }
192         return sb.toString();
193     }
194 
195     public static String extractAppType(String fragment) {
196         int i = fragment.indexOf(':');
197         return i != -1 ? fragment.substring(0, i) : fragment;
198     }
199 
200     public static String extractAppName(String fragment) {
201         fragment = removeParameter(fragment);
202         int i = fragment.indexOf(':');
203         if (i == -1) {
204             return "";
205         }
206         int j = fragment.indexOf(':', i + 1);
207         return j != -1 ? fragment.substring(i + 1, j) : fragment.substring(i + 1);
208     }
209 
210     public static String extractSubAppId(String fragment) {
211         fragment = removeParameter(fragment);
212 
213         int i = fragment.indexOf(':');
214         if (i == -1) {
215             return "";
216         }
217         int j = fragment.indexOf(':', i + 1);
218         if (j == -1) {
219             return "";
220         }
221         return fragment.substring(j + 1);
222     }
223 
224     public static String extractParameter(String fragment) {
225         int i = fragment.indexOf(';');
226         if (i == -1) {
227             return "";
228         }
229         return fragment.substring(i + 1);
230     }
231 
232     private static String removeParameter(String fragment) {
233         int i = fragment.indexOf(';');
234         return i != -1 ? fragment.substring(0, i) : fragment;
235     }
236 
237     /**
238      * Decodes <code>application/x-www-form-urlencoded</code> fragment string using a specified encoding scheme if necessary.
239      */
240     public static String decodeFragment(String fragment, String encoding) {
241         if (fragment == null) {
242             return fragment;
243         }
244 
245         if (fragment.indexOf('%') > -1) {
246             try {
247                 fragment = URLDecoder.decode(fragment, encoding);
248             } catch (UnsupportedEncodingException e) {
249                 log.error("Error decoding fragment '" + fragment + "' with encoding '" + encoding + "'", e);
250             }
251         }
252 
253         return fragment;
254     }
255 
256     /**
257      * Decodes a fragment using the character encoding from the {@link info.magnolia.cms.core.AggregationState}.
258      */
259     public static String decodeFragment(String fragment) {
260         return decodeFragment(fragment, MgnlContext.getAggregationState().getCharacterEncoding());
261     }
262 
263 }