001 /**
002 * GRANITE DATA SERVICES
003 * Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 * This file is part of the Granite Data Services Platform.
006 *
007 * Granite Data Services is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * Granite Data Services is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
015 * General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
020 * USA, or see <http://www.gnu.org/licenses/>.
021 */
022 package org.granite.gravity.gae;
023
024
025 /**
026 * Adapted from Greg Wilkins code (Jetty).
027 *
028 * @author William DRAI
029 */
030 public class GAETopicId {
031
032 public final static String WILD = "*";
033 public final static String WILDWILD = "**";
034
035 private final static String[] ROOT = {};
036
037 private final String name;
038 private final String[] segments;
039 private final int wild;
040
041 public GAETopicId(String name) {
042 this.name = name;
043 if (name == null || name.length() == 0 || name.charAt(0) != '/')
044 throw new IllegalArgumentException("Illegal topic name: " + name);
045
046 if ("/".equals(name))
047 segments = ROOT;
048 else {
049 if (name.charAt(name.length() - 1) == '/')
050 throw new IllegalArgumentException("Illegal topic name (should not end with '/'): " + name);
051 segments = name.substring(1).split("\\Q/\\E", -1);
052 }
053
054 if (segments.length > 0) {
055 if (WILD.equals(segments[segments.length-1]))
056 wild = 1;
057 else if (WILDWILD.equals(segments[segments.length-1]))
058 wild = 2;
059 else
060 wild = 0;
061 }
062 else
063 wild = 0;
064 }
065
066 public boolean isWild() {
067 return wild > 0;
068 }
069
070 @Override
071 public boolean equals(Object obj) {
072 if (this == obj)
073 return true;
074
075 if (obj instanceof GAETopicId) {
076 GAETopicId other = (GAETopicId)obj;
077 if (isWild()) {
078 if (other.isWild())
079 return this.name.equals(other.name);
080 return matches(other);
081 }
082 if (other.isWild())
083 return other.matches(this);
084 return name.equals(other.name);
085 }
086 else if (obj instanceof String) {
087 if (isWild())
088 return matches((String)obj);
089 return name.equals(obj);
090 }
091
092 return false;
093 }
094
095 public boolean matches(GAETopicId name) {
096 if (name.isWild())
097 return equals(name);
098
099 switch (wild) {
100 case 0:
101 return equals(name);
102 case 1:
103 if (name.segments.length != segments.length)
104 return false;
105 for (int i = segments.length-1; i-- > 0; )
106 if (!segments[i].equals(name.segments[i]))
107 return false;
108 return true;
109
110 case 2:
111 if (name.segments.length < segments.length)
112 return false;
113 for (int i = segments.length-1; i-- > 0; )
114 if (!segments[i].equals(name.segments[i]))
115 return false;
116 return true;
117 }
118 return false;
119 }
120
121 public boolean matches(String name) {
122 if (wild == 0)
123 return this.name.equals(name);
124
125 // TODO more efficient?
126 return matches(new GAETopicId(name));
127 }
128
129 @Override
130 public int hashCode() {
131 return name.hashCode();
132 }
133
134 @Override
135 public String toString() {
136 return name;
137 }
138
139 public int depth() {
140 return segments.length;
141 }
142
143 public boolean isParentOf(GAETopicId id) {
144 if (isWild() || depth() >= id.depth())
145 return false;
146
147 for (int i = segments.length-1; i-- >0; )
148 if (!segments[i].equals(id.segments[i]))
149 return false;
150
151 return true;
152 }
153
154 public String getSegment(int i) {
155 if (i > segments.length)
156 return null;
157 return segments[i];
158 }
159
160 public static String normalize(String topicId) {
161 if (topicId == null)
162 return "/";
163 if (topicId.indexOf('.') >= 0)
164 topicId = topicId.replace('.', '/');
165 return (topicId.startsWith("/") ? topicId : ("/" + topicId));
166 }
167 }