001/**
002 * Copyright 2005-2018 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 */
016package org.kuali.rice.kew.api.document;
017
018import org.apache.commons.lang.StringUtils;
019import org.joda.time.DateTime;
020import org.kuali.rice.core.api.CoreConstants;
021import org.kuali.rice.core.api.mo.AbstractDataTransferObject;
022import org.kuali.rice.core.api.mo.ModelBuilder;
023import org.kuali.rice.core.api.util.jaxb.DateTimeAdapter;
024import org.kuali.rice.core.api.util.jaxb.MapStringStringAdapter;
025import org.kuali.rice.kew.api.util.UserTextFilterForXml;
026import org.w3c.dom.Element;
027
028import javax.xml.bind.annotation.XmlAccessType;
029import javax.xml.bind.annotation.XmlAccessorType;
030import javax.xml.bind.annotation.XmlAnyElement;
031import javax.xml.bind.annotation.XmlElement;
032import javax.xml.bind.annotation.XmlRootElement;
033import javax.xml.bind.annotation.XmlType;
034import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
035import java.io.Serializable;
036import java.util.Collection;
037import java.util.Collections;
038import java.util.HashMap;
039import java.util.Map;
040
041@XmlRootElement(name = Document.Constants.ROOT_ELEMENT_NAME)
042@XmlAccessorType(XmlAccessType.NONE)
043@XmlType(name = Document.Constants.TYPE_NAME, propOrder = {
044    Document.Elements.DOCUMENT_ID,
045    Document.Elements.STATUS,
046    Document.Elements.DATE_CREATED,
047    Document.Elements.DATE_LAST_MODIFIED,
048    Document.Elements.DATE_APPROVED,
049    Document.Elements.DATE_FINALIZED,
050    Document.Elements.TITLE,
051    Document.Elements.APPLICATION_DOCUMENT_ID,
052    Document.Elements.INITIATOR_PRINCIPAL_ID,
053    Document.Elements.ROUTED_BY_PRINCIPAL_ID,
054    Document.Elements.DOCUMENT_TYPE_NAME,
055    Document.Elements.DOCUMENT_TYPE_ID,
056    Document.Elements.DOCUMENT_HANDLER_URL,
057    Document.Elements.APPLICATION_DOCUMENT_STATUS,
058    Document.Elements.APPLICATION_DOCUMENT_STATUS_DATE,
059    Document.Elements.VARIABLES,
060    CoreConstants.CommonElements.FUTURE_ELEMENTS
061})
062public final class Document extends AbstractDataTransferObject implements DocumentContract {
063
064        private static final long serialVersionUID = -6954090887747605047L;
065
066        @XmlElement(name = Elements.DOCUMENT_ID, required = true)
067    private final String documentId;
068
069    @XmlElement(name = Elements.STATUS, required = true)
070    private final String status;
071
072    @XmlElement(name = Elements.DATE_CREATED, required = true)
073    @XmlJavaTypeAdapter(DateTimeAdapter.class)
074    private final DateTime dateCreated;
075
076    @XmlElement(name = Elements.DATE_LAST_MODIFIED, required = true)
077    @XmlJavaTypeAdapter(DateTimeAdapter.class)
078    private final DateTime dateLastModified;
079
080    @XmlElement(name = Elements.DATE_APPROVED, required = false)
081    @XmlJavaTypeAdapter(DateTimeAdapter.class)
082    private final DateTime dateApproved;
083
084    @XmlElement(name = Elements.DATE_FINALIZED, required = false)
085    @XmlJavaTypeAdapter(DateTimeAdapter.class)
086    private final DateTime dateFinalized;
087
088    @XmlElement(name = Elements.TITLE, required = false)
089    private final String title;
090
091    @XmlElement(name = Elements.APPLICATION_DOCUMENT_ID, required = false)
092    private final String applicationDocumentId;
093
094    @XmlElement(name = Elements.INITIATOR_PRINCIPAL_ID, required = true)
095    private final String initiatorPrincipalId;
096
097    @XmlElement(name = Elements.ROUTED_BY_PRINCIPAL_ID, required = false)
098    private final String routedByPrincipalId;
099
100    @XmlElement(name = Elements.DOCUMENT_TYPE_NAME, required = true)
101    private final String documentTypeName;
102
103    @XmlElement(name = Elements.DOCUMENT_TYPE_ID, required = true)
104    private final String documentTypeId;
105
106    @XmlElement(name = Elements.DOCUMENT_HANDLER_URL, required = false)
107    private final String documentHandlerUrl;
108
109    @XmlElement(name = Elements.APPLICATION_DOCUMENT_STATUS, required = false)
110    private final String applicationDocumentStatus;
111
112    @XmlElement(name = Elements.APPLICATION_DOCUMENT_STATUS_DATE, required = false)
113    @XmlJavaTypeAdapter(DateTimeAdapter.class)
114    private final DateTime applicationDocumentStatusDate;
115
116    @XmlElement(name = Elements.VARIABLES, required = false)
117    @XmlJavaTypeAdapter(MapStringStringAdapter.class)
118    private final Map<String, String> variables;
119
120    @SuppressWarnings("unused")
121    @XmlAnyElement
122    private final Collection<Element> _futureElements = null;
123
124    /**
125     * Private constructor used only by JAXB.
126     */
127    private Document() {
128        this.documentId = null;
129        this.status = null;
130        this.dateCreated = null;
131        this.dateLastModified = null;
132        this.dateApproved = null;
133        this.dateFinalized = null;
134        this.title = null;
135        this.applicationDocumentId = null;
136        this.initiatorPrincipalId = null;
137        this.routedByPrincipalId = null;
138        this.documentTypeName = null;
139        this.documentTypeId = null;
140        this.documentHandlerUrl = null;
141        this.applicationDocumentStatus = null;
142        this.applicationDocumentStatusDate = null;
143        this.variables = null;
144    }
145
146    private Document(Builder builder) {
147        this.documentId = builder.getDocumentId();
148        this.status = builder.getStatus().getCode();
149        this.dateCreated = builder.getDateCreated();
150        this.dateLastModified = builder.getDateLastModified();
151        this.dateApproved = builder.getDateApproved();
152        this.dateFinalized = builder.getDateFinalized();
153        this.title = builder.getTitle();
154        this.applicationDocumentId = builder.getApplicationDocumentId();
155        this.initiatorPrincipalId = builder.getInitiatorPrincipalId();
156        this.routedByPrincipalId = builder.getRoutedByPrincipalId();
157        this.documentTypeName = builder.getDocumentTypeName();
158        this.documentTypeId = builder.getDocumentTypeId();
159        this.documentHandlerUrl = builder.getDocumentHandlerUrl();
160        this.applicationDocumentStatus = builder.getApplicationDocumentStatus();
161        this.applicationDocumentStatusDate = builder.getApplicationDocumentStatusDate();
162        this.variables = new HashMap<String, String>(builder.getVariables());
163    }
164
165    @Override
166    public String getDocumentId() {
167        return this.documentId;
168    }
169
170    @Override
171    public DocumentStatus getStatus() {
172        if (StringUtils.isBlank(this.status)) {
173                throw new IllegalStateException("Status should not be null");
174        }
175                return DocumentStatus.fromCode(this.status);
176    }
177
178    @Override
179    public DateTime getDateCreated() {
180        return this.dateCreated;
181    }
182
183    @Override
184    public DateTime getDateLastModified() {
185        return this.dateLastModified;
186    }
187
188    @Override
189    public DateTime getDateApproved() {
190        return this.dateApproved;
191    }
192
193    @Override
194    public DateTime getDateFinalized() {
195        return this.dateFinalized;
196    }
197
198    @Override
199    public String getTitle() {
200        return this.title;
201    }
202
203    @Override
204    public String getApplicationDocumentId() {
205        return this.applicationDocumentId;
206    }
207
208    @Override
209    public String getInitiatorPrincipalId() {
210        return this.initiatorPrincipalId;
211    }
212
213    @Override
214    public String getRoutedByPrincipalId() {
215        return this.routedByPrincipalId;
216    }
217
218    @Override
219    public String getDocumentTypeName() {
220        return this.documentTypeName;
221    }
222
223    @Override
224    public String getDocumentTypeId() {
225        return this.documentTypeId;
226    }
227
228    @Override
229    public String getDocumentHandlerUrl() {
230        return this.documentHandlerUrl;
231    }
232
233    @Override
234    public String getApplicationDocumentStatus() {
235        return this.applicationDocumentStatus;
236    }
237
238    @Override
239    public DateTime getApplicationDocumentStatusDate() {
240        return this.applicationDocumentStatusDate;
241    }
242
243    @Override
244    public Map<String, String> getVariables() {
245        return Collections.unmodifiableMap(this.variables);
246    }
247
248    /**
249     * A builder which can be used to construct {@link Document} instances.  Enforces the constraints of the {@link DocumentContract}.
250     *
251     */
252    public final static class Builder
253        implements Serializable, ModelBuilder, DocumentContract
254    {
255
256                private static final long serialVersionUID = -1584497024880308500L;
257
258                private String documentId;
259        private DocumentStatus status;
260        private DateTime dateCreated;
261        private DateTime dateLastModified;
262        private DateTime dateApproved;
263        private DateTime dateFinalized;
264        private String title;
265        private String applicationDocumentId;
266        private String initiatorPrincipalId;
267        private String routedByPrincipalId;
268        private String documentTypeName;
269        private String documentTypeId;
270        private String documentHandlerUrl;
271        private String applicationDocumentStatus;
272        private DateTime applicationDocumentStatusDate;
273        private Map<String, String> variables;
274
275        private Builder(String documentId, DocumentStatus status, DateTime dateCreated, String initiatorPrincipalId, String documentTypeName, String documentTypeId) {
276            setDocumentId(documentId);
277            setStatus(status);
278            setDateCreated(dateCreated);
279            setTitle("");
280            setInitiatorPrincipalId(initiatorPrincipalId);
281            setDocumentTypeName(documentTypeName);
282            setDocumentTypeId(documentTypeId);
283            setVariables(new HashMap<String, String>());
284        }
285
286        public static Builder create(String documentId, DocumentStatus status, DateTime dateCreated, String initiatorPrincipalId, String documentTypeName, String documentTypeId) {
287            return new Builder(documentId, status, dateCreated, initiatorPrincipalId, documentTypeName, documentTypeId);
288        }
289
290        public static Builder create(String documentId, String initiatorPrinicpalId, String documentTypeName, String documentTypeId) {
291                return new Builder(documentId, DocumentStatus.INITIATED, new DateTime(), initiatorPrinicpalId, documentTypeName, documentTypeId);
292        }
293
294        public static Builder create(DocumentContract contract) {
295            if (contract == null) {
296                throw new IllegalArgumentException("contract was null");
297            }
298            Builder builder = create(
299                        contract.getDocumentId(),
300                        contract.getStatus(),
301                        contract.getDateCreated(),
302                        contract.getInitiatorPrincipalId(),
303                        contract.getDocumentTypeName(),
304                        contract.getDocumentTypeId()
305            );
306            builder.setDateLastModified(contract.getDateLastModified());
307            builder.setDateApproved(contract.getDateApproved());
308            builder.setDateFinalized(contract.getDateFinalized());
309            builder.setTitle(contract.getTitle());
310            builder.setApplicationDocumentId(contract.getApplicationDocumentId());
311            builder.setRoutedByPrincipalId(contract.getRoutedByPrincipalId());
312            builder.setDocumentHandlerUrl(contract.getDocumentHandlerUrl());
313            builder.setApplicationDocumentStatus(contract.getApplicationDocumentStatus());
314            builder.setApplicationDocumentStatusDate(contract.getApplicationDocumentStatusDate());
315            builder.setVariables(new HashMap<String, String>(contract.getVariables()));
316            return builder;
317        }
318
319        public Document build() {
320            return new Document(this);
321        }
322
323        @Override
324        public String getDocumentId() {
325            return this.documentId;
326        }
327
328        @Override
329        public DocumentStatus getStatus() {
330            return this.status;
331        }
332
333        @Override
334        public DateTime getDateCreated() {
335            return this.dateCreated;
336        }
337
338        @Override
339        public DateTime getDateLastModified() {
340            return this.dateLastModified;
341        }
342
343        @Override
344        public DateTime getDateApproved() {
345            return this.dateApproved;
346        }
347
348        @Override
349        public DateTime getDateFinalized() {
350            return this.dateFinalized;
351        }
352
353        @Override
354        public String getTitle() {
355            return this.title;
356        }
357
358        @Override
359        public String getApplicationDocumentId() {
360            return this.applicationDocumentId;
361        }
362
363        @Override
364        public String getInitiatorPrincipalId() {
365            return this.initiatorPrincipalId;
366        }
367
368        @Override
369        public String getRoutedByPrincipalId() {
370            return this.routedByPrincipalId;
371        }
372
373        @Override
374        public String getDocumentTypeName() {
375            return this.documentTypeName;
376        }
377
378        @Override
379        public String getDocumentTypeId() {
380            return this.documentTypeId;
381        }
382
383        @Override
384        public String getDocumentHandlerUrl() {
385            return this.documentHandlerUrl;
386        }
387
388        @Override
389        public String getApplicationDocumentStatus() {
390            return this.applicationDocumentStatus;
391        }
392
393        @Override
394        public DateTime getApplicationDocumentStatusDate() {
395            return this.applicationDocumentStatusDate;
396        }
397
398        @Override
399        public Map<String, String> getVariables() {
400            return this.variables;
401        }
402
403        public void setDocumentId(String documentId) {
404            if (StringUtils.isBlank(documentId)) {
405                throw new IllegalArgumentException("documentId was null or blank");
406            }
407            this.documentId = documentId;
408        }
409
410        public void setStatus(DocumentStatus status) {
411            if (status == null) {
412                throw new IllegalArgumentException("status was null");
413            }
414            this.status = status;
415        }
416
417        public void setDateCreated(DateTime dateCreated) {
418            if (dateCreated == null) {
419                throw new IllegalArgumentException("dateCreated was null");
420            }
421            this.dateCreated = dateCreated;
422        }
423
424        public void setDateLastModified(DateTime dateLastModified) {
425            this.dateLastModified = dateLastModified;
426        }
427
428        public void setDateApproved(DateTime dateApproved) {
429            this.dateApproved = dateApproved;
430        }
431
432        public void setDateFinalized(DateTime dateFinalized) {
433            this.dateFinalized = dateFinalized;
434        }
435
436        public void setTitle(String title) {
437                if (title == null) {
438                        title = "";
439                }
440            this.title = UserTextFilterForXml.cleanInvalidXmlChars(title);
441        }
442
443        public void setApplicationDocumentId(String applicationDocumentId) {
444            this.applicationDocumentId = applicationDocumentId;
445        }
446
447        public void setInitiatorPrincipalId(String initiatorPrincipalId) {
448            if (StringUtils.isBlank(initiatorPrincipalId)) {
449                throw new IllegalArgumentException("initiatorPrincipalId was null or blank");
450            }
451            this.initiatorPrincipalId = initiatorPrincipalId;
452        }
453
454        public void setRoutedByPrincipalId(String routedByPrincipalId) {
455            this.routedByPrincipalId = routedByPrincipalId;
456        }
457
458        public void setDocumentTypeName(String documentTypeName) {
459                if (StringUtils.isBlank(documentTypeName)) {
460                throw new IllegalArgumentException("documentTypeName was null or blank");
461            }
462            this.documentTypeName = documentTypeName;
463        }
464
465        public void setDocumentTypeId(String documentTypeId) {
466                if (StringUtils.isBlank(documentTypeId)) {
467                throw new IllegalArgumentException("documentTypeId was null or blank");
468            }
469            this.documentTypeId = documentTypeId;
470        }
471
472        public void setDocumentHandlerUrl(String documentHandlerUrl) {
473            this.documentHandlerUrl = documentHandlerUrl;
474        }
475
476        public void setApplicationDocumentStatus(String applicationDocumentStatus) {
477            this.applicationDocumentStatus = applicationDocumentStatus;
478        }
479
480        public void setApplicationDocumentStatusDate(DateTime applicationDocumentStatusDate) {
481            this.applicationDocumentStatusDate = applicationDocumentStatusDate;
482        }
483
484        public void setVariables(Map<String, String> variables) {
485                if (variables == null) {
486                        variables = new HashMap<String, String>();
487                }
488            this.variables = variables;
489        }
490
491    }
492
493    /**
494     * Defines some internal constants used on this class.
495     */
496    static class Constants {
497        final static String ROOT_ELEMENT_NAME = "document";
498        final static String TYPE_NAME = "DocumentType";
499    }
500
501    /**
502     * A private class which exposes constants which define the XML element names to use when this object is marshalled to XML.
503     */
504    static class Elements {
505        final static String DOCUMENT_ID = "documentId";
506        final static String STATUS = "status";
507        final static String DATE_CREATED = "dateCreated";
508        final static String DATE_LAST_MODIFIED = "dateLastModified";
509        final static String DATE_APPROVED = "dateApproved";
510        final static String DATE_FINALIZED = "dateFinalized";
511        final static String TITLE = "title";
512        final static String APPLICATION_DOCUMENT_ID = "applicationDocumentId";
513        final static String INITIATOR_PRINCIPAL_ID = "initiatorPrincipalId";
514        final static String ROUTED_BY_PRINCIPAL_ID = "routedByPrincipalId";
515        final static String DOCUMENT_TYPE_NAME = "documentTypeName";
516        final static String DOCUMENT_TYPE_ID = "documentTypeId";
517        final static String DOCUMENT_HANDLER_URL = "documentHandlerUrl";
518        final static String APPLICATION_DOCUMENT_STATUS = "applicationDocumentStatus";
519        final static String APPLICATION_DOCUMENT_STATUS_DATE = "applicationDocumentStatusDate";
520        final static String VARIABLES = "variables";
521    }
522
523}
524