Skip to content

Commit

Permalink
DATAMONGO-943 - Add support for $position to Update $push $each.
Browse files Browse the repository at this point in the history
We now support $position on update.push.

Original pull request: #248.
  • Loading branch information
christophstrobl authored and Thomas Darimont committed Nov 28, 2014
1 parent 461e7d0 commit dab6034
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 1 deletion.
Expand Up @@ -163,7 +163,8 @@ public Update push(String key, Object value) {

/**
* Update using {@code $push} modifier. <br/>
* Allows creation of {@code $push} command for single or multiple (using {@code $each}) values.
* Allows creation of {@code $push} command for single or multiple (using {@code $each}) values as well as using
* {@code $position}.
*
* @see http://docs.mongodb.org/manual/reference/operator/update/push/
* @see http://docs.mongodb.org/manual/reference/operator/update/each/
Expand Down Expand Up @@ -577,6 +578,31 @@ public boolean equals(Object that) {
}
}

/**
* {@link Modifier} implementation used to propagate {@code $position}.
*
* @author Christoph Strobl
* @since 1.7
*/
private static class PositionModifier implements Modifier {

private final int position;

public PositionModifier(int position) {
this.position = position;
}

@Override
public String getKey() {
return "$position";
}

@Override
public Object getValue() {
return position;
}
}

/**
* Builder for creating {@code $push} modifiers
*
Expand Down Expand Up @@ -605,6 +631,42 @@ public Update each(Object... values) {
return Update.this.push(key, this.modifiers);
}

/**
* Forces values to be added at the given {@literal position}.
*
* @param position needs to be greater than or equal to zero.
* @return
* @since 1.7
*/
public PushOperatorBuilder atPosition(int position) {

if (position < 0) {
throw new IllegalArgumentException("Position must be greater than or equal to zero.");
}

this.modifiers.addModifier(new PositionModifier(position));

return this;
}

/**
* Forces values to be added at given {@literal position}.
*
* @param position can be {@literal null} which will be appended at the last position.
* @return
* @since 1.7
*/
public PushOperatorBuilder atPosition(Position position) {

if (position == null || Position.LAST.equals(position)) {
return this;
}

this.modifiers.addModifier(new PositionModifier(0));

return this;
}

/**
* Propagates {@link #value(Object)} to {@code $push}
*
Expand Down
Expand Up @@ -44,6 +44,7 @@
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.mongodb.core.query.Update.Position;

import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
Expand Down Expand Up @@ -293,6 +294,76 @@ public void testUpdateShouldAllowMultiplePushEachForDifferentFields() {
assertThat(getAsDBObject(push, "type").containsField("$each"), is(true));
}

/**
* @see DATAMONGO-943
*/
@Test
public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositiveIndexParameter() {

Update update = new Update().push("key").atPosition(2).each(Arrays.asList("Arya", "Arry", "Weasel"));

DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Object.class));

DBObject push = getAsDBObject(mappedObject, "$push");
DBObject key = getAsDBObject(push, "key");

assertThat(key.containsField("$position"), is(true));
assertThat((Integer) key.get("$position"), is(2));
assertThat(getAsDBObject(push, "key").containsField("$each"), is(true));
}

/**
* @see DATAMONGO-943
*/
@Test
public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionFirst() {

Update update = new Update().push("key").atPosition(Position.FIRST).each(Arrays.asList("Arya", "Arry", "Weasel"));

DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Object.class));

DBObject push = getAsDBObject(mappedObject, "$push");
DBObject key = getAsDBObject(push, "key");

assertThat(key.containsField("$position"), is(true));
assertThat((Integer) key.get("$position"), is(0));
assertThat(getAsDBObject(push, "key").containsField("$each"), is(true));
}

/**
* @see DATAMONGO-943
*/
@Test
public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionLast() {

Update update = new Update().push("key").atPosition(Position.LAST).each(Arrays.asList("Arya", "Arry", "Weasel"));

DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Object.class));

DBObject push = getAsDBObject(mappedObject, "$push");
DBObject key = getAsDBObject(push, "key");

assertThat(key.containsField("$position"), is(false));
assertThat(getAsDBObject(push, "key").containsField("$each"), is(true));
}

/**
* @see DATAMONGO-943
*/
@Test
public void updatePushEachAtPositionWorksCorrectlyWhenGivenPositionNull() {

Update update = new Update().push("key").atPosition(null).each(Arrays.asList("Arya", "Arry", "Weasel"));

DBObject mappedObject = mapper.getMappedObject(update.getUpdateObject(), context.getPersistentEntity(Object.class));

DBObject push = getAsDBObject(mappedObject, "$push");
DBObject key = getAsDBObject(push, "key");

assertThat(key.containsField("$position"), is(false));
assertThat(getAsDBObject(push, "key").containsField("$each"), is(true));
}

/**
* @see DATAMONGO-410
*/
Expand Down
Expand Up @@ -476,4 +476,12 @@ public void getUpdateObjectShouldReturnCorrectRepresentationForBitwiseXor() {
assertThat(update.getUpdateObject(),
equalTo(new BasicDBObjectBuilder().add("$bit", new BasicDBObject("key", new BasicDBObject("xor", 10L))).get()));
}

/**
* @see DATAMONGO-943
*/
@Test(expected = IllegalArgumentException.class)
public void pushShouldThrowExceptionWhenGivenNegativePosition() {
new Update().push("foo").atPosition(-1).each("booh");
}
}

0 comments on commit dab6034

Please sign in to comment.