View Javadoc

1   /* This file is part of COPAL (COntext Provisioning for All).
2    *
3    * COPAL is a part of SM4All (Smart hoMes for All) project.
4    *
5    * COPAL is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU Lesser General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * COPAL is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public License
16   * along with COPAL. If not, see <http://www.gnu.org/licenses/>.
17   */
18  package at.ac.tuwien.infosys.sm4all.copal.api.processor;
19  
20  import java.text.MessageFormat;
21  import java.util.Arrays;
22  import java.util.Collections;
23  import java.util.HashSet;
24  import java.util.Set;
25  import org.apache.log4j.Logger;
26  import at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEvent;
27  import at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEventAction;
28  import at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEventType;
29  
30  /**
31   * Class which defines action which a {@link ContextProcessor} can process. The
32   * name and the input of processor action uniquely defines the
33   * {@link ContextEventAction} and its associated input {@link ContextEventType}
34   * using same values of {@link ContextEventAction#getName()} and
35   * {@link ContextEventType#getName()} respectively. Each action also can define
36   * the names of {@link ContextEventType} of {@link ContextEvent}s returned by
37   * the {@link ContextProcessor} after processing a {@link ContextEvent}.
38   * 
39   * @author sanjin
40   */
41  public class ProcessorAction {
42  
43      private static final Logger LOGGER = Logger.getLogger(ProcessorAction.class);
44  
45      private final String name;
46      private final String input;
47      private final Set<String> output;
48  
49      /**
50       * Creates an instance of {@link ProcessorAction}. The <code>name</code> is
51       * the globally unique name of the {@link ContextEventAction} and cannot be
52       * <code>null</code>. The <code>input</code> is the globally unique name of
53       * the input {@link ContextEventType} and also cannot be <code>null</code>.
54       * The <code>output</code> are globally unique names of
55       * {@link ContextEventType}s of {@link ContextEvent}s returned by a
56       * {@link ContextProcessor} as result of processing this
57       * {@link ProcessorAction}. If <code>output</code> is <code>null</code> or
58       * an empty array then the {@link ContextProcessor} will not produce a
59       * result.
60       * 
61       * @param name the globally unique name of the {@link ContextEventAction}.
62       * @param input the globally unique name of the input
63       *        {@link ContextEventType}.
64       * @param output the globally unique names of output
65       *        {@link ContextEventType}s.
66       * @throws NullPointerException if specified name or input is
67       *         <code>null</code>.
68       * @throws IllegalArgumentException if specified name or input is an empty
69       *         or blank string.
70       */
71      public ProcessorAction(final String name, final String input,
72              final String... output) {
73          super();
74  
75          if (null == name) {
76              throw new NullPointerException("Name cannot be null.");
77          }
78          if (name.trim().isEmpty()) {
79              throw new IllegalArgumentException(
80                      "Name cannot be an empty or blank string.");
81          }
82          if (null == input) {
83              throw new NullPointerException("Input cannot be null.");
84          }
85          if (input.trim().isEmpty()) {
86              throw new IllegalArgumentException(
87                      "Input cannot be an empty or blank string.");
88          }
89  
90          this.name = name;
91          this.input = input;
92          if ((null != output) && (output.length > 0)) {
93              this.output = Collections.unmodifiableSet(new HashSet<String>(
94                      Arrays.asList(output)));
95          } else {
96              this.output = Collections.unmodifiableSet(new HashSet<String>());
97          }
98  
99          if (LOGGER.isDebugEnabled()) {
100             LOGGER.debug(MessageFormat.format(
101                     "Created processor action ''{0}''.", this.name));
102         }
103     }
104 
105     /**
106      * @return the globally unique name of the {@link ContextEventAction}.
107      */
108     public String getName() {
109         return this.name;
110     }
111 
112     /**
113      * Returns the globally unique name of the input {@link ContextEventType}.
114      * 
115      * @return the globally unique name of the input {@link ContextEventType}.
116      */
117     public String getInput() {
118         return this.input;
119     }
120 
121     /**
122      * Returns the globally unique name of the output {@link ContextEventType}.
123      * 
124      * @return the globally unique name of the output {@link ContextEventType}.
125      */
126     public String[] getOutput() {
127         return this.output.toArray(new String[this.output.size()]);
128     }
129 
130     /**
131      * Returns if this {@link ProcessorAction} produces a result.
132      * 
133      * @return if this {@link ProcessorAction} produces a result.
134      */
135     public boolean hasOutput() {
136         return !this.output.isEmpty();
137     }
138 
139     /**
140      * Returns hash code for this {@link ProcessorAction}. The hash code for a
141      * {@link ProcessorAction} object is computed as:
142      * 
143      * <pre>
144      * name * 31 + input
145      * </pre>
146      * 
147      * using integer arithmetic.
148      * 
149      * @return a hash code value for this {@link ProcessorAction}.
150      */
151     @Override
152     public int hashCode() {
153         return (this.name.hashCode() * 31) + this.input.hashCode();
154     }
155 
156     /**
157      * Compares this {@link ProcessorAction} to the specified object. The result
158      * is <code>true</code> if and only if the argument is not <code>null</code>
159      * and is a {@link ProcessorAction} object that has same name, input and
160      * output as this {@link ProcessorAction}.
161      * 
162      * @param obj the {@link Object} to compare this {@link ProcessorAction}
163      *        against.
164      * @return <code>true</code> if {@link ProcessorAction}s are equal;
165      *         <code>false</code> otherwise.
166      */
167     @Override
168     public boolean equals(final Object obj) {
169         boolean result = false;
170 
171         if (null != obj) {
172             if (this == obj) {
173                 result = true;
174             } else if (obj instanceof ProcessorAction) {
175                 final ProcessorAction other = (ProcessorAction) obj;
176 
177                 result = this.name.equals(other.name)
178                         && this.input.equals(other.input);
179                 result = result
180                         && ((hasOutput() && this.output.equals(other.output)) || (!hasOutput() && !other.hasOutput()));
181             }
182         }
183 
184         return result;
185     }
186 }