/**
* Copyright (C) 2012 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 co.jirm.orm.builder.update;
import static com.google.common.collect.Maps.newLinkedHashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import static co.jirm.core.util.JirmPrecondition.check;
import co.jirm.mapper.copy.AbstractCopyBuilder;
import co.jirm.mapper.definition.SqlParameterDefinition;
import co.jirm.orm.JirmOptimisticLockException;
import com.google.common.base.Optional;
public class UpdateObjectBuilder<T> extends AbstractCopyBuilder<UpdateObjectBuilder<T>> {
private final UpdateBuilderFactory<T> updateBuilderFactory;
private final LinkedHashMap<String, Object> object;
private UpdateObjectBuilder(
UpdateBuilderFactory<T> factory,
LinkedHashMap<String, Object> object) {
super();
this.updateBuilderFactory = factory;
this.object = object;
}
static <T> UpdateObjectBuilder<T> newInstance(
UpdateBuilderFactory<T> factory,
LinkedHashMap<String, Object> object) {
return new UpdateObjectBuilder<T>(factory, object);
}
@Override
public UpdateObjectBuilder<T> exclude(String... properties) {
checkProperties(properties);
return super.exclude(properties);
}
@Override
public UpdateObjectBuilder<T> include(String... properties) {
checkProperties(properties);
return super.include(properties);
}
private void checkProperties(String... properties) {
for (String p : properties) {
check.argument(
updateBuilderFactory.getDefinition().getParameters().containsKey(p),
"Property {} not found for object: {}", p, updateBuilderFactory.getDefinition().getObjectType());
}
}
public void execute() {
LinkedHashMap<String, Object> m = object;
LinkedHashMap<String, Object> where = newLinkedHashMap();
Iterator<Entry<String, Object>> it = m.entrySet().iterator();
while(it.hasNext()) {
Entry<String, Object> e = it.next();
Optional<SqlParameterDefinition> p = updateBuilderFactory.getDefinition().resolveParameter(e.getKey());
if (p.isPresent()) {
if (p.get().isId()) {
where.put(e.getKey(), e.getValue());
it.remove();
}
else if (p.get().isVersion()) {
Object o = e.getValue();
check.state(o instanceof Number,
"Property: {}, @Version only supports numerics", e.getKey());
Number n = (Number) o;
where.put(e.getKey(), n.intValue());
e.setValue(n.intValue() + 1);
}
else if (excludeProperties.contains(p.get().getParameterName())) {
it.remove();
}
else if( ! includeProperties.isEmpty() && ! includeProperties.contains(p.get().getParameterName()) ) {
it.remove();
}
}
}
check.state(!where.isEmpty(), "where should not be empty");
int results = update(m, where);
if (results < 1) {
throw new JirmOptimisticLockException("Failed to update object: {}, where: {}",
updateBuilderFactory.getDefinition().getObjectType(),
where);
}
}
private int update(Map<String,Object> setValues, Map<String, Object> filters) {
return updateBuilderFactory
.update()
.setAll(setValues)
.where().propertyAll(filters)
.execute();
}
@Override
protected UpdateObjectBuilder<T> getSelf() {
return this;
}
}