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.camel;
018    
019    import java.util.ArrayList;
020    import java.util.HashMap;
021    import java.util.List;
022    import java.util.Map;
023    
024    /**
025     * Represents an instance and a type safe registry of well known Camel Exchange properties.
026     * <p/>
027     * <b>Usage pattern:</b>
028     * <br/>In your code register a property that you wish to pass via Camel Exchange:
029     * <pre>
030     *      public static final ExchangeProperty<Boolean> myProperty =
031     *            new ExchangeProperty<Boolean>("myProperty", "org.apache.myproject.mypackage.myproperty", Boolean.class);
032     *
033     *  Then in your code set this property's value:
034     *      myProperty.set(exchange, Boolean.TRUE);
035     *
036     *  Check the value of this property where required:
037     *      ExchangeProperty<?> property = ExchangeProperty.get("myProperty");
038     *      if (property != null && property.get(exchange) == Boolean.TRUE) {
039     *           // do your thing ...
040     *       }
041     *  Or
042     *      Boolean value = myProperty.get(exchange);
043     *      if (value == Boolean.TRUE) {
044     *          // do your thing
045     *      }
046     *
047     *  When your code no longer requires this property then deregister it:
048     *      ExchangeProperty.deregister(myProperty);
049     *  Or
050     *      ExchangeProperty.deregister("myProperty");
051     *  </pre>
052     *
053     *  <b>Note:</b> that if ExchangeProperty instance get or set methods are used then type checks
054     *  of property's value are performed and a runtime exception can be thrown if type
055     *  safety is violated.
056     */
057    public class ExchangeProperty<T> {
058    
059        private static final List<ExchangeProperty<?>> VALUES =
060            new ArrayList<ExchangeProperty<?>>();
061    
062        private static final Map<String, ExchangeProperty<?>> LITERAL_MAP =
063            new HashMap<String, ExchangeProperty<?>>();
064    
065        private static final Map<String, ExchangeProperty<?>> NAME_MAP =
066            new HashMap<String, ExchangeProperty<?>>();
067    
068        private final String literal;
069        private final String name;
070        private final Class<T> type;
071    
072        public ExchangeProperty(String literal, String name, Class<T> type) {
073            this.literal = literal;
074            this.name = name;
075            this.type = type;
076            register(this);
077        }
078    
079        public String literal() {
080            return literal;
081        }
082    
083        public String name() {
084            return name;
085        }
086    
087        public Class<T> type() {
088            return type;
089        }
090    
091        public T get(Exchange exchange) {
092            return exchange.getProperty(name, type);
093        }
094    
095        public static ExchangeProperty<?> get(String literal) {
096            return LITERAL_MAP.get(literal);
097        }
098    
099        public static ExchangeProperty<?> getByName(String name) {
100            return NAME_MAP.get(name);
101        }
102    
103        public T set(Exchange exchange, T value) {
104            T oldValue = get(exchange);
105            exchange.setProperty(name, value);
106            return oldValue;
107        }
108    
109        public T remove(Exchange exchange) {
110            T oldValue = get(exchange);
111            exchange.removeProperty(name);
112            return oldValue;
113        }
114    
115        @Override
116        public String toString() {
117            return type().getCanonicalName() + " " + name + " (" + literal() + ")";
118        }
119    
120        public static synchronized void register(ExchangeProperty<?> property) {
121            ExchangeProperty<?> existingProperty = LITERAL_MAP.get(property.literal());
122            if (existingProperty != null && existingProperty != property) {
123                throw new RuntimeCamelException("An Exchange Property '" + property.literal()
124                        + "' has already been registered; its traits are: " + existingProperty.toString());
125            }
126            VALUES.add(property);
127            LITERAL_MAP.put(property.literal(), property);
128            NAME_MAP.put(property.name(), property);
129        }
130    
131        public static synchronized void deregister(ExchangeProperty<?> property) {
132            if (property != null) {
133                VALUES.remove(property);
134                LITERAL_MAP.remove(property.literal());
135                NAME_MAP.put(property.name(), property);
136            }
137        }
138    
139        public static synchronized void deregister(String literal) {
140            ExchangeProperty<?> property = LITERAL_MAP.get(literal);
141            if (property != null) {
142                VALUES.remove(property);
143                LITERAL_MAP.remove(property.literal());
144                NAME_MAP.put(property.name(), property);
145            }
146        }
147    
148        public static synchronized ExchangeProperty<?>[] values() {
149            return VALUES.toArray(new ExchangeProperty[0]);
150        }
151    
152    }