001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.activemq.command;
018    
019    import java.util.concurrent.atomic.AtomicReference;
020    
021    /**
022     * @openwire:marshaller code="110"
023     *
024     */
025    public class MessageId implements DataStructure, Comparable<MessageId> {
026    
027        public static final byte DATA_STRUCTURE_TYPE = CommandTypes.MESSAGE_ID;
028    
029        protected String textView;
030        protected ProducerId producerId;
031        protected long producerSequenceId;
032        protected long brokerSequenceId;
033    
034        private transient String key;
035        private transient int hashCode;
036    
037        private transient AtomicReference<Object> dataLocator = new AtomicReference<Object>();
038        private transient Object entryLocator;
039        private transient Object plistLocator;
040    
041        public MessageId() {
042            this.producerId = new ProducerId();
043        }
044    
045        public MessageId(ProducerInfo producerInfo, long producerSequenceId) {
046            this.producerId = producerInfo.getProducerId();
047            this.producerSequenceId = producerSequenceId;
048        }
049    
050        public MessageId(String messageKey) {
051            setValue(messageKey);
052        }
053    
054        public MessageId(String producerId, long producerSequenceId) {
055            this(new ProducerId(producerId), producerSequenceId);
056        }
057    
058        public MessageId(ProducerId producerId, long producerSequenceId) {
059            this.producerId = producerId;
060            this.producerSequenceId = producerSequenceId;
061        }
062    
063        /**
064         * Sets the value as a String
065         */
066        public void setValue(String messageKey) {
067            key = messageKey;
068            // Parse off the sequenceId
069            int p = messageKey.lastIndexOf(":");
070            if (p >= 0) {
071                producerSequenceId = Long.parseLong(messageKey.substring(p + 1));
072                messageKey = messageKey.substring(0, p);
073            } else {
074                throw new NumberFormatException();
075            }
076            producerId = new ProducerId(messageKey);
077        }
078    
079        /**
080         * Sets the transient text view of the message which will be ignored if the message is marshaled on a transport; so
081         * is only for in-JVM changes to accommodate foreign JMS message IDs
082         */
083        public void setTextView(String key) {
084            this.textView = key;
085        }
086    
087        /**
088         * @openwire:property version=10
089         * @return
090         */
091        public String getTextView() {
092            return textView;
093        }
094    
095        @Override
096        public byte getDataStructureType() {
097            return DATA_STRUCTURE_TYPE;
098        }
099    
100        @Override
101        public boolean equals(Object o) {
102            if (this == o) {
103                return true;
104            }
105            if (o == null || o.getClass() != getClass()) {
106                return false;
107            }
108    
109            MessageId id = (MessageId) o;
110            return producerSequenceId == id.producerSequenceId && producerId.equals(id.producerId);
111        }
112    
113        @Override
114        public int hashCode() {
115            if (hashCode == 0) {
116                hashCode = producerId.hashCode() ^ (int) producerSequenceId;
117            }
118            return hashCode;
119        }
120    
121        public String toProducerKey() {
122            if (textView == null) {
123                return toString();
124            } else {
125                return producerId.toString() + ":" + producerSequenceId;
126            }
127        }
128    
129        @Override
130        public String toString() {
131            if (key == null) {
132                if (textView != null) {
133                    if (textView.startsWith("ID:")) {
134                        key = textView;
135                    } else {
136                        key = "ID:" + textView;
137                    }
138                } else {
139                    key = producerId.toString() + ":" + producerSequenceId;
140                }
141            }
142            return key;
143        }
144    
145        /**
146         * @openwire:property version=1 cache=true
147         */
148        public ProducerId getProducerId() {
149            return producerId;
150        }
151    
152        public void setProducerId(ProducerId producerId) {
153            this.producerId = producerId;
154        }
155    
156        /**
157         * @openwire:property version=1
158         */
159        public long getProducerSequenceId() {
160            return producerSequenceId;
161        }
162    
163        public void setProducerSequenceId(long producerSequenceId) {
164            this.producerSequenceId = producerSequenceId;
165        }
166    
167        /**
168         * @openwire:property version=1
169         */
170        public long getBrokerSequenceId() {
171            return brokerSequenceId;
172        }
173    
174        public void setBrokerSequenceId(long brokerSequenceId) {
175            this.brokerSequenceId = brokerSequenceId;
176        }
177    
178        @Override
179        public boolean isMarshallAware() {
180            return false;
181        }
182    
183        public MessageId copy() {
184            MessageId copy = new MessageId(producerId, producerSequenceId);
185            copy.key = key;
186            copy.brokerSequenceId = brokerSequenceId;
187            copy.dataLocator = dataLocator;
188            copy.entryLocator = entryLocator;
189            copy.plistLocator = plistLocator;
190            copy.textView = textView;
191            return copy;
192        }
193    
194        /**
195         * @param
196         * @return
197         * @see java.lang.Comparable#compareTo(java.lang.Object)
198         */
199        @Override
200        public int compareTo(MessageId other) {
201            int result = -1;
202            if (other != null) {
203                result = this.toString().compareTo(other.toString());
204            }
205            return result;
206        }
207    
208        /**
209         * @return a locator which aids a message store in loading a message faster. Only used by the message stores.
210         */
211        public Object getDataLocator() {
212            return dataLocator.get();
213        }
214    
215        /**
216         * Sets a locator which aids a message store in loading a message faster. Only used by the message stores.
217         */
218        public void setDataLocator(Object value) {
219            this.dataLocator.set(value);
220        }
221    
222        public Object getEntryLocator() {
223            return entryLocator;
224        }
225    
226        public void setEntryLocator(Object entryLocator) {
227            this.entryLocator = entryLocator;
228        }
229    
230        public Object getPlistLocator() {
231            return plistLocator;
232        }
233    
234        public void setPlistLocator(Object plistLocator) {
235            this.plistLocator = plistLocator;
236        }
237    }