Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
Copyright 2011 the original author or authors. 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 org.springframework.data.neo4j.fieldaccess;
 
 import  org.springframework.util.ObjectUtils;
 
 import java.util.Map;
 
 import static org.springframework.data.neo4j.support.DoReturn.unwrap;

Author(s):
Michael Hunger
Since:
15.09.2010
 
 public class DetachedEntityState<STATE> implements EntityState<STATE> {
     private final static Logger log = LoggerFactory.getLogger(DetachedEntityState.class);
 
     protected final EntityState<STATE> delegate;
     private Neo4jTemplate template;
 
     public DetachedEntityState(final EntityState<STATE> delegateNeo4jTemplate template) {
         this. = delegate;
         this. = delegate.getPersistentEntity();
         this. = template;
     }
 
     @Override
     public boolean isWritable(Neo4jPersistentProperty property) {
         return .isWritable(property);
     }
 
     @Override
     public Object getEntity() {
         return .getEntity();
     }
 
     @Override
     public boolean hasPersistentState() {
         return .hasPersistentState();
     }
 
     @Override
     public STATE getPersistentState() {
         return .getPersistentState();
     }
 
     @Override
     public Neo4jPersistentEntity<?> getPersistentEntity() {
         return ;
     }
 
     @Override
     public Object getValue(Neo4jPersistentProperty propertyMappingPolicy mappingPolicy) {
         if (mappingPolicy == null) {
             if (property!=nullmappingPolicy = property.getMappingPolicy();
             else mappingPolicy = .;
         }
         if (isDetached()) {
             if (!.transactionIsRunning() || .getPersistentState(getEntity())==null || isDirty(property)) {
                 if (.isDebugEnabled()) .debug("Outside of transaction, GET value from field " + property);
                 Object entityValue = getValueFromEntity(property.);
                 if (entityValue != null) {
                 	return entityValue;
                 }
 
                 Object defaultValue = getDefaultValue(property);
                 if (defaultValue != null) {
                     final Object entity = getEntity();
                     property.setValue(entitydefaultValue);
                     addDirty(propertydefaultValuefalse);
                     if (defaultValue instanceof DirtyValue) {
                         ((DirtyValue)defaultValue).setDirty(true);
                    }
                }
                return defaultValue;
            }
        } else {
//            flushDirty();
        }
        return .getValue(propertymappingPolicy);
    }
    @Override
    public Object getValue(final Field fieldMappingPolicy mappingPolicy) {
        return getValue(property(field), mappingPolicy);
    }
    protected boolean isDetached() {
        return !transactionIsRunning() || !hasPersistentState() || isDirty();
    }
    protected boolean transactionIsRunning() {
        return getTemplate().transactionIsRunning();
    }
    static class ExistingValue {
        public final Object value;
        private final boolean fromGraph;
        ExistingValue(Object valueboolean fromGraph) {
            this. = value;
            this. = fromGraph;
        }
        @Override
        public String toString() {
            return String.format("ExistingValue{value=%s, fromGraph=%s}");
        }
        private boolean mustCheckConcurrentModification() {
            return ;
        }
    }
    @Override
    public Object setValue(final Field fieldfinal Object newValMappingPolicy mappingPolicy) {
        Neo4jPersistentProperty property = property(field);
        if (property != null) {
            return setValue(propertynewValmappingPolicy);
        }
        return .setValue(propertynewValmappingPolicy);
    }
    private Neo4jPersistentProperty property(Field field) {
        return .getPersistentProperty(field.getName());
    }
    @Override
    public Object setValue(final Neo4jPersistentProperty propertyfinal Object newValMappingPolicy mappingPolicy) {
        if (isDetached()) {
            if (!isDirty(property) && isWritable(property)) {
                if (hasPersistentState()) {
                    Object valueFromDb = null;
                    if (.transactionIsRunning()) {
                        valueFromDb = unwrap(.getValue(property.));
                    } else {
                        // For Implicit Transactions, we need to create
                        // a tx to ensure we get the correct previous value
                        // otherwise the possibility of getting a concurrent
                        // modification exception when next persisting may occur
                        try (Transaction tx = .getGraphDatabaseService().beginTx()) {
                            valueFromDb = unwrap(.getValue(property.));
                            tx.success();
                        }
                    }
                    addDirty(propertyvalueFromDbtrue);
                }
                else {
                    addDirty(propertynewValfalse);
                }
            }
            return newVal;
        }
        // flushDirty();
        return .setValue(propertynewValmappingPolicy);
    }
        return .getDefaultValue(property);
	}
    @SuppressWarnings("deprecation")
    @Override
    public void createAndAssignState() {
        if (.transactionIsRunning()) {
            .createAndAssignState();
        } else {
            .warn("New Nodebacked created outside of transaction " + .getEntity().getClass());
        }
    }

    
always runs inside of a transaction
    private void flushDirty() {
        final Object entity = getEntity();
        if (!hasPersistentState()) {
            // createAndAssignState();
            throw new IllegalStateException("Flushing detached entity without a persistent state, this had to be created first.");
        }
        if (isDirty()) {
            final Map<Neo4jPersistentPropertyExistingValuedirtyCopy = new HashMap<Neo4jPersistentPropertyExistingValue>();
            try {
                for (final Map.Entry<Neo4jPersistentPropertyExistingValueentry : dirtyCopy.entrySet()) {
                    final Neo4jPersistentProperty property = entry.getKey();
                    Object valueFromEntity = getValueFromEntity(property.);
                    cascadePersist(valueFromEntity);
                    if (.isDebugEnabled()) .debug("Flushing dirty Entity new node " + entity + " field " + property" with value "valueFromEntity);
                    final MappingPolicy mappingPolicy = property.getMappingPolicy();
                    checkConcurrentModification(entityentrypropertymappingPolicy);
                    .setValue(propertyvalueFromEntitymappingPolicy);
                    .remove(property);
                    if (valueFromEntity instanceof DirtyValue) {
                        ((DirtyValue)valueFromEntity).setDirty(false);
                    }
                }
            } finally {
                if (!.isEmpty()) { // restore all dirty data
                    .putAll(dirtyCopy);
                    for (Map.Entry<Neo4jPersistentPropertyExistingValueentry : dirtyCopy.entrySet()) {
                        final Neo4jPersistentProperty property = entry.getKey();
                        Object valueFromEntity = getValueFromEntity(property.);
                        if (valueFromEntity instanceof DirtyValue) {
                            ((DirtyValue)valueFromEntity).setDirty(true);
                        }
                    }
                }
            }
        }
    }
    private void cascadePersist(Object valueFromEntity) {
    /* TODO   if (valueFromEntity instanceof NodeBacked) {
            ((NodeBacked) valueFromEntity).persist();
        }
        if (valueFromEntity instanceof Collection) {
            for (Object o : (Collection<Object>)valueFromEntity) {
                if (o instanceof NodeBacked) {
                    ((NodeBacked) o).persist();
                }
            }
        }
     */
    }
    @Override
    public void setPersistentState(final STATE state) {
        .setPersistentState(state);
    }
    private Object getValueFromEntity(final Neo4jPersistentProperty propertyMappingPolicy mappingPolicy) {
        final Object entity = getEntity();
        return property.getValue(entitymappingPolicy);
    }
    private void checkConcurrentModification(final Object entityfinal Map.Entry<Neo4jPersistentPropertyExistingValueentryfinal Neo4jPersistentProperty propertyfinal MappingPolicy mappingPolicy) {
        final ExistingValue previousValue = entry.getValue();
        if (previousValue == null || !previousValue.mustCheckConcurrentModification()) return;
        final Object nodeValue = unwrap(.getValue(propertymappingPolicy));
        if (!ObjectUtils.nullSafeEquals(nodeValuepreviousValue.value)) {
            throw new ConcurrentModificationException("Node " + entity + " field " + property + " changed in between previous " + previousValue + " current " + nodeValue); // todo or just overwrite
        }
    }
    private boolean isDirty() {
        return !this..isEmpty();
    }
    private boolean isDirty(final Neo4jPersistentProperty property) {
        return this..containsKey(property);
    }
    private void addDirty(final Neo4jPersistentProperty propertyfinal Object previousValueboolean fromGraph) {
        this..put(propertynew ExistingValue(previousValue,fromGraph));
    }
    public Neo4jTemplate getTemplate() {
        return ;
    }
    // todo always create an transaction for persist, atomic operation when no outside tx exists
    @Override
    public Object persist() {
        if (!isDetached()) return getEntity();
        Transaction tx = .getGraphDatabase().beginTx();
        try {
            Object result = .persist();
            flushDirty();
            tx.success();
            return result;
        } catch(Throwable t) {
			tx.failure();
			if (t instanceof Errorthrow (Error)t;
			if (t instanceof RuntimeExceptionthrow (RuntimeException)t;
			throw new org.springframework.data.neo4j.core.UncategorizedGraphStoreException("Error persisting entity "+getEntity(),t);
        } finally {
            tx.close();
        }
    }
New to GrepCode? Check out our FAQ X