io.mosip.registration.util.control.impl.BiometricFxControl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of registration-client Show documentation
Show all versions of registration-client Show documentation
Maven project of MOSIP Registration UI
package io.mosip.registration.util.control.impl;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import io.mosip.registration.api.docscanner.DocScannerUtil;
import io.mosip.registration.audit.AuditManagerService;
import io.mosip.registration.constants.AuditEvent;
import io.mosip.registration.constants.AuditReferenceIdTypes;
import io.mosip.registration.constants.Components;
import io.mosip.registration.context.SessionContext;
import io.mosip.registration.controller.ClientApplication;
import io.mosip.registration.dto.mastersync.GenericDto;
import io.mosip.registration.dto.packetmanager.BiometricsDto;
import io.mosip.registration.dto.packetmanager.DocumentDto;
import io.mosip.registration.dto.schema.ConditionalBioAttributes;
import io.mosip.registration.service.bio.BioService;
import io.mosip.registration.enums.Modality;
import javafx.scene.layout.*;
import org.apache.commons.collections4.ListUtils;
import io.mosip.kernel.core.logger.spi.Logger;
import io.mosip.registration.config.AppConfig;
import io.mosip.registration.constants.RegistrationConstants;
import io.mosip.registration.context.ApplicationContext;
import io.mosip.registration.controller.BaseController;
import io.mosip.registration.controller.Initialization;
import io.mosip.registration.controller.device.GenericBiometricsController;
import io.mosip.registration.dto.schema.UiFieldDTO;
import io.mosip.registration.exception.RegBaseCheckedException;
import io.mosip.registration.service.IdentitySchemaService;
import io.mosip.registration.util.control.FxControl;
import io.mosip.registration.validator.RequiredFieldValidator;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Parent;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import org.mvel2.MVEL;
import javax.imageio.ImageIO;
public class BiometricFxControl extends FxControl {
protected static final Logger LOGGER = AppConfig.getLogger(BiometricFxControl.class);
private GenericBiometricsController biometricsController;
private IdentitySchemaService identitySchemaService;
private BioService bioService;
private Modality currentModality;
private Map>> modalityAttributeMap = new HashMap<>();
private List exceptionProofFields;
public BiometricFxControl(List biometricExceptionProofFields) {
org.springframework.context.ApplicationContext applicationContext = ClientApplication.getApplicationContext();
this.biometricsController = applicationContext.getBean(GenericBiometricsController.class);
this.identitySchemaService = applicationContext.getBean(IdentitySchemaService.class);
this.bioService = applicationContext.getBean(BioService.class);
this.requiredFieldValidator = applicationContext.getBean(RequiredFieldValidator.class);
this.auditFactory = applicationContext.getBean(AuditManagerService.class);
exceptionProofFields = biometricExceptionProofFields;
}
@Override
public FxControl build(UiFieldDTO uiFieldDTO) {
this.uiFieldDTO = uiFieldDTO;
this.control = this;
this.node = create();
getRegistrationDTo().CONFIGURED_BIOATTRIBUTES.put(uiFieldDTO.getId(), uiFieldDTO.getBioAttributes());
return this.node == null ? null : this.control;
}
@Override
public void setData(Object data) {
if (data != null) {
getRegistrationDTo().addAllBiometrics(uiFieldDTO.getId(), (Map) data,
bioService.getMDMQualityThreshold(currentModality), bioService.getRetryCount(currentModality));
}
//remove POE_EOP document if there are no biometric exception
if(getRegistrationDTo().getBiometricExceptions(uiFieldDTO.getId()).isEmpty()) {
LOGGER.info("Removing exception photo as no exceptions are marked currently");
biometricsController.deleteProofOfExceptionDocument();
}
}
@Override
public void fillData(Object data) {
}
@Override
public Object getData() {
List requiredAttributes = requiredFieldValidator.getRequiredBioAttributes(uiFieldDTO, getRegistrationDTo());
List configBioAttributes = ListUtils.intersection(requiredAttributes,
Modality.getAllBioAttributes(currentModality));
return getRegistrationDTo().getBiometric(uiFieldDTO.getId(), configBioAttributes);
}
@Override
public void setListener(Node node) {
}
@Override
public void selectAndSet(Object data) {
}
@Override
public boolean isValid() {
return true;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public List getPossibleValues(String langCode) {
return null;
}
private GridPane create() {
String fieldName = this.uiFieldDTO.getId();
List modalityList = getModalityButtons();
List labels = new ArrayList<>();
getRegistrationDTo().getSelectedLanguagesByApplicant().forEach(langCode -> {
labels.add(this.uiFieldDTO.getLabel().get(langCode));
});
Label label = new Label();
label.setText(String.join(RegistrationConstants.SLASH, labels));
label.getStyleClass().add(RegistrationConstants.QUALITY_BOX_LABEL);
GridPane gridPane = createGridPane();
gridPane.setHgap(10);
gridPane.setId(fieldName);
gridPane.add(label,1,0);
GridPane.setHalignment(label, HPos.CENTER);
GridPane.setValignment(label, VPos.TOP);
Node modalityListingNode = null;
switch (getBiometricFieldLayout()) {
case "compact":
modalityListingNode = new HBox();
modalityListingNode.setId(uiFieldDTO.getId()+"_listing");
//((HBox)modalityListingNode).setSpacing(5);
((HBox)modalityListingNode).getChildren().addAll(modalityList);
gridPane.add(modalityListingNode,1,1);
break;
default:
modalityListingNode = new VBox();
modalityListingNode.setId(uiFieldDTO.getId()+"_listing");
//((VBox)modalityListingNode).setSpacing(5);
((VBox)modalityListingNode).getChildren().addAll(modalityList);
gridPane.add(modalityListingNode,0,1);
Parent captureDetails = null;
try {
captureDetails = BaseController.loadWithNewInstance(getClass().getResource("/fxml/BiometricsCapture.fxml"),
this.biometricsController);
captureDetails.visibleProperty().bind(gridPane.visibleProperty());
captureDetails.managedProperty().bind(gridPane.managedProperty());
GridPane.setHalignment(captureDetails, HPos.CENTER);
GridPane.setValignment(captureDetails, VPos.TOP);
gridPane.add(captureDetails,1,1);
} catch (IOException e) {
LOGGER.error("Failed to load biometrics capture details page", e);
}
scanForModality(this.control, currentModality);
break;
}
modalityListingNode.visibleProperty().bind(gridPane.visibleProperty());
modalityListingNode.managedProperty().bind(gridPane.managedProperty());
return gridPane;
}
private String getBiometricFieldLayout() {
return this.uiFieldDTO.getFieldLayout() == null ? "default" : this.uiFieldDTO.getFieldLayout();
}
private GridPane createGridPane() {
GridPane gridPane = new GridPane();
gridPane.setPadding(new Insets(50, 0, 0, 0));
RowConstraints topRowConstraints = new RowConstraints();
topRowConstraints.setPercentHeight(5);
RowConstraints midRowConstraints = new RowConstraints();
midRowConstraints.setPercentHeight(95);
gridPane.getRowConstraints().addAll(topRowConstraints,midRowConstraints);
ColumnConstraints columnConstraint1 = new ColumnConstraints();
columnConstraint1.setPercentWidth(15);
ColumnConstraints columnConstraint2 = new ColumnConstraints();
columnConstraint2.setPercentWidth(80);
ColumnConstraints columnConstraint3 = new ColumnConstraints();
columnConstraint3.setPercentWidth(5);
gridPane.getColumnConstraints().addAll(columnConstraint1, columnConstraint2,columnConstraint3);
return gridPane;
}
private List getModalityButtons() {
this.currentModality = null;
List modalityList = new ArrayList<>();
List requiredBioAttributes = requiredFieldValidator.getRequiredBioAttributes(this.uiFieldDTO, getRegistrationDTo());
//if(!requiredBioAttributes.isEmpty()) {
for(Modality modality : Modality.values()) {
List modalityAttributes = ListUtils.intersection(requiredBioAttributes, modality.getAttributes());
modalityAttributeMap.put(modality, new ArrayList<>());
modalityAttributeMap.get(modality).add(modalityAttributes);
modalityAttributeMap.get(modality).add(ListUtils.subtract(modality.getAttributes(), requiredBioAttributes));
if(!modalityAttributes.isEmpty()) {
HBox modalityView = new HBox();
modalityView.setSpacing(10);
modalityView.setId(uiFieldDTO.getId() + modality);
modalityView.getChildren().add(addModalityButton(modality));
modalityList.add(modalityView);
if(currentModality == null)
currentModality = modality;
addRemoveCaptureStatusMark(modalityView, modality);
}
}
if(!modalityList.isEmpty())
createExceptionPhoto(modalityList);
//}
return modalityList;
}
private ImageView getImageView(Image image, double height) {
ImageView imageView = new ImageView(image);
imageView.setFitHeight(height);
imageView.setFitWidth(height);
imageView.setPreserveRatio(true);
return imageView;
}
private Button addModalityButton(Modality modality) {
Button button = new Button();
button.setId(uiFieldDTO.getId()+ modality+"Button");
button.setMaxSize(100, 90);
button.setMinSize(100, 90);
button.setPrefSize(100, 90);
List capturedData = getRegistrationDTo().getBiometric(uiFieldDTO.getId(), modality.getAttributes());
try {
Image image = null;
if(Modality.EXCEPTION_PHOTO == modality) {
image = getExceptionDocumentAsImage();
}
image = !capturedData.isEmpty() ? biometricsController.getBioStreamImage(uiFieldDTO.getId(), modality,
capturedData.get(0).getNumOfRetries()) : (image == null ? biometricsController.getImage(getImageIconPath(modality.name()),true) : image);
button.setGraphic(getImageView(image, 80));
} catch (RegBaseCheckedException exception) {
LOGGER.error("Exception while Getting Image", exception);
}
button.getStyleClass().add(RegistrationConstants.MODALITY_BUTTONS);
Tooltip tooltip = new Tooltip(ApplicationContext.getInstance().getBundle(ApplicationContext.applicationLanguage(),
RegistrationConstants.LABELS).getString(modality.name()));
tooltip.getStyleClass().add(RegistrationConstants.TOOLTIP_STYLE);
button.setTooltip(tooltip);
button.setOnAction(getModalityActionHandler(this, modality));
return button;
}
private EventHandler getModalityActionHandler(BiometricFxControl control, Modality modality) {
return new EventHandler() {
@Override
public void handle(ActionEvent event) {
currentModality = modality;
scanForModality(control, currentModality);
}
};
}
private void scanForModality(FxControl control, Modality modality) {
LOGGER.info("Clicked on modality {} for field {}", modality, control.getUiSchemaDTO().getId());
//this is null when nothing to be captured for this field, so ignore
if(modality == null)
return;
List requiredAttributes = requiredFieldValidator.getRequiredBioAttributes(uiFieldDTO, getRegistrationDTo());
List configBioAttributes = ListUtils.intersection(requiredAttributes, Modality.getAllBioAttributes(modality));
List nonConfigBioAttributes = ListUtils.subtract(Modality.getAllBioAttributes(modality), configBioAttributes);
switch (getBiometricFieldLayout()) {
case "compact" :
try {
biometricsController.init(control, modality,
configBioAttributes,nonConfigBioAttributes);
} catch (IOException e) {
LOGGER.error("Failed to load GenericBiometricFXML.fxml", e);
}
break;
default :
biometricsController.initializeWithoutStage(control, modality,
configBioAttributes,nonConfigBioAttributes);
}
}
public String getImageIconPath(String modality) {
String imageIconPath = RegistrationConstants.DEFAULT_EXCEPTION_IMG;
if (modality != null) {
switch (modality) {
case RegistrationConstants.FACE:
imageIconPath = RegistrationConstants.FACE_IMG;
break;
case RegistrationConstants.IRIS_DOUBLE:
imageIconPath = RegistrationConstants.DOUBLE_IRIS_IMG;
break;
case RegistrationConstants.FINGERPRINT_SLAB_RIGHT:
imageIconPath = RegistrationConstants.RIGHTPALM_IMG;
break;
case RegistrationConstants.FINGERPRINT_SLAB_LEFT:
imageIconPath = RegistrationConstants.LEFTPALM_IMG;
break;
case RegistrationConstants.FINGERPRINT_SLAB_THUMBS:
imageIconPath = RegistrationConstants.THUMB_IMG;
break;
}
}
return imageIconPath;
}
@Override
public void refresh() {
LOGGER.error("Refreshing biometric field {} ", uiFieldDTO.getId());
List modalityButtons = getModalityButtons();
if(modalityButtons.isEmpty()) {
this.node.setVisible(false);
this.node.setManaged(false);
}
else {
Node listingNode = this.node.lookup(RegistrationConstants.HASH+ uiFieldDTO.getId()+"_listing");
if(listingNode instanceof HBox) {
((HBox)listingNode).getChildren().clear();
((HBox)listingNode).getChildren().addAll(modalityButtons);
}
if(listingNode instanceof VBox) {
((VBox)listingNode).getChildren().clear();
((VBox)listingNode).getChildren().addAll(modalityButtons);
}
this.node.setVisible(true);
this.node.setManaged(true);
scanForModality(this.control, this.currentModality);
}
List requiredAttributes = requiredFieldValidator.getRequiredBioAttributes(uiFieldDTO, getRegistrationDTo());
for(String bioAttribute : uiFieldDTO.getBioAttributes()) {
if(!requiredAttributes.contains(bioAttribute)) {
getRegistrationDTo().clearBIOCache(uiFieldDTO.getId(), bioAttribute);
}
}
}
@Override
public boolean canContinue() {
if(requiredFieldValidator.getRequiredBioAttributes(uiFieldDTO,
getRegistrationDTo()).isEmpty()) {
return true;
}
Map capturedDetails = bioService.getCapturedBiometrics(uiFieldDTO,
getRegistrationDTo().getIdSchemaVersion(), getRegistrationDTo());
String expression = String.join(" && ", uiFieldDTO.getBioAttributes());
ConditionalBioAttributes selectedCondition = requiredFieldValidator.getConditionalBioAttributes(uiFieldDTO,
getRegistrationDTo());
if(selectedCondition != null) {
expression = selectedCondition.getValidationExpr();
}
boolean valid = MVEL.evalToBoolean(expression, capturedDetails);
valid = biometricsController.hasApplicantBiometricException() ? valid && biometricsController.isBiometricExceptionProofCollected() : valid;
//TODO - display message about exception proof
if (valid) {
auditFactory.audit(AuditEvent.REG_BIO_CAPTURE_NEXT, Components.REG_BIOMETRICS, SessionContext.userId(),
AuditReferenceIdTypes.USER_ID.getReferenceTypeId());
}
return valid;
}
private void createExceptionPhoto(List modalityList) {
if(exceptionProofFields == null || exceptionProofFields.isEmpty())
return;
HBox modalityView = new HBox();
modalityView.setSpacing(10);
modalityView.setId(uiFieldDTO.getId() + Modality.EXCEPTION_PHOTO);
Button button = new Button();
button.setMaxSize(100, 90);
button.setMinSize(100, 90);
button.setPrefSize(100, 90);
try {
Image image = getExceptionDocumentAsImage();
image = image != null ? image : biometricsController.getImage(getImageIconPath(Modality.EXCEPTION_PHOTO.name()),true);
button.setGraphic(getImageView(image, 80));
} catch (RegBaseCheckedException exception) {
LOGGER.error("Exception while Getting Image", exception);
}
button.getStyleClass().add(RegistrationConstants.MODALITY_BUTTONS);
Tooltip tooltip = new Tooltip(ApplicationContext.getInstance().getBundle(ApplicationContext.applicationLanguage(),
RegistrationConstants.LABELS).getString(Modality.EXCEPTION_PHOTO.name()));
tooltip.getStyleClass().add(RegistrationConstants.TOOLTIP_STYLE);
button.setTooltip(tooltip);
button.setOnAction(getModalityActionHandler(this, Modality.EXCEPTION_PHOTO));
modalityView.getChildren().add(addModalityButton(Modality.EXCEPTION_PHOTO));
addRemoveCaptureStatusMark(modalityView, Modality.EXCEPTION_PHOTO);
boolean exceptionExists = biometricsController.hasApplicantBiometricException();
modalityView.setVisible(exceptionExists);
modalityView.setManaged(exceptionExists);
modalityView.getChildren().forEach( child -> {
child.setVisible(exceptionExists);
child.setManaged(exceptionExists);
});
modalityList.add(modalityView);
}
public void displayExceptionPhoto() {
boolean exceptionExists = biometricsController.hasApplicantBiometricException();
HBox exceptionPhotoNode = (HBox) this.node.lookup(RegistrationConstants.HASH + uiFieldDTO.getId() + Modality.EXCEPTION_PHOTO);
if(exceptionPhotoNode != null) {
exceptionPhotoNode.setVisible(exceptionExists);
exceptionPhotoNode.setManaged(exceptionExists);
exceptionPhotoNode.getChildren().forEach( child -> {
child.setVisible(exceptionExists);
child.setManaged(exceptionExists);
});
}
}
public void refreshModalityButton(Modality modality) {
LOGGER.info("Refreshing biometric field {} modality : {}", uiFieldDTO.getId(), modality);
Node tempNode = getField(uiFieldDTO.getId()+modality);
if(tempNode == null)
return;
HBox modalityView = (HBox) tempNode;
Button button = (Button) modalityView.getChildren().get(0);
Image image = null;
List capturedData = getRegistrationDTo().getBiometric(uiFieldDTO.getId(), modality.getAttributes());
if(!capturedData.isEmpty()) {
Optional bestCopy = capturedData.stream().sorted(Comparator.comparingDouble(BiometricsDto::getQualityScore)).findFirst();
image = biometricsController.getBioStreamImage(uiFieldDTO.getId(), modality,
bestCopy.isPresent() ? bestCopy.get().getNumOfRetries() : 1);
} else {
image = biometricsController.getBioStreamImage(uiFieldDTO.getId(), modality, 0);
}
button.setGraphic(getImageView(image, 80));
button.setPrefSize(105, 80);
addRemoveCaptureStatusMark(modalityView, modality);
displayExceptionPhoto();
}
private void addRemoveCaptureStatusMark(HBox pane, Modality modality) {
if (pane.getChildren().size() > 1) {
pane.getChildren().remove(1);
}
boolean isExceptionsMarked = isAnyExceptions(modality);
boolean isCaptured = !getRegistrationDTo().getBiometric(uiFieldDTO.getId(), modality.getAttributes()).isEmpty();
if(modality.equals(Modality.EXCEPTION_PHOTO) && biometricsController.isBiometricExceptionProofCollected()) {
pane.getChildren().add(addCompletionImg(getCompletionImgPath(false)));
return;
}
if(isExceptionsMarked) {
pane.getChildren().add(addCompletionImg(getCompletionImgPath(true)));
return;
}
if(isCaptured) {
pane.getChildren().add(addCompletionImg(getCompletionImgPath(false)));
return;
}
}
private String getCompletionImgPath(boolean isAnyException) {
return isAnyException ? RegistrationConstants.EXCLAMATION_IMG
: RegistrationConstants.TICK_CIRICLE_IMG;
}
public boolean isAnyExceptions(Modality modality) {
//checking with configured set of attributes for the given modality
return modalityAttributeMap.get(modality).get(0)
.stream()
.anyMatch( attr -> biometricsController.isBiometricExceptionAvailable(uiFieldDTO.getId(), attr));
}
public boolean isAllExceptions(Modality modality) {
//checking with configured set of attributes for the given modality
return modalityAttributeMap.get(modality).get(0)
.stream()
.allMatch( attr -> biometricsController.isBiometricExceptionAvailable(uiFieldDTO.getId(), attr));
}
private ImageView addCompletionImg(String imgPath) {
ImageView tickImageView = null;
try {
tickImageView = new ImageView(biometricsController.getImage(imgPath,true));
tickImageView.setId(uiFieldDTO.getId() + currentModality.name() + "PANE");
tickImageView.setFitWidth(35);
tickImageView.setFitHeight(35);
tickImageView.setPreserveRatio(true);
} catch (RegBaseCheckedException regBaseCheckedException) {
LOGGER.error("Exception while getting image");
}
return tickImageView;
}
//TODO check how multiple exception photos can be taken, and also displayed in biometric field
public Image getExceptionDocumentAsImage() {
try {
DocumentDto documentDto = null;
for(String key : getRegistrationDTo().getDocuments().keySet()) {
if(getRegistrationDTo().getDocuments().get(key).getCategory().equals(RegistrationConstants.POE_DOCUMENT) &&
getRegistrationDTo().getDocuments().get(key).getType().equals("EOP") &&
getRegistrationDTo().getDocuments().get(key).getFormat().equals(RegistrationConstants.SCANNER_IMG_TYPE)) {
documentDto = getRegistrationDTo().getDocuments().get(key);
break;
}
}
if(documentDto == null)
return null;
if(RegistrationConstants.PDF.equalsIgnoreCase(documentDto.getFormat())) {
List list = DocScannerUtil.pdfToImages(documentDto.getDocument());
return list.isEmpty() ? null : DocScannerUtil.getImage(list.get(0));
} else {
InputStream is = new ByteArrayInputStream(documentDto.getDocument());
return DocScannerUtil.getImage(ImageIO.read(is));
}
} catch (Exception ex) {
LOGGER.error("Failed to read document as image", ex);
}
return null;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy