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 */ 022package org.granite.gravity.gae; 023 024 025/** 026 * Adapted from Greg Wilkins code (Jetty). 027 * 028 * @author William DRAI 029 */ 030public 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}