001/* 002 * (C) Copyright 2014 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-2.1.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 * Florent Guillaume 016 */ 017package org.nuxeo.ecm.core.storage.dbs; 018 019import static org.nuxeo.ecm.core.storage.dbs.DBSDocument.KEY_FULLTEXT_BINARY; 020import static org.nuxeo.ecm.core.storage.dbs.DBSDocument.KEY_FULLTEXT_JOBID; 021import static org.nuxeo.ecm.core.storage.dbs.DBSDocument.KEY_FULLTEXT_SIMPLE; 022import static org.nuxeo.ecm.core.storage.dbs.DBSDocument.KEY_ID; 023import static org.nuxeo.ecm.core.storage.dbs.DBSDocument.KEY_NAME; 024import static org.nuxeo.ecm.core.storage.dbs.DBSDocument.KEY_PARENT_ID; 025import static org.nuxeo.ecm.core.storage.dbs.DBSDocument.KEY_PRIMARY_TYPE; 026import static org.nuxeo.ecm.core.storage.dbs.DBSDocument.KEY_VERSION_SERIES_ID; 027 028import java.io.Serializable; 029 030import org.nuxeo.ecm.core.model.Document; 031import org.nuxeo.ecm.core.storage.State.StateDiff; 032import org.nuxeo.ecm.core.storage.StateHelper; 033import org.nuxeo.ecm.core.storage.State; 034 035/** 036 * Implementation of a {@link Document} state for Document-Based Storage. 037 * <p> 038 * It wraps a {@link State}, together with a dirty flag. 039 * 040 * @since 5.9.4 041 */ 042public class DBSDocumentState { 043 044 /** 045 * The current state. 046 */ 047 protected State state; 048 049 /** 050 * When non-null, the original state (otherwise the state hasn't been modified). 051 */ 052 protected State originalState; 053 054 /** 055 * Constructs an empty state. 056 */ 057 public DBSDocumentState() { 058 state = new State(); 059 originalState = null; 060 } 061 062 /** 063 * Constructs a document state from the copy of an existing base state. 064 */ 065 public DBSDocumentState(State base) { 066 state = StateHelper.deepCopy(base); 067 originalState = null; 068 } 069 070 /** 071 * This must be called if we're about to directly change the internal state. 072 */ 073 public void markDirty() { 074 if (originalState == null) { 075 originalState = StateHelper.deepCopy(state); 076 } 077 } 078 079 /** 080 * Checks if the document state has been changed since its construction or the last call to {@link #setNotDirty}. 081 */ 082 public boolean isDirty() { 083 return originalState != null; 084 } 085 086 public boolean isDirtyIgnoringFulltext() { 087 StateDiff diff = getStateChange(); 088 if (diff == null) { 089 return false; 090 } 091 diff.remove(KEY_FULLTEXT_SIMPLE); 092 diff.remove(KEY_FULLTEXT_BINARY); 093 diff.remove(KEY_FULLTEXT_JOBID); 094 return !diff.isEmpty(); 095 } 096 097 public void setNotDirty() { 098 originalState = null; 099 StateHelper.resetDeltas(state); 100 } 101 102 /** 103 * Gets the state. If the caller changes the state, it must also call {@link #dirty} to inform this object that the 104 * state is dirtied. 105 */ 106 public State getState() { 107 return state; 108 } 109 110 /** 111 * Gets a diff of what changed since this document state was read from database or saved. 112 * 113 * @return {@code null} if there was no change, or a {@link StateDiff} 114 */ 115 public StateDiff getStateChange() { 116 if (originalState == null) { 117 return null; 118 } 119 StateDiff diff = StateHelper.diff(originalState, state); 120 if (diff.isEmpty()) { 121 return null; 122 } 123 return diff; 124 } 125 126 /** 127 * Gets the original state for this, needed when creating an undo log. 128 * 129 * @return a state that must not be modified 130 * @since 7.4 131 */ 132 public State getOriginalState() { 133 return originalState == null ? state : originalState; 134 } 135 136 public Serializable get(String key) { 137 return state.get(key); 138 } 139 140 public void put(String key, Serializable value) { 141 markDirty(); 142 state.put(key, value); 143 } 144 145 public boolean containsKey(String key) { 146 return state.get(key) != null; 147 } 148 149 public String getId() { 150 return (String) get(KEY_ID); 151 } 152 153 public String getParentId() { 154 return (String) get(KEY_PARENT_ID); 155 } 156 157 public String getName() { 158 return (String) get(KEY_NAME); 159 } 160 161 public String getPrimaryType() { 162 return (String) get(KEY_PRIMARY_TYPE); 163 } 164 165 public String getVersionSeriesId() { 166 return (String) get(KEY_VERSION_SERIES_ID); 167 } 168 169 @Override 170 public String toString() { 171 return getClass().getSimpleName() + '(' + (isDirty() ? "dirty," : "") + state.toString() + ')'; 172 } 173 174}