/** * Copyright 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.waveprotocol.wave.model.id; import org.waveprotocol.wave.model.id.IdSerialiser.InvalidIdException; import org.waveprotocol.wave.model.id.IdSerialiser.RuntimeInvalidIdException; import org.waveprotocol.wave.model.util.Preconditions; /** * In the context of a single wave, a wavelet is identified by a tuple of a * wave provider domain and a local identifier which is unique within the domain * and the wave. * * @author zdwang@google.com (David Wang) * @author anorth@google.com (Alex North) */ public final class WaveletId implements Comparable<WaveletId> { private final String domain; private final String id; /** * Deserialises a wavelet identifier from a string, throwing a checked exception * if deserialisation fails. * * @param waveletIdString a serialised wave id * @return a wave id * @throws InvalidIdException if the serialised form is invalid */ public static WaveletId checkedDeserialise(String waveletIdString) throws InvalidIdException { return LongIdSerialiser.INSTANCE.deserialiseWaveletId(waveletIdString); } /** * Deserialises a wave identifier from a string. * * @param waveletIdString a serialised wave id * @return a wavelet id * @throws RuntimeInvalidIdException if the serialised form is invalid */ public static WaveletId deserialise(String waveletIdString) throws RuntimeInvalidIdException { try { return checkedDeserialise(waveletIdString); } catch (InvalidIdException e) { throw new RuntimeInvalidIdException(e.getId(), e.getMessage()); } } /** * Checks a string is a valid serialised wavelet id. * * @param waveletIdString serialised wavelet id * @return the input string, for convenience * @throws RuntimeInvalidIdException if the string is invalid */ public static String checkIsValid(String waveletIdString) throws RuntimeInvalidIdException { deserialise(waveletIdString); return waveletIdString; } /** * @param domain must not be null. This is assumed to be of a valid canonical * domain format. * @param id must not be null. This is assumed to be escaped with * SimplePrefixEscaper.DEFAULT_ESCAPER. */ public WaveletId(String domain, String id) { if (domain == null || id == null) { Preconditions.nullPointer("Cannot create WaveletId with null value in [domain:" + domain + "] [id:" + id + "]"); } if (domain.isEmpty() || id.isEmpty()) { Preconditions.illegalArgument("Cannot create wave id with empty value in [domain:" + domain + "] [id:" + id + "]"); } if (SimplePrefixEscaper.DEFAULT_ESCAPER.hasEscapeCharacters(domain)) { Preconditions.illegalArgument( "Domain cannot contain characters that requires escaping: " + domain); } if (!SimplePrefixEscaper.DEFAULT_ESCAPER.isEscapedProperly(IdConstants.TOKEN_SEPARATOR, id)) { Preconditions.illegalArgument("Id is not properly escaped: " + id); } // Intern domain string for memory efficiency. // NOTE(anorth): Update equals() if interning is removed. this.domain = domain.intern(); this.id = id; } /** * @return the domain */ public String getDomain() { return domain; } /** * @return the local id */ public String getId() { return id; } /** * Serialises this waveletId into a unique string. For any two wavelet ids, * waveletId1.serialise().equals(waveletId2.serialise()) iff waveId1.equals(waveId2). */ public String serialise() { return LongIdSerialiser.INSTANCE.serialiseWaveletId(this); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + domain.hashCode(); result = prime * result + id.hashCode(); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; WaveletId other = (WaveletId) obj; // Reference equality as domains are interned at construction. return (domain == other.domain) && id.equals(other.id); } @Override public String toString() { return "[WaveletId:" + serialise() + "]"; } @Override public int compareTo(WaveletId other) { int domainCompare = domain.compareTo(other.domain); if (domainCompare == 0) { return id.compareTo(other.id); } else { return domainCompare; } } }