/* * Copyright (c) 2010-2013 Evolveum * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.evolveum.midpoint.repo.sql.data.audit; import com.evolveum.midpoint.prism.ItemDefinition; import com.evolveum.midpoint.prism.PrismContext; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.repo.sql.data.common.OperationResultFull; import com.evolveum.midpoint.repo.sql.data.common.embedded.RPolyString; import com.evolveum.midpoint.repo.sql.data.common.enums.RChangeType; import com.evolveum.midpoint.repo.sql.data.common.enums.ROperationResultStatus; import com.evolveum.midpoint.repo.sql.util.DtoTranslationException; import com.evolveum.midpoint.repo.sql.util.EntityState; import com.evolveum.midpoint.repo.sql.util.RUtil; import com.evolveum.midpoint.schema.DeltaConversionOptions; import com.evolveum.midpoint.schema.DeltaConvertor; import com.evolveum.midpoint.schema.ObjectDeltaOperation; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.xml.ns._public.common.common_3.OperationResultType; import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType; import org.hibernate.annotations.ForeignKey; import org.hibernate.annotations.Type; import javax.persistence.*; /** * @author lazyman */ @Entity @IdClass(RObjectDeltaOperationId.class) @Table(name = RObjectDeltaOperation.TABLE_NAME) public class RObjectDeltaOperation implements OperationResultFull, EntityState { public static final String TABLE_NAME = "m_audit_delta"; public static final String COLUMN_RECORD_ID = "record_id"; private Boolean trans; private RAuditEventRecord record; private Long recordId; //delta private String delta; private String checksum; private String deltaOid; private RChangeType deltaType; //operation result private ROperationResultStatus status; private String fullResult; // additional info from ObjectDeltaOperationType private RPolyString objectName; private String resourceOid; private RPolyString resourceName; @ForeignKey(name = "none") @MapsId("record") @ManyToOne(fetch = FetchType.LAZY) @JoinColumns({ @JoinColumn(name = COLUMN_RECORD_ID, referencedColumnName = "id") }) public RAuditEventRecord getRecord() { return record; } @Id @Column(name = COLUMN_RECORD_ID) public Long getRecordId() { if (recordId == null && record != null) { recordId = record.getId(); } return recordId; } /** * This method is used for content comparing when querying database (we don't want to compare clob values). * * @return md5 hash of {@link RObjectDeltaOperation#delta} and {@link RObjectDeltaOperation#fullResult} */ @Id @Column(length = 32, name = "checksum") public String getChecksum() { if (checksum == null) { recomputeChecksum(); } return checksum; } @Lob @Type(type = RUtil.LOB_STRING_TYPE) public String getDelta() { return delta; } @Enumerated(EnumType.ORDINAL) public RChangeType getDeltaType() { return deltaType; } @Column(length = RUtil.COLUMN_LENGTH_OID) public String getDeltaOid() { return deltaOid; } @Lob @Type(type = RUtil.LOB_STRING_TYPE) public String getFullResult() { return fullResult; } @Enumerated(EnumType.ORDINAL) public ROperationResultStatus getStatus() { return status; } @Embedded public RPolyString getObjectName() { return objectName; } @Column(length = RUtil.COLUMN_LENGTH_OID) public String getResourceOid() { return resourceOid; } @Embedded public RPolyString getResourceName() { return resourceName; } @Transient @Override public Boolean isTransient() { return trans; } @Override public void setTransient(Boolean trans) { this.trans = trans; } public void setRecord(RAuditEventRecord record) { if (record.getId() != 0) { this.recordId = record.getId(); } this.record = record; } public void setRecordId(Long recordId) { this.recordId = recordId; } public void setChecksum(String checksum) { //checksum is always computed from delta and result, this setter is only to satisfy hibernate } public void setDelta(String delta) { this.delta = delta; recomputeChecksum(); } public void setStatus(ROperationResultStatus status) { this.status = status; } public void setFullResult(String fullResult) { this.fullResult = fullResult; recomputeChecksum(); } public void setDeltaType(RChangeType deltaType) { this.deltaType = deltaType; } public void setDeltaOid(String deltaOid) { this.deltaOid = deltaOid; } public void setObjectName(RPolyString objectName) { this.objectName = objectName; } public void setResourceOid(String resourceOid) { this.resourceOid = resourceOid; } public void setResourceName(RPolyString resourceName) { this.resourceName = resourceName; } @Transient private void recomputeChecksum() { checksum = RUtil.computeChecksum(delta, fullResult); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; RObjectDeltaOperation that = (RObjectDeltaOperation) o; if (getChecksum() != null ? !getChecksum().equals(that.getChecksum()) : that.getChecksum() != null) return false; if (delta != null ? !delta.equals(that.delta) : that.delta != null) return false; if (fullResult != null ? !fullResult.equals(that.fullResult) : that.fullResult != null) return false; if (status != that.status) return false; if (deltaType != null ? !deltaType.equals(that.deltaType) : that.deltaType != null) return false; if (deltaOid != null ? !deltaOid.equals(that.deltaOid) : that.deltaOid != null) return false; if (objectName != null ? !objectName.equals(that.objectName) : that.objectName != null) return false; if (resourceOid != null ? !resourceOid.equals(that.resourceOid) : that.resourceOid != null) return false; if (resourceName != null ? !resourceName.equals(that.resourceName) : that.resourceName != null) return false; return true; } @Override public int hashCode() { int result1 = delta != null ? delta.hashCode() : 0; result1 = 31 * result1 + (getChecksum() != null ? getChecksum().hashCode() : 0); result1 = 31 * result1 + (status != null ? status.hashCode() : 0); result1 = 31 * result1 + (fullResult != null ? fullResult.hashCode() : 0); result1 = 31 * result1 + (deltaOid != null ? deltaOid.hashCode() : 0); result1 = 31 * result1 + (deltaType != null ? deltaType.hashCode() : 0); result1 = 31 * result1 + (objectName != null ? objectName.hashCode() : 0); result1 = 31 * result1 + (resourceOid != null ? resourceOid.hashCode() : 0); result1 = 31 * result1 + (resourceName != null ? resourceName.hashCode() : 0); return result1; } public static RObjectDeltaOperation toRepo(RAuditEventRecord record, ObjectDeltaOperation operation, PrismContext prismContext) throws DtoTranslationException { RObjectDeltaOperation auditDelta = new RObjectDeltaOperation(); auditDelta.setRecord(record); try { if (operation.getObjectDelta() != null) { ObjectDelta delta = operation.getObjectDelta(); String xmlDelta = DeltaConvertor.toObjectDeltaTypeXml(delta, DeltaConversionOptions.createSerializeReferenceNames()); auditDelta.setDelta(xmlDelta); auditDelta.setDeltaOid(delta.getOid()); auditDelta.setDeltaType(RUtil.getRepoEnumValue(delta.getChangeType(), RChangeType.class)); } if (operation.getExecutionResult() != null) { ItemDefinition def = prismContext.getSchemaRegistry().findItemDefinitionByElementName(SchemaConstantsGenerated.C_OPERATION_RESULT); RUtil.copyResultFromJAXB(def, SchemaConstantsGenerated.C_OPERATION_RESULT, operation.getExecutionResult().createOperationResultType(), auditDelta, prismContext); } auditDelta.setObjectName(RPolyString.toRepo(operation.getObjectName())); auditDelta.setResourceOid(operation.getResourceOid()); auditDelta.setResourceName(RPolyString.toRepo(operation.getResourceName())); } catch (Exception ex) { throw new DtoTranslationException(ex.getMessage(), ex); } return auditDelta; } public static ObjectDeltaOperation fromRepo(RObjectDeltaOperation operation, PrismContext prismContext) throws DtoTranslationException { ObjectDeltaOperation odo = new ObjectDeltaOperation(); try { if (operation.getDelta() != null) { ObjectDeltaType delta = prismContext.parserFor(operation.getDelta()).parseRealValue(ObjectDeltaType.class); odo.setObjectDelta(DeltaConvertor.createObjectDelta(delta, prismContext)); } if (operation.getFullResult() != null) { OperationResultType resultType = prismContext.parserFor(operation.getFullResult()).parseRealValue(OperationResultType.class); odo.setExecutionResult(OperationResult.createOperationResult(resultType)); } odo.setObjectName(RPolyString.fromRepo(operation.getObjectName())); odo.setResourceOid(operation.getResourceOid()); odo.setResourceName(RPolyString.fromRepo(operation.getResourceName())); } catch (Exception ex) { throw new DtoTranslationException(ex.getMessage(), ex); } return odo; } }