001 /**
002 * Copyright 2005-2011 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.krms.api.repository.agenda;
017
018 import org.apache.commons.lang.StringUtils;
019 import org.kuali.rice.core.api.CoreConstants;
020 import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
021 import org.kuali.rice.core.api.mo.ModelBuilder;
022 import org.kuali.rice.core.api.util.jaxb.MapStringStringAdapter;
023 import org.kuali.rice.krms.api.repository.context.ContextDefinitionContract;
024
025 import javax.xml.bind.annotation.XmlAccessType;
026 import javax.xml.bind.annotation.XmlAccessorType;
027 import javax.xml.bind.annotation.XmlAnyElement;
028 import javax.xml.bind.annotation.XmlElement;
029 import javax.xml.bind.annotation.XmlRootElement;
030 import javax.xml.bind.annotation.XmlType;
031 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
032 import java.io.Serializable;
033 import java.util.Collection;
034 import java.util.Collections;
035 import java.util.HashMap;
036 import java.util.Map;
037
038 /**
039 * Concrete model object implementation of KRMS Repository Agenda
040 * immutable.
041 * Instances of Agenda can be (un)marshalled to and from XML.
042 *
043 * @see AgendaDefinitionContract
044 */
045 @XmlRootElement(name = AgendaDefinition.Constants.ROOT_ELEMENT_NAME)
046 @XmlAccessorType(XmlAccessType.NONE)
047 @XmlType(name = AgendaDefinition.Constants.TYPE_NAME, propOrder = {
048 AgendaDefinition.Elements.AGENDA_ID,
049 AgendaDefinition.Elements.NAME,
050 AgendaDefinition.Elements.TYPE_ID,
051 AgendaDefinition.Elements.CONTEXT_ID,
052 AgendaDefinition.Elements.ACTIVE,
053 AgendaDefinition.Elements.FIRST_ITEM_ID,
054 AgendaDefinition.Elements.ATTRIBUTES,
055 CoreConstants.CommonElements.VERSION_NUMBER,
056 CoreConstants.CommonElements.FUTURE_ELEMENTS
057 })
058 public final class AgendaDefinition extends AbstractDataTransferObject implements AgendaDefinitionContract {
059 private static final long serialVersionUID = 2783959459503209577L;
060
061 @XmlElement(name = Elements.AGENDA_ID, required = false)
062 private final String id;
063
064 @XmlElement(name = Elements.NAME, required = true)
065 private final String name;
066
067 @XmlElement(name = Elements.TYPE_ID, required = false)
068 private final String typeId;
069
070 @XmlElement(name = Elements.CONTEXT_ID, required = true)
071 private final String contextId;
072
073 @XmlElement(name = Elements.ACTIVE, required = false)
074 private final boolean active;
075
076 @XmlElement(name = Elements.FIRST_ITEM_ID, required = false)
077 private final String firstItemId;
078
079 @XmlElement(name = Elements.ATTRIBUTES, required = false)
080 @XmlJavaTypeAdapter(value = MapStringStringAdapter.class)
081 private final Map<String, String> attributes;
082
083 @XmlElement(name = CoreConstants.CommonElements.VERSION_NUMBER, required = false)
084 private final Long versionNumber;
085
086 @SuppressWarnings("unused")
087 @XmlAnyElement
088 private final Collection<org.w3c.dom.Element> _futureElements = null;
089
090 /**
091 * This constructor should never be called.
092 * It is only present for use during JAXB unmarshalling.
093 */
094 private AgendaDefinition() {
095 this.id = null;
096 this.name = null;
097 this.typeId = null;
098 this.contextId = null;
099 this.active = false;
100 this.firstItemId = null;
101 this.attributes = null;
102 this.versionNumber = null;
103 }
104
105 /**
106 * Constructs a KRMS Repository Agenda object from the given builder.
107 * This constructor is private and should only ever be invoked from the builder.
108 *
109 * @param builder the Builder from which to construct the Agenda
110 */
111 private AgendaDefinition(Builder builder) {
112 this.id = builder.getId();
113 this.name = builder.getName();
114 this.typeId = builder.getTypeId();
115 this.contextId = builder.getContextId();
116 this.active = builder.isActive();
117 this.firstItemId = builder.getFirstItemId();
118 if (builder.getAttributes() != null){
119 this.attributes = Collections.unmodifiableMap(new HashMap<String, String>(builder.getAttributes()));
120 } else {
121 this.attributes = null;
122 }
123 this.versionNumber = builder.getVersionNumber();
124 }
125
126 @Override
127 public String getId() {
128 return this.id;
129 }
130
131 @Override
132 public String getName() {
133 return this.name;
134 }
135
136 @Override
137 public String getTypeId() {
138 return this.typeId;
139 }
140
141 @Override
142 public String getContextId(){
143 return this.contextId;
144 }
145
146 @Override
147 public boolean isActive() {
148 return this.active;
149 }
150
151 @Override
152 public String getFirstItemId(){
153 return this.firstItemId;
154 }
155
156 @Override
157 public Map<String, String> getAttributes() {
158 return this.attributes;
159 }
160
161 @Override
162 public Long getVersionNumber() {
163 return versionNumber;
164 }
165
166 /**
167 * This builder is used to construct instances of KRMS Repository Agenda. It enforces the constraints of the {@link AgendaDefinitionContract}.
168 */
169 public static class Builder implements AgendaDefinitionContract, ModelBuilder, Serializable {
170
171 private static final long serialVersionUID = -8862851720709537839L;
172
173 private String id;
174 private String name;
175 private String typeId;
176 private String contextId;
177 private boolean active;
178 private String firstItemId;
179 private Map<String, String> attributes;
180 private Long versionNumber;
181
182 /**
183 * Private constructor for creating a builder with all of it's required attributes.
184 */
185 private Builder(String id, String name, String typeId, String contextId) {
186 setId(id);
187 setName(name);
188 setTypeId(typeId);
189 setContextId(contextId);
190 setActive(true);
191 setAttributes(new HashMap<String, String>());
192 }
193
194 public static Builder create(String id, String name, String typeId, String contextId){
195 return new Builder(id, name, typeId, contextId);
196 }
197 /**
198 * Creates a builder by populating it with data from the given {@link AgendaDefinitionContract}.
199 *
200 * @param contract the contract from which to populate this builder
201 * @return an instance of the builder populated with data from the contract
202 */
203 public static Builder create(AgendaDefinitionContract contract) {
204 if (contract == null) {
205 throw new IllegalArgumentException("contract is null");
206 }
207 Builder builder = new Builder(contract.getId(), contract.getName(), contract.getTypeId(), contract.getContextId());
208 builder.setActive(contract.isActive());
209 builder.setFirstItemId( contract.getFirstItemId() );
210 if (contract.getAttributes() != null) {
211 builder.setAttributes(new HashMap<String, String>(contract.getAttributes()));
212 }
213 builder.setVersionNumber(contract.getVersionNumber());
214 return builder;
215 }
216
217 /**
218 * Sets the value of the id on this builder to the given value.
219 *
220 * @param id the id value to set, must not be null or blank
221 * @throws IllegalArgumentException if the id is null or blank
222 */
223
224 public void setId(String agendaId) {
225 if (agendaId != null && StringUtils.isBlank(agendaId)) {
226 throw new IllegalArgumentException("agenda ID must be null or non-blank");
227 }
228 this.id = agendaId;
229 }
230
231 public void setName(String name) {
232 if (StringUtils.isBlank(name)) {
233 throw new IllegalArgumentException("name is blank");
234 }
235 this.name = name;
236 }
237
238 public void setTypeId(String typeId) {
239 this.typeId = typeId;
240 }
241
242 public void setContextId(String contextId) {
243 if (StringUtils.isBlank(contextId)) {
244 throw new IllegalArgumentException("context id is blank");
245 }
246 this.contextId = contextId;
247 }
248
249 public void setActive(boolean active) {
250 this.active = active;
251 }
252
253 public void setFirstItemId(String firstItemId) {
254 this.firstItemId = firstItemId;
255 }
256
257 public void setAttributes(Map<String, String> attributes){
258 if (attributes == null){
259 this.attributes = Collections.emptyMap();
260 }
261 this.attributes = Collections.unmodifiableMap(attributes);
262 }
263
264 /**
265 * Sets the version number for the style that will be returned by this
266 * builder.
267 *
268 * <p>In general, this value should not be manually set on the builder,
269 * but rather copied from an existing {@link ContextDefinitionContract} when
270 * invoking {@link Builder#create(ContextDefinitionContract)}.
271 *
272 * @param versionNumber the version number to set
273 */
274 public void setVersionNumber(Long versionNumber){
275 this.versionNumber = versionNumber;
276 }
277
278 @Override
279 public String getId() {
280 return id;
281 }
282
283 @Override
284 public String getName() {
285 return name;
286 }
287
288 @Override
289 public String getTypeId() {
290 return typeId;
291 }
292
293 @Override
294 public String getContextId() {
295 return contextId;
296 }
297
298 @Override
299 public boolean isActive() {
300 return active;
301 }
302
303 @Override
304 public String getFirstItemId() {
305 return firstItemId;
306 }
307
308 @Override
309 public Map<String, String> getAttributes() {
310 return attributes;
311 }
312
313 @Override
314 public Long getVersionNumber() {
315 return versionNumber;
316 }
317
318 /**
319 * Builds an instance of a Agenda based on the current state of the builder.
320 *
321 * @return the fully-constructed Agenda
322 */
323 @Override
324 public AgendaDefinition build() {
325 return new AgendaDefinition(this);
326 }
327
328 }
329
330 /**
331 * Defines some constants used on this class.
332 */
333 public static class Constants {
334 final static String ROOT_ELEMENT_NAME = "agenda";
335 final static String TYPE_NAME = "AgendaType";
336 final static String[] HASH_CODE_EQUALS_EXCLUDE = { "_furutreElements" };
337 public final static String EVENT = "Event"; // key for event attribute
338 }
339
340 /**
341 * A private class which exposes constants which define the XML element names to use
342 * when this object is marshalled to XML.
343 */
344 public static class Elements {
345 final static String AGENDA_ID = "id";
346 final static String NAME = "name";
347 final static String TYPE_ID = "typeId";
348 final static String CONTEXT_ID = "contextId";
349 final static String ACTIVE = "active";
350 final static String FIRST_ITEM_ID = "firstItemId";
351 final static String ATTRIBUTES = "attributes";
352 final static String ATTRIBUTE = "attribute";
353 }
354
355 }