class ImmutablePolicy implements Policy {

    @Override
    public Policy setSubjectFor(final CharSequence label, final Subject subject) {
        final Label lbl = Label.of(label);
        checkNotNull(subject, "subject to set to the Policy entry");

        final Policy result;
        final PolicyEntry existingPolicyEntry = entries.get(lbl);
        if (null != existingPolicyEntry) {
            final Subjects existingSubjects = existingPolicyEntry.getSubjects();
            final Subjects newSubjects = existingSubjects.setSubject(subject);
            if (!Objects.equals(existingSubjects, newSubjects)) {
                final Map<Label, PolicyEntry> entriesCopy = copyEntries();
                entriesCopy.put(lbl, newPolicyEntry(lbl, newSubjects, existingPolicyEntry.getResources()));
                result = new ImmutablePolicy(policyId, entriesCopy, lifecycle, revision, modified, created);
            } else {
                result = this;
            }
        } else {
            result = setSubjectsFor(label, Subjects.newInstance(subject));
        }

        return result;
    }

    private  ImmutablePolicy(@Nullable final PolicyId policyId,
            final Map<Label, PolicyEntry> theEntries,
            @Nullable final PolicyLifecycle lifecycle,
            @Nullable final PolicyRevision revision,
            @Nullable final Instant modified,
            @Nullable final Instant created);

}