/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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. */ using System; using System.Collections.Specialized; using Apache.NMS.Util; namespace Apache.NMS.Stomp.Commands { /// /// Summary description for Destination. /// public abstract class Destination : BaseDataStructure, IDestination { /// /// Topic Destination object /// public const int STOMP_TOPIC = 1; /// /// Temporary Topic Destination object /// public const int STOMP_TEMPORARY_TOPIC = 2; /// /// Queue Destination object /// public const int STOMP_QUEUE = 3; /// /// Temporary Queue Destination object /// public const int STOMP_TEMPORARY_QUEUE = 4; // private const String TEMP_PREFIX = "{TD{"; // private const String TEMP_POSTFIX = "}TD}"; private const String COMPOSITE_SEPARATOR = ","; private String physicalName = ""; private StringDictionary options = null; private bool remoteDestination; /// /// The Default Constructor /// protected Destination() { } /// /// Construct the Destination with a defined physical name; /// /// protected Destination(String name) { SetPhysicalName(name); } public bool IsTopic { get { int destinationType = GetDestinationType(); return STOMP_TOPIC == destinationType || STOMP_TEMPORARY_TOPIC == destinationType; } } public bool IsQueue { get { int destinationType = GetDestinationType(); return STOMP_QUEUE == destinationType || STOMP_TEMPORARY_QUEUE == destinationType; } } public bool IsTemporary { get { int destinationType = GetDestinationType(); return STOMP_TEMPORARY_QUEUE == destinationType || STOMP_TEMPORARY_TOPIC == destinationType; } } /// /// Dictionary of name/value pairs representing option values specified /// in the URI used to create this Destination. A null value is returned /// if no options were specified. /// internal StringDictionary Options { get { return this.options; } } /// /// Indicates if the Desination was created by this client or was provided /// by the broker, most commonly the deinstinations provided by the broker /// are those that appear in the ReplyTo field of a Message. /// internal bool RemoteDestination { get { return this.remoteDestination; } set { this.remoteDestination = value; } } private void SetPhysicalName(string name) { this.physicalName = name; int p = name.IndexOf('?'); if(p >= 0) { String optstring = physicalName.Substring(p + 1); this.physicalName = name.Substring(0, p); options = URISupport.ParseQuery(optstring); } } /// /// /// /// public static Destination Transform(IDestination destination) { Destination result = null; if(destination != null) { if(destination is Destination) { result = (Destination) destination; } else { if(destination is ITemporaryQueue) { result = new TempQueue(((IQueue) destination).QueueName); } else if(destination is ITemporaryTopic) { result = new TempTopic(((ITopic) destination).TopicName); } else if(destination is IQueue) { result = new Queue(((IQueue) destination).QueueName); } else if(destination is ITopic) { result = new Topic(((ITopic) destination).TopicName); } } } return result; } /// /// Create a Destination using the name given, the type is determined by the /// value of the type parameter. /// /// /// /// /// public static Destination CreateDestination(int type, String pyhsicalName, bool remote) { Destination result = null; if(pyhsicalName == null) { return null; } else switch (type) { case STOMP_TOPIC: result = new Topic(pyhsicalName); break; case STOMP_TEMPORARY_TOPIC: result = new TempTopic(pyhsicalName); break; case STOMP_QUEUE: result = new Queue(pyhsicalName); break; default: result = new TempQueue(pyhsicalName); break; } result.RemoteDestination = remote; return result; } public static Destination ConvertToDestination(String text) { if(text == null) { return null; } int type = Destination.STOMP_QUEUE; string lowertext = text.ToLower(); bool remote = false; if(lowertext.StartsWith("/queue/")) { text = text.Substring("/queue/".Length); } else if(lowertext.StartsWith("/topic/")) { text = text.Substring("/topic/".Length); type = Destination.STOMP_TOPIC; } else if(lowertext.StartsWith("/temp-topic/")) { text = text.Substring("/temp-topic/".Length); type = Destination.STOMP_TEMPORARY_TOPIC; } else if(lowertext.StartsWith("/temp-queue/")) { text = text.Substring("/temp-queue/".Length); type = Destination.STOMP_TEMPORARY_QUEUE; } else if(lowertext.StartsWith("/remote-temp-topic/")) { text = text.Substring("/remote-temp-topic/".Length); type = Destination.STOMP_TEMPORARY_TOPIC; remote = true; } else if(lowertext.StartsWith("/remote-temp-queue/")) { text = text.Substring("/remote-temp-queue/".Length); type = Destination.STOMP_TEMPORARY_QUEUE; remote = true; } return Destination.CreateDestination(type, text, remote); } public static string ConvertToStompString(Destination destination) { if(destination == null) { return null; } string result; switch(destination.DestinationType) { case DestinationType.Topic: result = "/topic/" + destination.PhysicalName; break; case DestinationType.TemporaryTopic: result = (destination.RemoteDestination ? "/remote-temp-topic/" : "/temp-topic/") + destination.PhysicalName; break; case DestinationType.TemporaryQueue: result = (destination.RemoteDestination ? "/remote-temp-queue/" : "/temp-queue/") + destination.PhysicalName; break; default: result = "/queue/" + destination.PhysicalName; break; } return result; } /// /// /// object to compare /// 1 if this is less than o else 0 if they are equal or -1 if this is less than o public int CompareTo(Object o) { if(o is Destination) { return CompareTo((Destination) o); } return -1; } /// /// Lets sort by name first then lets sort topics greater than queues /// /// another destination to compare against /// 1 if this is less than o else 0 if they are equal or -1 if this is less than o public int CompareTo(Destination that) { int answer = 0; if(physicalName != that.physicalName) { if(physicalName == null) { return -1; } else if(that.physicalName == null) { return 1; } answer = physicalName.CompareTo(that.physicalName); } if(answer == 0) { if(IsTopic) { if(that.IsQueue) { return 1; } } else { if(that.IsTopic) { return -1; } } } return answer; } /// /// /// Returns the Destination type public abstract int GetDestinationType(); public String PhysicalName { get { return this.physicalName; } set { this.physicalName = value; } } /// /// Returns true if this destination represents a collection of /// destinations; allowing a set of destinations to be published to or subscribed /// from in one NMS operation. /// public bool IsComposite { get { return physicalName.IndexOf(COMPOSITE_SEPARATOR) > 0; } } /// /// /// string representation of this instance public override String ToString() { switch(DestinationType) { case DestinationType.Topic: return "topic://" + PhysicalName; case DestinationType.TemporaryTopic: return "temp-topic://" + PhysicalName; case DestinationType.TemporaryQueue: return "temp-queue://" + PhysicalName; default: return "queue://" + PhysicalName; } } /// /// /// hashCode for this instance public override int GetHashCode() { int answer = 37; if(this.physicalName != null) { answer = physicalName.GetHashCode(); } if(IsTopic) { answer ^= 0xfabfab; } return answer; } /// /// if the object passed in is equivalent, return true /// /// the object to compare /// true if this instance and obj are equivalent public override bool Equals(Object obj) { bool result = this == obj; if(!result && obj != null && obj is Destination) { Destination other = (Destination) obj; result = this.GetDestinationType() == other.GetDestinationType() && this.physicalName.Equals(other.physicalName); } return result; } /// /// Factory method to create a child destination if this destination is a composite /// /// /// the created Destination public abstract Destination CreateDestination(String name); public abstract DestinationType DestinationType { get; } public override Object Clone() { // Since we are a derived class use the base's Clone() // to perform the shallow copy. Since it is shallow it // will include our derived class. Since we are derived, // this method is an override. Destination o = (Destination) base.Clone(); // Now do the deep work required // If any new variables are added then this routine will // likely need updating return o; } } }