Skip to content

Commit

Permalink
Add support for returning optional results
Browse files Browse the repository at this point in the history
  • Loading branch information
mmnaseri committed Oct 29, 2020
1 parent 35ed84e commit 1afe8ad
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

/**
* @author Milad Naseri ([email protected])
Expand All @@ -17,7 +18,7 @@ public interface MembershipRepository extends JpaRepository<Membership, String>

List<Membership> findByGroup(Group group);

Membership findByUserAndGroup(User user, Group group);
Optional<Membership> findByUserAndGroup(User user, Group group);

List<Membership> findAllByUserAndActive(User user, boolean active);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static java.util.stream.Collectors.toList;

Expand Down Expand Up @@ -43,7 +44,7 @@ public void deleteGroup(Group group) {

@Override
public void join(Group group, User user) {
if (membershipRepository.findByUserAndGroup(user, group) != null) {
if (membershipRepository.findByUserAndGroup(user, group).isPresent()) {
return;
}
final Membership membership = new Membership();
Expand All @@ -54,11 +55,11 @@ public void join(Group group, User user) {

@Override
public void leave(Group group, User user) {
final Membership membership = membershipRepository.findByUserAndGroup(user, group);
if (membership == null) {
final Optional<Membership> membership = membershipRepository.findByUserAndGroup(user, group);
if (!membership.isPresent()) {
return;
}
membershipRepository.delete(membership);
membershipRepository.delete(membership.get());
}

@Override
Expand All @@ -83,10 +84,11 @@ public List<Group> groups(User user) {

@Override
public void deactivate(final Group group, final User user) {
Membership membership = membershipRepository.findByUserAndGroup(user, group);
if (membership == null) {
Optional<Membership> optional = membershipRepository.findByUserAndGroup(user, group);
if (!optional.isPresent()) {
return;
}
Membership membership = optional.get();
membership.setActive(false);
membershipRepository.save(membership);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.mmnaseri.utils.spring.data.proxy.impl.adapters.NullToListenableFutureResultAdapter;
import com.mmnaseri.utils.spring.data.proxy.impl.adapters.NullToSliceResultAdapter;
import com.mmnaseri.utils.spring.data.proxy.impl.adapters.NumberIterableResultAdapter;
import com.mmnaseri.utils.spring.data.proxy.impl.adapters.OptionalResultAdapter;
import com.mmnaseri.utils.spring.data.proxy.impl.adapters.PageIterableResultAdapter;
import com.mmnaseri.utils.spring.data.proxy.impl.adapters.SameTypeResultAdapter;
import com.mmnaseri.utils.spring.data.proxy.impl.adapters.SimpleIterableResultAdapter;
Expand Down Expand Up @@ -66,6 +67,7 @@ public DefaultResultAdapterContext(boolean registerDefaults) {
adapters.add(new NullToListenableFutureResultAdapter());
adapters.add(new NumberIterableResultAdapter());
adapters.add(new SimpleIterableResultAdapter());
adapters.add(new OptionalResultAdapter());
adapters.add(new IteratorIterableResultAdapter());
adapters.add(new CollectionIterableResultAdapter());
adapters.add(new SliceIterableResultAdapter());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.mmnaseri.utils.spring.data.proxy.impl.adapters;

import com.mmnaseri.utils.spring.data.domain.Invocation;
import com.mmnaseri.utils.spring.data.error.ResultAdapterFailureException;

import java.util.Iterator;
import java.util.Optional;

/**
* This adapter accepts all invocations wherein the original value is an {@link Iterable} object and
* the requested method type is an {@link Optional} value.
*
* <p>While adapting, the adapter will also check that the iterable yields only one item and that it
* is of the same type or of a child type of the type requested by the invoked method.
*
* <p>This adapter runs at the priority {@literal -400}.
*
* @author Milad Naseri ([email protected])
* @since 2.1.1 (10/29/2020)
*/
public class OptionalResultAdapter extends AbstractIterableResultAdapter<Object> {

public OptionalResultAdapter() {
super(-400);
}

@Override
public boolean accepts(final Invocation invocation, final Object originalValue) {
if (!(originalValue instanceof Iterable)) {
return false;
}
final Class<?> returnType = invocation.getMethod().getReturnType();
return returnType.isAssignableFrom(Optional.class);
}

@Override
protected Object doAdapt(final Invocation invocation, final Iterable iterable) {
final Iterator iterator = iterable.iterator();
if (iterator.hasNext()) {
final Object value = iterator.next();
if (iterator.hasNext()) {
throw new ResultAdapterFailureException(
iterable,
invocation.getMethod().getReturnType(),
"Expected only one item but found many");
}
return Optional.of(value);
} else {
return Optional.empty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
import com.mmnaseri.utils.spring.data.tools.PropertyUtils;

import java.util.Iterator;
import java.util.Optional;
import java.util.concurrent.Future;

/**
* This adapter accepts all invocations wherein the original value is an {@link Iterable} object and
* the requested method type is a simple value. Simple types are types that are not a subtype of
* {@link Iterable}, {@link Iterator}, or {@link Future}.
* {@link Iterable}, {@link Iterator}, {@link Future}, or {@link Optional}.
*
* <p>While adapting, the adapter will also check that the iterable yields only one item and that it
* is of the same type or of a child type of the type requested by the invoked method.
Expand All @@ -34,7 +35,8 @@ public boolean accepts(Invocation invocation, Object originalValue) {
final Class<?> returnType = invocation.getMethod().getReturnType();
return !Iterable.class.isAssignableFrom(returnType)
&& !Iterator.class.isAssignableFrom(returnType)
&& !Future.class.isAssignableFrom(returnType);
&& !Future.class.isAssignableFrom(returnType)
&& !Optional.class.isAssignableFrom(returnType);
}

@Override
Expand Down

0 comments on commit 1afe8ad

Please sign in to comment.