001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.tools;
016    
017    import java.util.Map;
018    import java.util.Set;
019    import java.util.TreeMap;
020    import java.util.TreeSet;
021    
022    /**
023     * A dummy container for friendly URL route data used by source formatter.
024     * Implements the comparable interface to sort routes by increasing generality.
025     *
026     * @author Connor McKay
027     * @author Hugo Huijser
028     */
029    public class ComparableRoute implements Comparable<ComparableRoute> {
030    
031            public static boolean isCaptureFragment(String fragment) {
032                    return fragment.contains("{");
033            }
034    
035            public static boolean isMatchAny(String fragment) {
036                    return fragment.matches(".*\\{.+?:\\.\\*\\}.*");
037            }
038    
039            public ComparableRoute(String pattern) {
040                    _pattern = pattern;
041            }
042    
043            public void addGeneratedParameter(String name, String pattern) {
044                    _generatedParameters.put(name, pattern);
045            }
046    
047            public void addIgnoredParameter(String name) {
048                    _ignoredParameters.add(name);
049            }
050    
051            public void addImplicitParameter(String name, String value) {
052                    _implicitParameters.put(name, value);
053            }
054    
055            public void addOverriddenParameter(String name, String value) {
056                    _overriddenParameters.put(name, value);
057            }
058    
059            @Override
060            public int compareTo(ComparableRoute comparableRoute) {
061    
062                    // Don't split on .*
063    
064                    String[] _fragments = _pattern.split("[/\\.](?!\\*)");
065    
066                    String pattern = comparableRoute.getPattern();
067    
068                    String[] fragments = pattern.split("[/\\.](?!\\*)");
069    
070                    // Having more fragments is more general
071    
072                    if (_fragments.length != fragments.length) {
073                            return _fragments.length - fragments.length;
074                    }
075    
076                    // Having more capture fragments is more general
077    
078                    int _captureFragmentsCount = getCaptureFragmentsCount(_fragments);
079                    int captureFragmentsCount = getCaptureFragmentsCount(fragments);
080    
081                    if (_captureFragmentsCount != captureFragmentsCount) {
082                            return _captureFragmentsCount - _captureFragmentsCount;
083                    }
084    
085                    int i;
086    
087                    for (i = 0; (i < _fragments.length) && (i < fragments.length); i++) {
088                            String _fragment = _fragments[i];
089                            String fragment = fragments[i];
090    
091                            // Capture fragments are more general than static ones
092    
093                            if (!isCaptureFragment(_fragment) && isCaptureFragment(fragment)) {
094                                    return -1;
095                            }
096    
097                            if (isCaptureFragment(_fragment) && !isCaptureFragment(fragment)) {
098                                    return 1;
099                            }
100    
101                            // A fragment matching .* is more general than anything
102    
103                            if (!isMatchAny(_fragment) && isMatchAny(fragment)) {
104                                    return -1;
105                            }
106    
107                            if (isMatchAny(_fragment) && !isMatchAny(fragment)) {
108                                    return 1;
109                            }
110                    }
111    
112                    // Having fewer implicit parameters is more general
113    
114                    Map<String, String> implicitParameters =
115                            comparableRoute.getImplicitParameters();
116    
117                    if (_implicitParameters.size() != implicitParameters.size()) {
118                            return implicitParameters.size() - _implicitParameters.size();
119                    }
120    
121                    return _pattern.compareTo(comparableRoute.getPattern());
122            }
123    
124            @Override
125            public boolean equals(Object obj) {
126                    if (this == obj) {
127                            return true;
128                    }
129    
130                    if (!(obj instanceof ComparableRoute)) {
131                            return false;
132                    }
133    
134                    ComparableRoute comparableRoute = (ComparableRoute)obj;
135    
136                    if (compareTo(comparableRoute) == 0) {
137                            return true;
138                    }
139                    else {
140                            return false;
141                    }
142            }
143    
144            public int getCaptureFragmentsCount(String[] fragments) {
145                    int count = 0;
146    
147                    for (String fragment : fragments) {
148                            if (isCaptureFragment(fragment)) {
149                                    count++;
150                            }
151                    }
152    
153                    return count;
154            }
155    
156            public Map<String, String> getGeneratedParameters() {
157                    return _generatedParameters;
158            }
159    
160            public Set<String> getIgnoredParameters() {
161                    return _ignoredParameters;
162            }
163    
164            public Map<String, String> getImplicitParameters() {
165                    return _implicitParameters;
166            }
167    
168            public Map<String, String> getOverriddenParameters() {
169                    return _overriddenParameters;
170            }
171    
172            public String getPattern() {
173                    return _pattern;
174            }
175    
176            private Map<String, String> _generatedParameters =
177                    new TreeMap<String, String>();
178            private Set<String> _ignoredParameters = new TreeSet<String>();
179            private Map<String, String> _implicitParameters =
180                    new TreeMap<String, String>();
181            private Map<String, String> _overriddenParameters =
182                    new TreeMap<String, String>();
183            private String _pattern;
184    
185    }