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 }