diff --git a/container/oracle/initdb.d/02_ddl.sql b/container/oracle/initdb.d/02_ddl.sql index f07c5a60..0429dde7 100644 --- a/container/oracle/initdb.d/02_ddl.sql +++ b/container/oracle/initdb.d/02_ddl.sql @@ -189,10 +189,12 @@ CREATE TABLE JAM_OWNER.BEAM_DESTINATION_AUTHORIZATION CW_LIMIT NUMBER(24,12) NULL, COMMENTS VARCHAR2(256 CHAR) NULL, EXPIRATION_DATE DATE NULL, + CHANGED_YN VARCHAR2(1 CHAR) DEFAULT 'N' NOT NULL, CONSTRAINT BEAM_DESTINATION_AUTHORIZATION_PK PRIMARY KEY (BEAM_DESTINATION_ID,BEAM_AUTHORIZATION_ID), CONSTRAINT BEAM_DESTINATION_AUTHORIZATION_FK1 FOREIGN KEY (BEAM_DESTINATION_ID, FACILITY_ID) REFERENCES JAM_OWNER.BEAM_DESTINATION (BEAM_DESTINATION_ID, FACILITY_ID), CONSTRAINT BEAM_DESTINATION_AUTHORIZATION_FK2 FOREIGN KEY (BEAM_AUTHORIZATION_ID, FACILITY_ID) REFERENCES JAM_OWNER.BEAM_AUTHORIZATION (BEAM_AUTHORIZATION_ID, FACILITY_ID), - CONSTRAINT BEAM_DESTINATION_AUTHORIZATION_CK1 CHECK (BEAM_MODE IN ('None', 'Tune', 'CW', 'Ceramic Viewer', 'Viewer Limited', 'High Duty Cycle', 'BLM Checkout', 'RF Only')) + CONSTRAINT BEAM_DESTINATION_AUTHORIZATION_CK1 CHECK (BEAM_MODE IN ('None', 'Tune', 'CW', 'Ceramic Viewer', 'Viewer Limited', 'High Duty Cycle', 'BLM Checkout', 'RF Only')), + CONSTRAINT BEAM_DESTINATION_AUTHORIZATION_CK2 CHECK (CHANGED_YN IN ('Y', 'N')) ); CREATE TABLE JAM_OWNER.RF_SEGMENT_AUTHORIZATION @@ -203,10 +205,12 @@ CREATE TABLE JAM_OWNER.RF_SEGMENT_AUTHORIZATION HIGH_POWER_RF_YN VARCHAR2(1 CHAR) DEFAULT 'N' NOT NULL, COMMENTS VARCHAR2(256 CHAR) NULL, EXPIRATION_DATE DATE NULL, + CHANGED_YN VARCHAR2(1 CHAR) DEFAULT 'N' NOT NULL, CONSTRAINT RF_SEGMENT_AUTHORIZATION_PK PRIMARY KEY (RF_SEGMENT_ID,RF_AUTHORIZATION_ID), CONSTRAINT RF_SEGMENT_AUTHORIZATION_FK1 FOREIGN KEY (RF_SEGMENT_ID, FACILITY_ID) REFERENCES JAM_OWNER.RF_SEGMENT (RF_SEGMENT_ID, FACILITY_ID), CONSTRAINT RF_SEGMENT_AUTHORIZATION_FK2 FOREIGN KEY (RF_AUTHORIZATION_ID, FACILITY_ID) REFERENCES JAM_OWNER.RF_AUTHORIZATION (RF_AUTHORIZATION_ID, FACILITY_ID), - CONSTRAINT RF_SEGMENT_AUTHORIZATION_CK1 CHECK (HIGH_POWER_RF_YN IN ('Y', 'N')) + CONSTRAINT RF_SEGMENT_AUTHORIZATION_CK1 CHECK (HIGH_POWER_RF_YN IN ('Y', 'N')), + CONSTRAINT RF_SEGMENT_AUTHORIZATION_CK2 CHECK (CHANGED_YN IN ('Y', 'N')) ); CREATE TABLE JAM_OWNER.CREDITED_CONTROL diff --git a/src/main/java/org/jlab/jam/business/session/BeamAuthorizationFacade.java b/src/main/java/org/jlab/jam/business/session/BeamAuthorizationFacade.java index e522cc80..8e05f0d0 100644 --- a/src/main/java/org/jlab/jam/business/session/BeamAuthorizationFacade.java +++ b/src/main/java/org/jlab/jam/business/session/BeamAuthorizationFacade.java @@ -16,10 +16,8 @@ import javax.persistence.PersistenceContext; import javax.persistence.Query; import javax.persistence.TypedQuery; -import org.jlab.jam.persistence.entity.BeamAuthorization; -import org.jlab.jam.persistence.entity.BeamDestination; -import org.jlab.jam.persistence.entity.BeamDestinationAuthorization; -import org.jlab.jam.persistence.entity.Facility; +import org.jlab.jam.business.util.EqualityHelper; +import org.jlab.jam.persistence.entity.*; import org.jlab.jam.persistence.enumeration.OperationsType; import org.jlab.smoothness.business.exception.UserFriendlyException; @@ -145,6 +143,8 @@ public BigInteger saveAuthorization( authorizerFacade.isAuthorizer(facility, OperationsType.BEAM, username); } + BeamAuthorization previousAuth = findCurrent(facility); + BeamAuthorization beamAuthorization = new BeamAuthorization(); beamAuthorization.setFacility(facility); beamAuthorization.setComments(comments); @@ -198,11 +198,18 @@ public BigInteger saveAuthorization( } else { // mode = NONE (OFF) // We force expiration to empty da.setExpirationDate(null); + da.setCwLimit(null); + da.setComments(null); } da.setAuthorization(beamAuthorization); da.getDestinationAuthorizationPK() .setAuthorizationId(beamAuthorization.getBeamAuthorizationId()); + + boolean changed = isChanged(da, previousAuth); + + da.setChanged(changed); + em.persist(da); } @@ -213,6 +220,67 @@ public BigInteger saveAuthorization( return beamAuthorization.getBeamAuthorizationId(); } + private boolean isChanged( + BeamDestinationAuthorization newDestAuth, BeamAuthorization previousAuth) { + boolean changed = true; + + // System.err.println("Beam Authorization changed?: " + newDestAuth); + + if (previousAuth != null) { + List destList = previousAuth.getDestinationAuthorizationList(); + + // System.err.println("destList: " + destList == null ? "null" : destList.size()); + + for (BeamDestinationAuthorization oldDestAuth : destList) { + if (oldDestAuth + .getDestinationAuthorizationPK() + .getBeamDestinationId() + .equals(newDestAuth.getDestinationAuthorizationPK().getBeamDestinationId())) { + /*System.err.println("Found matching destination \"" + oldDestAuth.getDestination() + "\""); + System.err.println( + "Beam Mode Change \"" + + !EqualityHelper.nullableStringEqual( + oldDestAuth.getBeamMode(), newDestAuth.getBeamMode()) + + "\""); + System.err.println( + "Current Limit Change \"" + + !EqualityHelper.nullableObjEqual( + oldDestAuth.getCwLimit(), newDestAuth.getCwLimit()) + + "\""); + System.err.println( + "Date Change \"" + + !EqualityHelper.nullableDateEqual( + oldDestAuth.getExpirationDate(), newDestAuth.getExpirationDate()) + + "\" - \"" + + oldDestAuth.getExpirationDate() + + "\" vs \"" + + newDestAuth.getExpirationDate() + + "\""); + System.err.println( + "Comment Change \"" + + !EqualityHelper.nullableStringEqual( + oldDestAuth.getComments(), newDestAuth.getComments()) + + "\"");*/ + + // Check if change + changed = + (!EqualityHelper.nullableStringEqual( + oldDestAuth.getBeamMode(), newDestAuth.getBeamMode())) + || (!EqualityHelper.nullableObjEqual( + oldDestAuth.getCwLimit(), newDestAuth.getCwLimit())) + || !EqualityHelper.nullableDateEqual( + oldDestAuth.getExpirationDate(), newDestAuth.getExpirationDate()) + || !EqualityHelper.nullableStringEqual( + oldDestAuth.getComments(), newDestAuth.getComments()); + + break; + } + } + } + + return changed; + } + @PermitAll public void setLogEntry(BigInteger beamAuthorizationId, Long logId, String logbookServer) { BeamAuthorization current = find(beamAuthorizationId); diff --git a/src/main/java/org/jlab/jam/business/session/RFAuthorizationFacade.java b/src/main/java/org/jlab/jam/business/session/RFAuthorizationFacade.java index 9f9623fd..5271bdd2 100644 --- a/src/main/java/org/jlab/jam/business/session/RFAuthorizationFacade.java +++ b/src/main/java/org/jlab/jam/business/session/RFAuthorizationFacade.java @@ -13,6 +13,7 @@ import javax.persistence.PersistenceContext; import javax.persistence.Query; import javax.persistence.TypedQuery; +import org.jlab.jam.business.util.EqualityHelper; import org.jlab.jam.persistence.entity.*; import org.jlab.jam.persistence.enumeration.OperationsType; import org.jlab.smoothness.business.exception.UserFriendlyException; @@ -137,6 +138,8 @@ public BigInteger saveAuthorization( authorizerFacade.isAuthorizer(facility, OperationsType.RF, username); } + RFAuthorization previousAuth = findCurrent(facility); + RFAuthorization authorization = new RFAuthorization(); authorization.setFacility(facility); authorization.setComments(comments); @@ -189,10 +192,16 @@ public BigInteger saveAuthorization( } else { // High Power = OFF // We force expiration to empty da.setExpirationDate(null); + da.setComments(null); } da.setRFAuthorization(authorization); da.getSegmentAuthorizationPK().setRFAuthorizationId(authorization.getRfAuthorizationId()); + + boolean changed = isChanged(da, previousAuth); + + da.setChanged(changed); + em.persist(da); } @@ -203,6 +212,55 @@ public BigInteger saveAuthorization( return authorization.getRfAuthorizationId(); } + private boolean isChanged(RFSegmentAuthorization newSegAuth, RFAuthorization previousAuth) { + boolean changed = true; + + // System.err.println("RF Authorization changed?: " + newSegAuth); + + if (previousAuth != null) { + List segList = previousAuth.getRFSegmentAuthorizationList(); + + // System.err.println("segList: " + segList == null ? "null" : segList.size()); + + for (RFSegmentAuthorization oldSegAuth : segList) { + if (oldSegAuth + .getSegmentAuthorizationPK() + .getRFSegmentId() + .equals(newSegAuth.getSegmentAuthorizationPK().getRFSegmentId())) { + /*System.err.println("Found matching segment \"" + oldSegAuth.getSegment() + "\""); + System.err.println( + "RF Change \"" + (oldSegAuth.isHighPowerRf() != newSegAuth.isHighPowerRf()) + "\""); + System.err.println( + "Date Change \"" + + !EqualityHelper.nullableDateEqual( + oldSegAuth.getExpirationDate(), newSegAuth.getExpirationDate()) + + "\" - \"" + + oldSegAuth.getExpirationDate() + + "\" vs \"" + + newSegAuth.getExpirationDate() + + "\""); + System.err.println( + "Comment Change \"" + + !EqualityHelper.nullableStringEqual( + oldSegAuth.getComments(), newSegAuth.getComments()) + + "\"");*/ + + // Check if change + changed = + (oldSegAuth.isHighPowerRf() != newSegAuth.isHighPowerRf()) + || !EqualityHelper.nullableDateEqual( + oldSegAuth.getExpirationDate(), newSegAuth.getExpirationDate()) + || !EqualityHelper.nullableStringEqual( + oldSegAuth.getComments(), newSegAuth.getComments()); + + break; + } + } + } + + return changed; + } + @PermitAll public void setLogEntry(BigInteger rfAuthorizationId, Long logId, String logbookServer) { RFAuthorization current = find(rfAuthorizationId); diff --git a/src/main/java/org/jlab/jam/business/session/ReducedBeamAuthorizationBuilder.java b/src/main/java/org/jlab/jam/business/session/ReducedBeamAuthorizationBuilder.java index 19feb5ff..d9bd42eb 100644 --- a/src/main/java/org/jlab/jam/business/session/ReducedBeamAuthorizationBuilder.java +++ b/src/main/java/org/jlab/jam/business/session/ReducedBeamAuthorizationBuilder.java @@ -52,6 +52,7 @@ private boolean populateReducedPermissionsDueToVerification( operationAuth.setBeamMode("None"); operationAuth.setCwLimit(null); operationAuth.setExpirationDate(null); + operationAuth.setChanged(true); operationAuth.setComments( "Permission automatically revoked due to credited control " + verification.getCreditedControl().getName() @@ -66,12 +67,9 @@ private boolean populateReducedPermissionsDueToVerification( } if (atLeastOne) { - String comments = clone.getComments(); - if (comments == null) { - comments = ""; - } + String comments = ""; // We replace Change Notes completely with changes String csv = IOUtil.toCsv(revokedDestinationList.toArray()); - comments = comments + "\nCHANGE: Destination control verification revoked: " + csv; + comments = comments + "\nDestination control verification revoked: " + csv; clone.setComments(comments); } @@ -107,6 +105,7 @@ private boolean populateReducedPermissionDueToAuthorizationExpiration( operationAuth.setBeamMode("None"); operationAuth.setCwLimit(null); operationAuth.setExpirationDate(null); + operationAuth.setChanged(true); operationAuth.setComments( "Permission automatically revoked due to director's authorization expiration"); atLeastOne = true; @@ -116,12 +115,9 @@ private boolean populateReducedPermissionDueToAuthorizationExpiration( } if (atLeastOne) { - String comments = clone.getComments(); - if (comments == null) { - comments = ""; - } + String comments = ""; // We replace Change Notes completely with changes String csv = IOUtil.toCsv(revokedDestinationList.toArray()); - comments = comments + "\nCHANGE: Destination authorization revoked: " + csv; + comments = comments + "\nDestination authorization revoked: " + csv; clone.setComments(comments); } diff --git a/src/main/java/org/jlab/jam/business/session/ReducedRFAuthorizationBuilder.java b/src/main/java/org/jlab/jam/business/session/ReducedRFAuthorizationBuilder.java index 6e07f8ac..6c97676b 100644 --- a/src/main/java/org/jlab/jam/business/session/ReducedRFAuthorizationBuilder.java +++ b/src/main/java/org/jlab/jam/business/session/ReducedRFAuthorizationBuilder.java @@ -52,6 +52,7 @@ private boolean populateReducedPermissionsDueToVerification( if (segmentId.equals(verification.getRFSegment().getRFSegmentId())) { operationAuth.setHighPowerRf(false); operationAuth.setExpirationDate(null); + operationAuth.setChanged(true); operationAuth.setComments( "Permission automatically revoked due to credited control " + verification.getCreditedControl().getName() @@ -66,12 +67,9 @@ private boolean populateReducedPermissionsDueToVerification( } if (atLeastOne) { - String comments = clone.getComments(); - if (comments == null) { - comments = ""; - } + String comments = ""; // We replace Change Notes completely with changes String csv = IOUtil.toCsv(revokedSegmentList.toArray()); - comments = comments + "\nCHANGE: Segment control verification revoked: " + csv; + comments = comments + "\nSegment control verification revoked: " + csv; clone.setComments(comments); } @@ -104,6 +102,7 @@ private boolean populateReducedPermissionDueToAuthorizationExpiration( if (containsName(segmentList, operationAuth)) { operationAuth.setHighPowerRf(false); operationAuth.setExpirationDate(null); + operationAuth.setChanged(true); operationAuth.setComments( "Permission automatically revoked due to director's authorization expiration"); atLeastOne = true; @@ -113,12 +112,9 @@ private boolean populateReducedPermissionDueToAuthorizationExpiration( } if (atLeastOne) { - String comments = clone.getComments(); - if (comments == null) { - comments = ""; - } + String comments = ""; // We replace Change Notes completely with changes String csv = IOUtil.toCsv(revokedSegmentList.toArray()); - comments = comments + "\nCHANGE: Segment authorization revoked: " + csv; + comments = comments + "\nSegment authorization revoked: " + csv; clone.setComments(comments); } diff --git a/src/main/java/org/jlab/jam/business/util/EqualityHelper.java b/src/main/java/org/jlab/jam/business/util/EqualityHelper.java new file mode 100644 index 00000000..31b581c7 --- /dev/null +++ b/src/main/java/org/jlab/jam/business/util/EqualityHelper.java @@ -0,0 +1,74 @@ +package org.jlab.jam.business.util; + +import java.util.Date; + +public final class EqualityHelper { + private EqualityHelper() { + // Can't instantiate because private + } + + public static boolean nullableObjEqual(Object one, Object two) { + boolean equal = false; + + if (one == null) { + if (two == null) { + equal = true; + } + } else { + equal = one.equals(two); + } + + return equal; + } + + public static boolean nullableStringEqual(String one, String two) { + // String can be null, or contain just whitespace and we treat them as equal + + boolean equal = false; + + if (one != null && one.isBlank()) { + one = null; + } + + if (two != null && two.isBlank()) { + two = null; + } + + if (one == null) { + if (two == null) { + equal = true; + } + } else { + equal = one.equals(two); + } + + return equal; + } + + public static boolean nullableDateEqual(Date one, Date two) { + // Dates can be of type sql.Date vs util.Date and we treat them as equal + + boolean equal = false; + + Long oneUnix = null; + Long twoUnix = null; + + if (one != null) { + oneUnix = one.getTime(); + } + + if (two != null) { + twoUnix = two.getTime(); + } + + if (one == null) { + if (two == null) { + equal = true; + } + } else { + equal = oneUnix.equals(twoUnix); + } + + return equal; + } +} diff --git a/src/main/java/org/jlab/jam/persistence/entity/BeamAuthorization.java b/src/main/java/org/jlab/jam/persistence/entity/BeamAuthorization.java index 44847e87..9874bf1c 100644 --- a/src/main/java/org/jlab/jam/persistence/entity/BeamAuthorization.java +++ b/src/main/java/org/jlab/jam/persistence/entity/BeamAuthorization.java @@ -67,6 +67,10 @@ public class BeamAuthorization implements Serializable { @OneToMany(cascade = CascadeType.ALL, mappedBy = "beamAuthorization", fetch = FetchType.EAGER) private List beamDestinationAuthorizationList; + public boolean isAutomatedReduction() { + return !modifiedBy.equals(authorizedBy); + } + public BeamAuthorization() {} public BigInteger getBeamAuthorizationId() { diff --git a/src/main/java/org/jlab/jam/persistence/entity/BeamDestinationAuthorization.java b/src/main/java/org/jlab/jam/persistence/entity/BeamDestinationAuthorization.java index a70a8d49..14873950 100644 --- a/src/main/java/org/jlab/jam/persistence/entity/BeamDestinationAuthorization.java +++ b/src/main/java/org/jlab/jam/persistence/entity/BeamDestinationAuthorization.java @@ -4,20 +4,10 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.Date; -import javax.persistence.Basic; -import javax.persistence.Column; -import javax.persistence.EmbeddedId; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.NamedQueries; -import javax.persistence.NamedQuery; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; +import javax.persistence.*; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; +import org.jlab.smoothness.persistence.util.YnStringToBoolean; /** * @author ryans @@ -75,6 +65,11 @@ public class BeamDestinationAuthorization implements Serializable { @ManyToOne(optional = false, fetch = FetchType.LAZY) private BeamAuthorization beamAuthorization; + @Basic + @Column(name = "CHANGED_YN", nullable = false, length = 1) + @Convert(converter = YnStringToBoolean.class) + private boolean changed; + public BeamDestinationAuthorization() {} public BeamDestinationAuthorization(DestinationAuthorizationPK destinationAuthorizationPK) { @@ -152,6 +147,14 @@ public void setAuthorization(BeamAuthorization beamAuthorization) { this.beamAuthorization = beamAuthorization; } + public boolean isChanged() { + return changed; + } + + public void setChanged(boolean changed) { + this.changed = changed; + } + @Override public int hashCode() { int hash = 0; diff --git a/src/main/java/org/jlab/jam/persistence/entity/RFAuthorization.java b/src/main/java/org/jlab/jam/persistence/entity/RFAuthorization.java index 5c4d4bed..f8d8c16b 100644 --- a/src/main/java/org/jlab/jam/persistence/entity/RFAuthorization.java +++ b/src/main/java/org/jlab/jam/persistence/entity/RFAuthorization.java @@ -64,6 +64,10 @@ public class RFAuthorization implements Serializable { @Column(name = "LOGENTRY_URL", length = 2048) private String logentryUrl; + public boolean isAutomatedReduction() { + return !modifiedBy.equals(authorizedBy); + } + @OneToMany(cascade = CascadeType.ALL, mappedBy = "rfAuthorization", fetch = FetchType.EAGER) private List rfSegmentAuthorizationList; diff --git a/src/main/java/org/jlab/jam/persistence/entity/RFSegmentAuthorization.java b/src/main/java/org/jlab/jam/persistence/entity/RFSegmentAuthorization.java index ea661a70..d9264b95 100644 --- a/src/main/java/org/jlab/jam/persistence/entity/RFSegmentAuthorization.java +++ b/src/main/java/org/jlab/jam/persistence/entity/RFSegmentAuthorization.java @@ -60,6 +60,11 @@ public class RFSegmentAuthorization implements Serializable { @ManyToOne(optional = false, fetch = FetchType.LAZY) private RFAuthorization rfAuthorization; + @Basic + @Column(name = "CHANGED_YN", nullable = false, length = 1) + @Convert(converter = YnStringToBoolean.class) + private boolean changed; + public RFSegmentAuthorization() {} public RFSegmentAuthorization(SegmentAuthorizationPK segmentAuthorizationPK) { @@ -122,6 +127,14 @@ public void setRFAuthorization(RFAuthorization rfAuthorization) { this.rfAuthorization = rfAuthorization; } + public boolean isChanged() { + return changed; + } + + public void setChanged(boolean changed) { + this.changed = changed; + } + @Override public int hashCode() { int hash = 0; diff --git a/src/main/webapp/WEB-INF/tags/beam-operations-panel.tag b/src/main/webapp/WEB-INF/tags/beam-operations-panel.tag index 542c7711..88b686eb 100644 --- a/src/main/webapp/WEB-INF/tags/beam-operations-panel.tag +++ b/src/main/webapp/WEB-INF/tags/beam-operations-panel.tag @@ -30,7 +30,7 @@ - + @@ -122,12 +122,12 @@ -

Notes

+

Change Notes

- - + +

Digital Signature