/** * Performs an action on each Subject in the provided set. * * <p>Subjects are loaded, supplied to the consumer, and then allowed to be * uncached by the implementation.</p> * * <p>This should be used to apply bulk changes or gather data about all * Subjects in the collection. The provided consumer will be supplied * asynchronously. Acting upon a large collection may be particularly * resource intensive.</p> * * <p>Implementations may choose to load and process subjects in * parallel.</p> * * @param action The action to perform on each subject * @param identifiers a set of identifiers to apply the action to * @return A future which will complete when the operation has finished */ default CompletableFuture<Void> applyToAll(Consumer<Subject> action, Set<String> identifiers) { Preconditions.checkNotNull(action, "action"); Preconditions.checkNotNull(identifiers, "identifiers"); return CompletableFuture.runAsync(() -> { for (String id : identifiers) { Subject subject = loadSubject(id).join(); action.accept(subject); suggestUnload(subject.getIdentifier()); } }); }
@ApiModelProperty(value = "The unique id of this subject", required = true) public String getId() { return value.getIdentifier(); }
@Override public boolean addParent(Set<Context> contexts, Subject parent) { contexts = ImmutableSet.copyOf(contexts); while (true) { Map.Entry<String, String> newEnt = Maps.immutableEntry(parent.getContainingCollection().getIdentifier(), parent.getIdentifier()); List<Map.Entry<String, String>> oldParents = this.parents.get(contexts); List<Map.Entry<String, String>> newParents = ImmutableList.<Map.Entry<String, String>>builder() .addAll(oldParents == null ? Collections.emptyList() : oldParents) .add(newEnt) .build(); if (oldParents != null && oldParents.contains(newEnt)) { return false; } if (updateCollection(this.parents, contexts, oldParents, newParents)) { return true; } } }
@Override public boolean removeParent(Set<Context> contexts, Subject parent) { contexts = ImmutableSet.copyOf(contexts); while (true) { Map.Entry<String, String> removeEnt = Maps.immutableEntry(parent.getContainingCollection().getIdentifier(), parent.getIdentifier()); List<Map.Entry<String, String>> oldParents = this.parents.get(contexts); List<Map.Entry<String, String>> newParents; if (oldParents == null || !oldParents.contains(removeEnt)) { return false; } newParents = new ArrayList<>(oldParents); newParents.remove(removeEnt); if (updateCollection(this.parents, contexts, oldParents, Collections.unmodifiableList(newParents))) { return true; } } }
private static List<Subject> printWeights(List<Subject> subjects) { subjects.forEach(x -> System.out.println(x.getIdentifier() + " - " + Util.getIntOptionFromSubject(x, "nucleus.list.weight"))); return subjects; }
private static Subject createSubjectWithWeight(String name, int weight, Subject... parents) { Subject subject = Mockito.mock(Subject.class); Mockito.when(subject.getIdentifier()).thenReturn(name); Mockito.when(subject.getOption(Mockito.anySetOf(Context.class), Mockito.eq("nucleus.list.weight"))) .thenReturn(Optional.of(String.valueOf(weight))); Mockito.when(subject.getOption(Mockito.eq("nucleus.list.weight"))).thenReturn(Optional.of(String.valueOf(weight))); List<SubjectReference> lsr = getSubjectReferences(Arrays.asList(parents)); Mockito.when(subject.getParents()).thenReturn(lsr); Mockito.when(subject.getParents(Mockito.anySetOf(Context.class))).thenReturn(lsr); return subject; }
private static Subject createSubject(String name, Subject... parents) { Subject subject = Mockito.mock(Subject.class); List<Subject> ls = Arrays.asList(parents); Mockito.when(subject.getIdentifier()).thenReturn(name); Mockito.when(subject.getOption(Mockito.anySetOf(Context.class), Mockito.eq("nucleus.list.weight"))) .then(x -> ls.stream().map(y -> y.getOption("nucleus.list.weight")).filter(Optional::isPresent).findFirst().orElse(Optional.empty())); Mockito.when(subject.getOption(Mockito.eq("nucleus.list.weight"))) .then(x -> ls.stream().map(y -> y.getOption("nucleus.list.weight")).filter(Optional::isPresent).findFirst().orElse(Optional.empty())); List<SubjectReference> lsr = getSubjectReferences(Arrays.asList(parents)); Mockito.when(subject.getParents()).thenReturn(lsr); Mockito.when(subject.getParents(Mockito.anySetOf(Context.class))).thenReturn(lsr); return subject; }
@Override public boolean addParent(final Set<Context> set, final Subject subject) { return wasSuccess(data.update(input -> input.addParent(parSet(set), subject.getContainingCollection().getIdentifier(), subject.getIdentifier()))); }
@Override public boolean removeParent(final Set<Context> set, final Subject subject) { return wasSuccess(data.update(input -> input.removeParent(parSet(set), subject.getContainingCollection().getIdentifier(), subject.getIdentifier()))); }
@Test public void testTreeWeightedGroups() { Subject subject1 = createSubject("subject1"); Subject subject2 = createSubjectWithWeight("subject2", 4, subject1); Subject subject2a = createSubjectWithWeight("subject2a", -1, subject1); Subject subject3 = createSubject("subject3", subject1, subject2); Subject subject4 = createSubjectWithWeight("subject4", 1, subject1, subject2); Subject subject5 = createSubjectWithWeight("subject5", 2, subject1, subject2); List<Subject> subjects = Lists.newArrayList(subject1, subject2, subject2a, subject3, subject4, subject5); List<Subject> sorted = printWeights(subjects.stream().sorted((x, y) -> ListPlayerCommand.groupComparison(ListPlayerCommand.weightingFunction, x, y)) .collect(Collectors.toList())); List<Subject> expectedOrder = Lists.newArrayList(subject3, subject2, subject5, subject4, subject1, subject2a); for (int i = 0; i < sorted.size(); i++) { Assert.assertEquals( "Index " + i + " is wrong! (expected: " + expectedOrder.get(i).getIdentifier() + ", got: " + sorted.get(i).getIdentifier() + ")", expectedOrder.get(i), sorted.get(i)); } }