Organization.java
package access.model;
import access.manage.Contact;
import access.manage.PathUpdateType;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.hypersistence.utils.hibernate.type.json.JsonType;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.Formula;
import org.hibernate.annotations.Type;
import org.springframework.util.CollectionUtils;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static access.manage.ManageData.*;
@Entity(name = "organizations")
@NoArgsConstructor
@Getter
@Setter
public class Organization implements NameHolder {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column
@NotNull
private String name;
@Column(name = "schac_home_organization")
private String schacHomeOrganization;
@Column(name = "manage_identifier")
private String manageIdentifier;
@Column(name = "manage_version")
private Integer manageVersion;
@Column(name = "ticket_key")
private String ticketKey;
@Column(name = "created_at")
private Instant createdAt;
@Column(name = "last_contact_reminder_at")
private Instant lastContactReminderAt;
@Transient
private Map<String, Object> metaData = new HashMap<>();
@Enumerated(EnumType.STRING)
@Column
@NotNull
private OrganizationStatus status = OrganizationStatus.PENDING_APPROVAL;
@OneToMany(mappedBy = "organization", orphanRemoval = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Application> applications = new HashSet<>();
@OneToMany(mappedBy = "organization", orphanRemoval = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<OrganizationMembership> organizationMemberships = new HashSet<>();
@OneToMany(mappedBy = "organization", orphanRemoval = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<JoinRequest> joinRequests = new HashSet<>();
@OneToMany(mappedBy = "organization", orphanRemoval = true, fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<Invitation> invitations = new HashSet<>();
@Formula(value = "(SELECT COUNT(*) FROM organization_memberships om WHERE om.organization_id=id)")
private Long memberCount;
@Formula(value = "(SELECT COUNT(*) FROM applications a WHERE a.organization_id=id)")
private Long applicationCount;
public Organization(String name, String schacHomeOrganization) {
this.name = name;
this.schacHomeOrganization = schacHomeOrganization;
this.createdAt = Instant.now();
}
public Organization(String name, String schacHomeOrganization, String manageIdentifier, Integer manageVersion) {
this.name = name;
this.schacHomeOrganization = schacHomeOrganization;
this.manageIdentifier = manageIdentifier;
this.manageVersion = manageVersion;
this.createdAt = Instant.now();
}
@JsonIgnore
public OrganizationMembership addOrganizationMembership(OrganizationMembership organizationMembership) {
this.organizationMemberships.add(organizationMembership);
organizationMembership.setOrganization(this);
return organizationMembership;
}
@JsonIgnore
public void removeApplication(Application application) {
//This is required by Hibernate - children can't be dereferenced
Set<Application> newApplications = this.applications
.stream().filter(app -> !app.getId().equals(application.getId())).collect(Collectors.toSet());
this.applications.clear();
this.applications.addAll(newApplications);
}
@JsonIgnore
public void removeJoinRequest(JoinRequest joinRequest) {
//This is required by Hibernate - children can't be dereferenced
Set<JoinRequest> newJoinRequests = this.joinRequests
.stream().filter(jr -> !jr.getId().equals(joinRequest.getId())).collect(Collectors.toSet());
this.joinRequests.clear();
this.joinRequests.addAll(newJoinRequests);
}
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
public Map<String, Object> getMetaData() {
return metaData;
}
@JsonIgnore
public boolean mergeMetaData(Map<String, Object> provider, boolean force) {
// For new Connections
Integer newManageVersion = (Integer) provider.get("version");
if (newManageVersion.equals(this.manageVersion) && !force && !CollectionUtils.isEmpty(this.metaData)) {
//Two-way synchronization and optimistic locking
return false;
}
this.manageIdentifier = (String) provider.get("id");
this.manageVersion = newManageVersion;
this.metaData = new HashMap<>();
Map<String, Object> data = getData(provider);
String entityID = (String) data.get("entityid");
this.metaData.put("entityID", entityID);
String state = (String) data.get("state");
this.metaData.put("state", state);
this.metaData.put("allowedall", data.get("allowedall"));
List.of("allowedEntities", "disableConsent", "stepupEntities", "mfaEntities")
.forEach(key -> {
this.metaData.put(key, data.getOrDefault(key, List.of()));
});
Map<String, Object> metaDataFields = getMetaDataFields(data);
this.name = (String) metaDataFields.getOrDefault("name:en", this.name);
this.metaData.put("name", name);
this.metaData.put("logoUrl", metaDataFields.get("logo:0:url"));
String allKeyWords = (String) metaDataFields.getOrDefault("keywords:0:nl","") +
metaDataFields.getOrDefault("keywords:0:en","");
Set<String> keyWords = Arrays.stream(allKeyWords.split(" ")).map(String::trim).collect(Collectors.toSet());
this.metaData.put("keyWords", keyWords);
List<Contact> contactPersons = new ArrayList<>();
IntStream.of(0, 1, 2, 3, 4, 5).forEach(index -> {
if (metaDataFields.containsKey("contacts:" + index + ":emailAddress")) {
Contact contact = new Contact(
(String) metaDataFields.get("contacts:" + index + ":contactType"),
(String) metaDataFields.get("contacts:" + index + ":givenName"),
(String) metaDataFields.get("contacts:" + index + ":surName"),
(String) metaDataFields.get("contacts:" + index + ":emailAddress")
);
contactPersons.add(contact);
}
});
this.metaData.put("contactPersons", contactPersons);
return true;
}
}