001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Julien Anguenot
016 *     Thierry Delprat
017 *     Florent Guillaume
018 */
019
020package org.nuxeo.ecm.platform.audit.impl;
021
022import java.util.Date;
023import java.util.HashMap;
024import java.util.Map;
025
026import javax.persistence.CascadeType;
027import javax.persistence.Column;
028import javax.persistence.Entity;
029import javax.persistence.GeneratedValue;
030import javax.persistence.GenerationType;
031import javax.persistence.Id;
032import javax.persistence.JoinColumn;
033import javax.persistence.JoinTable;
034import javax.persistence.MapKey;
035import javax.persistence.NamedQueries;
036import javax.persistence.NamedQuery;
037import javax.persistence.OneToMany;
038import javax.persistence.Table;
039import javax.persistence.Temporal;
040import javax.persistence.TemporalType;
041import javax.persistence.Transient;
042
043import org.apache.commons.lang.builder.ToStringBuilder;
044import org.nuxeo.ecm.core.api.DocumentModel;
045import org.nuxeo.ecm.core.api.DocumentRef;
046import org.nuxeo.ecm.platform.audit.api.ExtendedInfo;
047import org.nuxeo.ecm.platform.audit.api.LogEntry;
048import org.nuxeo.ecm.platform.audit.api.comment.UIAuditComment;
049
050/**
051 * Log entry implementation.
052 */
053@Entity(name = "LogEntry")
054@NamedQueries({
055        @NamedQuery(name = "LogEntry.removeByEventIdAndPath", query = "delete LogEntry log where log.eventId = :eventId and log.docPath like :pathPattern"),
056        @NamedQuery(name = "LogEntry.findByDocument", query = "from LogEntry log where log.docUUID=:docUUID ORDER BY log.eventDate DESC"),
057        @NamedQuery(name = "LogEntry.findAll", query = "from LogEntry log order by log.eventDate DESC"),
058        @NamedQuery(name = "LogEntry.findByEventIdAndPath", query = "from LogEntry log where log.eventId=:eventId and log.docPath LIKE :pathPattern"),
059        @NamedQuery(name = "LogEntry.findByHavingExtendedInfo", query = "from LogEntry log where log.extendedInfos['one'] is not null order by log.eventDate DESC"),
060        @NamedQuery(name = "LogEntry.countEventsById", query = "select count(log.eventId) from LogEntry log where log.eventId=:eventId"),
061        @NamedQuery(name = "LogEntry.findEventIds", query = "select distinct log.eventId from LogEntry log") })
062@Table(name = "NXP_LOGS")
063public class LogEntryImpl implements LogEntry {
064
065    private static final long serialVersionUID = 3037187381843636097L;
066
067    private long id;
068
069    private String principalName;
070
071    private String eventId;
072
073    private Date eventDate;
074
075    private Date logDate;
076
077    private String docUUID;
078
079    private String docType;
080
081    private String docPath;
082
083    private String category;
084
085    private String comment;
086
087    private String docLifeCycle;
088
089    private String repositoryId;
090
091    protected transient UIAuditComment uiComment;
092
093    private Map<String, ExtendedInfoImpl> extendedInfos = new HashMap<String, ExtendedInfoImpl>();
094
095    /**
096     * @return the log identifier
097     */
098    @Override
099    @Id
100    @GeneratedValue(strategy = GenerationType.AUTO)
101    @Column(name = "LOG_ID", nullable = false, columnDefinition = "integer")
102    public long getId() {
103        return id;
104    }
105
106    @Override
107    public void setId(long id) {
108        this.id = id;
109    }
110
111    /**
112     * Returns the name of the principal who originated the log entry.
113     *
114     * @return the name of the principal who originated the log entry
115     */
116    @Override
117    @Column(name = "LOG_PRINCIPAL_NAME")
118    public String getPrincipalName() {
119        return principalName;
120    }
121
122    @Override
123    public void setPrincipalName(String principalName) {
124        this.principalName = principalName;
125    }
126
127    /**
128     * Returns the identifier of the event that originated the log entry.
129     *
130     * @return the identifier of the event that originated the log entry
131     */
132    @Override
133    @Column(name = "LOG_EVENT_ID", nullable = false)
134    @MapKey(name = "logKey")
135    public String getEventId() {
136        return eventId;
137    }
138
139    @Override
140    public void setEventId(String eventId) {
141        this.eventId = eventId;
142    }
143
144    /**
145     * Returns the date of the event that originated the log entry.
146     *
147     * @return the date of the event that originated the log entry
148     */
149    @Override
150    @Temporal(TemporalType.TIMESTAMP)
151    @Column(name = "LOG_EVENT_DATE")
152    public Date getEventDate() {
153        return eventDate;
154    }
155
156    @Override
157    public void setEventDate(Date eventDate) {
158        this.eventDate = eventDate;
159    }
160
161    /**
162     * @return the date of the log insertion: this up to max transaction timeout later than eventDate. This date is
163     *         useful for services such as Nuxeo Drive that need fine grained incremental near-monotonic access to the
164     *         audit log.
165     * @since 5.7
166     * @since 5.6-HF16
167     */
168    @Override
169    @Temporal(TemporalType.TIMESTAMP)
170    @Column(name = "LOG_DATE")
171    public Date getLogDate() {
172        return logDate;
173    }
174
175    @Override
176    public void setLogDate(Date logDate) {
177        this.logDate = logDate;
178    }
179
180    /**
181     * Returns the doc UUID related to the log entry.
182     * <p>
183     * It might be null if the event that originated the event is noe bound to any document.
184     *
185     * @return the doc UUID related to the log entry.
186     */
187    @Override
188    @Column(name = "LOG_DOC_UUID")
189    public String getDocUUID() {
190        return docUUID;
191    }
192
193    @Override
194    public void setDocUUID(String docUUID) {
195        this.docUUID = docUUID;
196    }
197
198    @Override
199    public void setDocUUID(DocumentRef docRef) {
200        switch (docRef.type()) {
201        case DocumentRef.ID:
202            docUUID = (String) docRef.reference();
203            break;
204        case DocumentRef.INSTANCE:
205            docUUID = ((DocumentModel) docRef.reference()).getId();
206            break;
207        default:
208            throw new IllegalArgumentException("not an id reference " + docRef);
209        }
210    }
211
212    /**
213     * Returns the doc path related to the log entry.
214     * <p>
215     * It might be null if the event that originated the event is noe bound to any document.
216     *
217     * @return the doc path related to the log entry.
218     */
219    @Override
220    @Column(name = "LOG_DOC_PATH", length = 1024)
221    public String getDocPath() {
222        return docPath;
223    }
224
225    @Override
226    public void setDocPath(String docPath) {
227        this.docPath = docPath;
228    }
229
230    /**
231     * Returns the doc type related to the log entry.
232     * <p>
233     * It might be null if the event that originated the event is not bound to any document.
234     *
235     * @return the doc type related to the log entry.
236     */
237    @Override
238    @Column(name = "LOG_DOC_TYPE")
239    public String getDocType() {
240        return docType;
241    }
242
243    @Override
244    public void setDocType(String docType) {
245        this.docType = docType;
246    }
247
248    /**
249     * Returns the category for this log entry.
250     * <p>
251     * This is defined at client level. Categories are not restricted in any ways.
252     *
253     * @return the category for this log entry.
254     */
255    @Override
256    @Column(name = "LOG_EVENT_CATEGORY")
257    public String getCategory() {
258        return category;
259    }
260
261    @Override
262    public void setCategory(String category) {
263        this.category = category;
264    }
265
266    /**
267     * Returns the associated comment for this log entry.
268     *
269     * @return the associated comment for this log entry
270     */
271    @Override
272    @Column(name = "LOG_EVENT_COMMENT", length = 1024)
273    public String getComment() {
274        return comment;
275    }
276
277    @Override
278    public void setComment(String comment) {
279        this.comment = comment;
280    }
281
282    /**
283     * Return the life cycle if the document related to the log entry.
284     * <p>
285     * It might be null if the event that originated the event is noe bound to any document.
286     *
287     * @return the life cycle if the document related to the log entry.
288     */
289    @Override
290    @Column(name = "LOG_DOC_LIFE_CYCLE")
291    public String getDocLifeCycle() {
292        return docLifeCycle;
293    }
294
295    @Override
296    public void setDocLifeCycle(String docLifeCycle) {
297        this.docLifeCycle = docLifeCycle;
298    }
299
300    /**
301     * Returns the repository id related to the log entry.
302     *
303     * @return the repository id
304     */
305    @Override
306    @Column(name = "LOG_REPO_ID")
307    public String getRepositoryId() {
308        return repositoryId;
309    }
310
311    @Override
312    public void setRepositoryId(String repositoryId) {
313        this.repositoryId = repositoryId;
314    }
315
316    // public Map<String, ExtendedInfoImpl> getExtendedInfosImpl() {
317    // return extendedInfos;
318    // }
319    //
320    // public void setExtendedInfosImpl(Map<String, ExtendedInfoImpl> infos) {
321    // extendedInfos = infos;
322    // }
323
324    @Override
325    @OneToMany(cascade = CascadeType.ALL, targetEntity = ExtendedInfoImpl.class)
326    @JoinTable(name = "NXP_LOGS_MAPEXTINFOS", joinColumns = { @JoinColumn(name = "LOG_FK") }, inverseJoinColumns = {
327            @JoinColumn(name = "INFO_FK") })
328    @org.hibernate.annotations.MapKey(columns = { @Column(name = "mapkey", nullable = false) })
329    public Map<String, ExtendedInfo> getExtendedInfos() {
330        return (Map) extendedInfos;
331        // return (Map)getExtendedInfosImpl();
332    }
333
334    @Override
335    public void setExtendedInfos(Map<String, ExtendedInfo> infos) {
336        extendedInfos = (Map) infos;
337        // setExtendedInfosImpl((Map)infos);
338    }
339
340    @Override
341    public String toString() {
342        return ToStringBuilder.reflectionToString(this);
343    }
344
345    @Transient
346    @Override
347    public UIAuditComment getPreprocessedComment() {
348        return uiComment;
349    }
350
351    @Override
352    public void setPreprocessedComment(UIAuditComment uiComment) {
353        this.uiComment = uiComment;
354    }
355
356}