private Object unmarshall(PersistentEntity persistentEntity, Long id, Map<String, Object> data) {

    log.debug("unmarshalling entity {}, props {}, {}", id, data);
    EntityAccess entityAccess = new EntityAccess(persistentEntity, persistentEntity.newInstance());
    entityAccess.setConversionService(persistentEntity.getMappingContext().getConversionService());
    entityAccess.setIdentifier(id);
    data.remove("__id__");

    for (PersistentProperty property :
        entityAccess.getPersistentEntity().getPersistentProperties()) {

      String propertyName = property.getName();
      if (property instanceof Simple) { // implicitly sets version property as well
        entityAccess.setProperty(propertyName, data.remove(propertyName));
        //            } else if (property instanceof OneToOne) {
        //                log.error("property " + property.getName() + " is of type " +
        // property.getClass().getSuperclass());
      } else if (property instanceof ToOne) {
        ToOne to = (ToOne) property;

        CypherResult cypherResult =
            getSession()
                .getNativeInterface()
                .execute(
                    CypherBuilder.findRelationshipEndpointIdsFor(to),
                    Collections.singletonMap("id", id));

        Map<String, Object> row = IteratorUtil.singleOrNull(cypherResult);
        if (row != null) {
          Long endpointId = (Long) row.get("id");
          entityAccess.setProperty(
              propertyName,
              getMappingContext()
                  .getProxyFactory()
                  .createProxy(session, to.getAssociatedEntity().getJavaClass(), endpointId));
        }
      } else if ((property instanceof OneToMany) || (property instanceof ManyToMany)) {

        LazyEnititySet lazyEnititySet =
            new LazyEnititySet(
                entityAccess,
                (Association) property,
                getMappingContext().getProxyFactory(),
                getSession());
        entityAccess.setProperty(propertyName, lazyEnititySet);

      } else {
        throw new IllegalArgumentException(
            "property $property.name is of type ${property.class.superclass}");
      }
    }

    if (!data.isEmpty()) {
      GroovyObject go = (GroovyObject) (entityAccess.getEntity());
      go.setProperty(Neo4jGormEnhancer.UNDECLARED_PROPERTIES, data);
    }

    firePostLoadEvent(entityAccess.getPersistentEntity(), entityAccess);
    return entityAccess.getEntity();
  }
  @Override
  protected DBObject createNewEntry(String family) {
    BasicDBObject dbo = new BasicDBObject();
    PersistentEntity persistentEntity = getPersistentEntity();
    if (!persistentEntity.isRoot()) {
      dbo.put(MONGO_CLASS_FIELD, persistentEntity.getDiscriminator());
    }

    return dbo;
  }
 public PersistentEntity getRootEntity() {
   if (isRoot() || getParentEntity() == null) {
     return this;
   }
   PersistentEntity parent = getParentEntity();
   while (!parent.isRoot()) {
     parent = parent.getParentEntity();
   }
   return parent;
 }
 private String getCollectionName(PersistentEntity persistentEntity, DBObject nativeEntry) {
   String collectionName;
   if (persistentEntity.isRoot()) {
     MongoSession mongoSession = (MongoSession) getSession();
     collectionName = mongoSession.getCollectionName(persistentEntity);
   } else {
     MongoSession mongoSession = (MongoSession) getSession();
     collectionName = mongoSession.getCollectionName(persistentEntity.getRootEntity());
   }
   return collectionName;
 }
 /**
  * Get hold of the GrailsDomainClassProperty represented by the targetClass' propertyName,
  * assuming targetClass corresponds to a GrailsDomainClass.
  */
 private static PersistentProperty getGrailsDomainClassProperty(
     AbstractHibernateDatastore datastore, Class<?> targetClass, String propertyName) {
   PersistentEntity grailsClass =
       datastore != null
           ? datastore.getMappingContext().getPersistentEntity(targetClass.getName())
           : null;
   if (grailsClass == null) {
     throw new IllegalArgumentException(
         "Unexpected: class is not a domain class:" + targetClass.getName());
   }
   return grailsClass.getPropertyByName(propertyName);
 }
 @Override
 public Serializable getObjectIdentifier(Object instance) {
   if (instance == null) return null;
   if (proxyHandler.isProxy(instance)) {
     return ((HibernateProxy) instance).getHibernateLazyInitializer().getIdentifier();
   }
   Class<?> type = instance.getClass();
   ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(type);
   final PersistentEntity persistentEntity =
       getMappingContext().getPersistentEntity(type.getName());
   if (persistentEntity != null) {
     return (Serializable)
         cpf.getPropertyValue(instance, persistentEntity.getIdentity().getName());
   }
   return null;
 }
  @Override
  @SuppressWarnings({"rawtypes", "unchecked"})
  public Family createMappedForm(PersistentEntity entity) {
    ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass());
    final Closure value = cpf.getStaticPropertyValue(GormProperties.MAPPING, Closure.class);
    if (value == null) {
      return new Region();
    }

    final Region family = new Region();
    AttributesFactory factory =
        new AttributesFactory() {
          @SuppressWarnings("unused")
          public void setRegion(String name) {
            family.setRegion(name);
          }
        };
    factory.setDataPolicy(defaultDataPolicy);

    MappingConfigurationBuilder builder = new MappingConfigurationBuilder(factory, KeyValue.class);
    builder.evaluate(value);
    entityToPropertyMap.put(entity, builder.getProperties());
    final RegionAttributes regionAttributes = factory.create();
    family.setRegionAttributes(regionAttributes);
    family.setCacheListeners(regionAttributes.getCacheListeners());
    family.setDataPolicy(regionAttributes.getDataPolicy());
    family.setCacheLoader(regionAttributes.getCacheLoader());
    family.setCacheWriter(regionAttributes.getCacheWriter());

    builder = new MappingConfigurationBuilder(family, KeyValue.class);
    builder.evaluate(value);
    return family;
  }
  @Override
  public Object invokeMethod(String name, Object obj) {
    Object[] args = obj.getClass().isArray() ? (Object[]) obj : new Object[] {obj};

    if (isCriteriaConstructionMethod(name, args)) {

      initializeQuery();

      uniqueResult = false;

      invokeClosureNode(args[0]);

      Object result;
      if (!uniqueResult) {
        result = query.list();
      } else {
        result = query.singleResult();
      }
      query = null;
      return result;
    }

    MetaMethod metaMethod = getMetaClass().getMetaMethod(name, args);
    if (metaMethod != null) {
      return metaMethod.invoke(this, args);
    }

    metaMethod = queryMetaClass.getMetaMethod(name, args);
    if (metaMethod != null) {
      return metaMethod.invoke(query, args);
    }

    if (args.length == 1 && args[0] instanceof Closure) {

      final PersistentProperty property = persistentEntity.getPropertyByName(name);
      if (property instanceof Association) {
        Association association = (Association) property;
        Query previousQuery = query;
        PersistentEntity previousEntity = persistentEntity;

        Query associationQuery = null;
        try {
          associationQuery = query.createQuery(property.getName());
          if (associationQuery instanceof AssociationQuery) {
            previousQuery.add((Query.Criterion) associationQuery);
          }
          query = associationQuery;
          persistentEntity = association.getAssociatedEntity();
          invokeClosureNode(args[0]);
          return query;
        } finally {

          persistentEntity = previousEntity;
          query = previousQuery;
        }
      }
    }

    throw new MissingMethodException(name, getClass(), args);
  }
 /**
  * Returns mapped domain name (*unprefixed*) for the specified @{link PersistentEntity}.
  *
  * @param entity
  * @return
  */
 public static String getMappedDomainName(PersistentEntity entity) {
   @SuppressWarnings("unchecked")
   ClassMapping<SimpleDBDomainClassMappedForm> classMapping = entity.getMapping();
   SimpleDBDomainClassMappedForm mappedForm = classMapping.getMappedForm();
   String entityFamily = getFamily(entity, mappedForm);
   return entityFamily;
 }
  @Override
  protected void deleteEntity(PersistentEntity pe, Object obj) {
    EntityAccess entityAccess = createEntityAccess(pe, obj);
    if (cancelDelete(pe, entityAccess)) {
      return;
    }

    for (Association association : pe.getAssociations()) {
      if (association.isOwningSide() && association.doesCascade(CascadeType.REMOVE)) {
        log.debug("cascading delete for property " + association.getName());

        GraphPersistentEntity otherPersistentEntity =
            (GraphPersistentEntity) association.getAssociatedEntity();
        Object otherSideValue = entityAccess.getProperty(association.getName());
        if (association instanceof ToOne) {
          deleteEntity(otherPersistentEntity, otherSideValue);
        } else {
          deleteEntities(otherPersistentEntity, (Iterable) otherSideValue);
        }
      }
    }

    getCypherEngine()
        .execute(
            String.format(
                "MATCH (n:%s) WHERE n.__id__={id} OPTIONAL MATCH (n)-[r]-() DELETE r,n",
                ((GraphPersistentEntity) pe).getLabel()),
            Collections.singletonMap("id", entityAccess.getIdentifier()));

    firePostDeleteEvent(pe, entityAccess);
  }
 int calcInheritenceChain(PersistentEntity pe) {
   if (pe == null) {
     return 0;
   } else {
     return calcInheritenceChain(pe.getParentEntity()) + 1;
   }
 }
 public static List<String> getDatasourceNames(PersistentEntity domainClass) {
   final Entity mappedForm = domainClass.getMapping().getMappedForm();
   if (mappedForm instanceof Mapping) {
     Mapping mapping = (Mapping) mappedForm;
     return mapping.getDatasources();
   }
   return Collections.singletonList(Mapping.DEFAULT_DATA_SOURCE);
 }
  @Override
  protected List<Object> retrieveAllEntities(
      PersistentEntity persistentEntity, Iterable<Serializable> keys) {

    Query query = session.createQuery(persistentEntity.getJavaClass());

    PersistentProperty identity = persistentEntity.getIdentity();
    if (keys instanceof List) {
      List actualKeys = new ArrayList();
      Iterator iterator = keys.iterator();
      while (iterator.hasNext()) {
        Object key = iterator.next();
        Object id = getIdentifierForKey(key);
        actualKeys.add(id);
      }
      query.in(identity.getName(), actualKeys);
    } else {
      List<Serializable> keyList = new ArrayList<Serializable>();
      for (Serializable key : keys) {
        keyList.add(key);
      }
      query.in(identity.getName(), keyList);
    }

    List<Object> entityResults = new ArrayList<Object>();
    Iterator<Serializable> keyIterator = keys.iterator();
    Map<Serializable, Object> resultMap = new HashMap<Serializable, Object>();
    for (Object o : query.list()) {
      if (o instanceof DBObject) {
        DBObject dbo = (DBObject) o;
        o =
            createObjectFromNativeEntry(
                getPersistentEntity(), (Serializable) dbo.get(MONGO_ID_FIELD), dbo);
      }
      resultMap.put(getObjectIdentifier(o), o);
    }
    while (keyIterator.hasNext()) {
      Object key = getIdentifierForKey(keyIterator.next());
      ConversionService conversionService = getMappingContext().getConversionService();
      key = conversionService.convert(key, identity.getType());
      Object o = resultMap.get(key);
      entityResults.add(o); // may add null, so entityResults list size matches input list size.
    }

    return entityResults;
  }
 private static String getFamily(
     PersistentEntity persistentEntity, SimpleDBDomainClassMappedForm mappedForm) {
   String table = null;
   if (mappedForm != null) {
     table = mappedForm.getFamily();
   }
   if (table == null) table = persistentEntity.getJavaClass().getSimpleName();
   return table;
 }
  @SuppressWarnings("unchecked")
  @Override
  public Table createMappedForm(PersistentEntity entity) {
    Table table = super.createMappedForm(entity);
    CassandraPersistentEntity cassandraPersistentEntity = (CassandraPersistentEntity) entity;
    // read tableOptions
    ClassPropertyFetcher cpf = ClassPropertyFetcher.forClass(entity.getJavaClass());
    final Closure value = cpf.getStaticPropertyValue(TABLE_PROPERTIES, Closure.class);
    if (value != null) {
      MapConfigurationBuilder builder = new MapConfigurationBuilder();
      try {
        builder.evaluate(value);
      } catch (Exception e) {
        throw new IllegalMappingException(
            String.format("Error reading %s : %s", TABLE_PROPERTIES, e.toString()));
      }
      table.setTableProperties(builder.getProperties());
    }

    if (table.getKeyspace() == null) {
      table.setKeyspace(keyspace);
    }

    // additional static mapping block handling
    Map<String, Column> properties = entityToPropertyMap.get(entity);
    Object version = properties.get(MappingConfigurationBuilder.VERSION_KEY);
    if (version instanceof Boolean) {
      cassandraPersistentEntity.setVersion((Boolean) version);
    }

    Column idProperty = properties.get(IDENTITY_PROPERTY);
    Iterator<Entry<String, Column>> propertyIterator = properties.entrySet().iterator();

    while (propertyIterator.hasNext()) {
      Entry<String, Column> entry = propertyIterator.next();
      if (entry.getValue() instanceof Column) {
        String name = entry.getKey();
        Column column = entry.getValue();
        if (idProperty != null
            && idProperty.getName() != null
            && idProperty.getName().equals(name)) {
          // remove extra column created if id property in constraints block, as it conflicts with
          // the column created in mapping block.
          // constraints will be handled elsewhere in GORM
          propertyIterator.remove();
          continue;
        }

        if (column.getName() == null) {
          column.setName(name);
        }
        table.addColumn(column);
      }
    }

    return table;
  }
  protected void validatePropertyName(String propertyName, String methodName) {
    if (propertyName == null) {
      throw new IllegalArgumentException(
          "Cannot use [" + methodName + "] restriction with null property name");
    }

    PersistentProperty property = persistentEntity.getPropertyByName(propertyName);
    if (property == null && persistentEntity.getIdentity().getName().equals(propertyName)) {
      property = persistentEntity.getIdentity();
    }
    if (property == null) {
      throw new IllegalArgumentException(
          "Property ["
              + propertyName
              + "] is not a valid property of class ["
              + persistentEntity
              + "]");
    }
  }
  public static org.hibernate.criterion.DetachedCriteria getHibernateDetachedCriteria(
      AbstractHibernateQuery hibernateQuery, QueryableCriteria<?> queryableCriteria) {

    String alias = queryableCriteria.getAlias();
    PersistentEntity persistentEntity = queryableCriteria.getPersistentEntity();
    Class targetClass = persistentEntity.getJavaClass();
    org.hibernate.criterion.DetachedCriteria detachedCriteria;

    if (alias != null) {
      detachedCriteria = org.hibernate.criterion.DetachedCriteria.forClass(targetClass, alias);
    } else {
      detachedCriteria = org.hibernate.criterion.DetachedCriteria.forClass(targetClass);
    }
    populateHibernateDetachedCriteria(
        new HibernateQuery(detachedCriteria, persistentEntity),
        detachedCriteria,
        queryableCriteria);
    return detachedCriteria;
  }
  @Override
  protected void deleteEntities(
      PersistentEntity pe, @SuppressWarnings("rawtypes") Iterable objects) {
    List<EntityAccess> entityAccesses = new ArrayList<EntityAccess>();
    List<Object> ids = new ArrayList<Object>();
    Map<PersistentEntity, Collection<Object>> cascades =
        new HashMap<PersistentEntity, Collection<Object>>();

    for (Object obj : objects) {
      EntityAccess entityAccess = createEntityAccess(pe, obj);
      if (cancelDelete(pe, entityAccess)) {
        return;
      }
      entityAccesses.add(entityAccess);
      ids.add(entityAccess.getIdentifier());

      // populate cascades
      for (Association association : pe.getAssociations()) {
        Object property = entityAccess.getProperty(association.getName());
        if (association.isOwningSide()
            && association.doesCascade(CascadeType.REMOVE)
            && (property != null)) {

          PersistentEntity associatedEntity = association.getAssociatedEntity();

          Collection<Object> cascadesForPersistentEntity = cascades.get(associatedEntity);
          if (cascadesForPersistentEntity == null) {
            cascadesForPersistentEntity = new ArrayList<Object>();
            cascades.put(associatedEntity, cascadesForPersistentEntity);
          }

          if (association instanceof ToOne) {
            cascadesForPersistentEntity.add(property);
          } else {
            cascadesForPersistentEntity.addAll((Collection<?>) property);
          }
        }
      }
    }

    for (Map.Entry<PersistentEntity, Collection<Object>> entry : cascades.entrySet()) {
      deleteEntities(entry.getKey(), entry.getValue());
    }

    getCypherEngine()
        .execute(
            String.format(
                "MATCH (n:%s) WHERE n.__id__ in {ids} OPTIONAL MATCH (n)-[r]-() DELETE r,n",
                ((GraphPersistentEntity) pe).getLabel()),
            Collections.singletonMap("ids", ids));

    for (EntityAccess entityAccess : entityAccesses) {
      firePostDeleteEvent(pe, entityAccess);
    }
  }
 @Override
 protected PersistentEntity discriminatePersistentEntity(
     PersistentEntity persistentEntity, DBObject nativeEntry) {
   final Object o = nativeEntry.get(MONGO_CLASS_FIELD);
   if (o != null) {
     final String className = o.toString();
     final PersistentEntity childEntity =
         getMappingContext()
             .getChildEntityByDiscriminator(persistentEntity.getRootEntity(), className);
     if (childEntity != null) {
       return childEntity;
     }
   }
   return super.discriminatePersistentEntity(persistentEntity, nativeEntry);
 }
  @Override
  @SuppressWarnings("unchecked")
  public Identity<Column> createIdentity(
      PersistentEntity owner, MappingContext context, PropertyDescriptor pd) {
    final Table table = (Table) owner.getMapping().getMappedForm();
    if (table.hasCompositePrimaryKeys()) {
      return new Identity<Column>(owner, context, table.getPrimaryKeyNames()[0], Map.class) {
        PropertyMapping<Column> propertyMapping = createPropertyMapping(this, owner);

        public PropertyMapping<Column> getMapping() {
          return propertyMapping;
        }
      };
    }
    return super.createIdentity(owner, context, pd);
  }
  public MongoEntityPersister(
      MappingContext mappingContext,
      PersistentEntity entity,
      MongoSession mongoSession,
      ApplicationEventPublisher publisher) {
    super(mappingContext, entity, mongoSession, publisher);
    MongoDatastore datastore = (MongoDatastore) mongoSession.getDatastore();
    mongoTemplate = datastore.getMongoTemplate(entity);
    collectionName = datastore.getCollectionName(entity);

    if (!(entity instanceof EmbeddedPersistentEntity)) {

      PersistentProperty identity = entity.getIdentity();
      if (identity != null) {
        hasNumericalIdentifier = Long.class.isAssignableFrom(identity.getType());
        hasStringIdentifier = String.class.isAssignableFrom(identity.getType());
      }
    }
  }
 @Override
 protected MappingConfigurationBuilder createConfigurationBuilder(
     PersistentEntity entity, Mapping mapping) {
   return new HibernateMappingBuilder(mapping, entity.getName(), defaultConstraints);
 }
 public boolean isOwningEntity(PersistentEntity owner) {
   return domainClass.isOwningClass(owner.getJavaClass());
 }
 /**
  * @see #getPersistentProperties(Class, org.grails.datastore.mapping.model.MappingContext,
  *     org.grails.datastore.mapping.model.ClassMapping)
  */
 public List<PersistentProperty> getPersistentProperties(
     PersistentEntity entity, MappingContext context, ClassMapping classMapping) {
   return getPersistentProperties(entity.getJavaClass(), context, classMapping);
 }
  @Override
  public CassandraPersistentProperty createPersistentProperty(
      Field field,
      PropertyDescriptor descriptor,
      CassandraPersistentEntity<?> owner,
      SimpleTypeHolder simpleTypeHolder) {
    PersistentEntity gormEntity = gormCassandraMappingContext.getPersistentEntity(owner.getName());
    final CassandraPersistentProperty property =
        super.createPersistentProperty(field, descriptor, owner, simpleTypeHolder);
    final CassandraPersistentProperty transientProperty =
        new BasicCassandraPersistentProperty(
            field, descriptor, owner, (CassandraSimpleTypeHolder) simpleTypeHolder) {
          public boolean isTransient() {
            return true;
          }
        };
    if (field == null && !property.usePropertyAccess()) {
      return transientProperty;
    }
    if (field != null && Modifier.isTransient(field.getModifiers())) {
      return transientProperty;
    }
    if (field != null && grails.core.GrailsDomainClassProperty.ERRORS.equals(field.getName())) {
      return transientProperty;
    }

    if (field != null && field.getType().equals(Errors.class)) {
      return transientProperty;
    }

    if (field != null
        && (field.getName().contains(INTERNAL_MARKER)
            || field.getName().startsWith(INTERNAL_GRAILS_FIELD_MARKER))) {
      return transientProperty;
    }

    if (descriptor != null
        && descriptor.getWriteMethod() == null
        && descriptor.getReadMethod() == null) {
      return transientProperty;
    }

    Class<?> rawType =
        field != null ? field.getType() : descriptor != null ? descriptor.getPropertyType() : null;
    if (rawType == null) {
      return transientProperty;
    }
    if (rawType.isEnum()) {
      // persist as a string
      return new BasicCassandraPersistentProperty(
          field, descriptor, owner, (CassandraSimpleTypeHolder) simpleTypeHolder) {
        public com.datastax.driver.core.DataType getDataType() {
          return CassandraSimpleTypeHolder.getDataTypeFor(String.class);
        };

        public java.lang.Class<?> getType() {
          return String.class;
        };

        public boolean usePropertyAccess() {
          return true;
        };
      };
    } else if (URL.class.isAssignableFrom(rawType)
        || TimeZone.class.isAssignableFrom(rawType)
        || Locale.class.isAssignableFrom(rawType)
        || Currency.class.isAssignableFrom(rawType)
        || Calendar.class.isAssignableFrom(rawType)) {
      // persist as a string
      return new BasicCassandraPersistentProperty(
          field, descriptor, owner, (CassandraSimpleTypeHolder) simpleTypeHolder) {
        public com.datastax.driver.core.DataType getDataType() {
          return CassandraSimpleTypeHolder.getDataTypeFor(String.class);
        };

        public java.lang.Class<?> getType() {
          return String.class;
        };

        public boolean isEntity() {
          return false;
        };

        public boolean usePropertyAccess() {
          return true;
        };
      };
    } else if (field != null
        && GrailsDomainClassProperty.VERSION.equals(field.getName())
        && !gormEntity.isVersioned()) {
      return transientProperty;
    }

    // for collections or maps of non-primitive types, i.e associations,
    // return transient property as spring data cassandra doesn't support
    if (!property.isTransient()) {
      if (property.isMap() || property.isCollectionLike()) {
        try {
          property.getDataType();
        } catch (InvalidDataAccessApiUsageException e) {
          return transientProperty;
        }
      }
    }
    return property;
  }
  private void persistAssociationsOfEntity(
      PersistentEntity pe, EntityAccess entityAccess, boolean isUpdate) {

    Object obj = entityAccess.getEntity();
    DirtyCheckable dirtyCheckable = null;
    if (obj instanceof DirtyCheckable) {
      dirtyCheckable = (DirtyCheckable) obj;
    }

    for (PersistentProperty pp : pe.getAssociations()) {
      if ((!isUpdate) || ((dirtyCheckable != null) && dirtyCheckable.hasChanged(pp.getName()))) {

        Object propertyValue = entityAccess.getProperty(pp.getName());

        if ((pp instanceof OneToMany) || (pp instanceof ManyToMany)) {
          Association association = (Association) pp;

          if (propertyValue != null) {

            if (association.isBidirectional()) { // Populate other side of bidi
              for (Object associatedObject : (Iterable) propertyValue) {
                EntityAccess assocEntityAccess =
                    createEntityAccess(association.getAssociatedEntity(), associatedObject);
                assocEntityAccess.setProperty(association.getReferencedPropertyName(), obj);
              }
            }

            Iterable targets = (Iterable) propertyValue;
            persistEntities(association.getAssociatedEntity(), targets);

            boolean reversed = RelationshipUtils.useReversedMappingFor(association);

            if (!reversed) {
              if (!(propertyValue instanceof LazyEnititySet)) {
                LazyEnititySet les =
                    new LazyEnititySet(
                        entityAccess,
                        association,
                        getMappingContext().getProxyFactory(),
                        getSession());
                les.addAll(targets);
                entityAccess.setProperty(association.getName(), les);
              }
            }
          }
        } else if (pp instanceof ToOne) {
          if (propertyValue != null) {
            ToOne to = (ToOne) pp;

            if (to.isBidirectional()) { // Populate other side of bidi
              EntityAccess assocEntityAccess =
                  createEntityAccess(to.getAssociatedEntity(), propertyValue);
              if (to instanceof OneToOne) {
                assocEntityAccess.setProperty(to.getReferencedPropertyName(), obj);
              } else {
                Collection collection =
                    (Collection) assocEntityAccess.getProperty(to.getReferencedPropertyName());
                if (collection == null) {
                  collection = new ArrayList();
                  assocEntityAccess.setProperty(to.getReferencedPropertyName(), collection);
                }
                if (!collection.contains(obj)) {
                  collection.add(obj);
                }
              }
            }

            persistEntity(to.getAssociatedEntity(), propertyValue);

            boolean reversed = RelationshipUtils.useReversedMappingFor(to);
            String relType = RelationshipUtils.relationshipTypeUsedFor(to);

            if (!reversed) {
              getSession()
                  .addPendingInsert(
                      new RelationshipPendingInsert(
                          entityAccess,
                          relType,
                          new EntityAccess(to.getAssociatedEntity(), propertyValue),
                          getCypherEngine()));
            }
          }
        } else {
          throw new IllegalArgumentException(
              "wtf don't know how to handle " + pp + "(" + pp.getClass() + ")");
        }
      }
    }
  }