Merge pull request 'feature_27488' (!4) from feature_27488 into master

Reviewed-on: #4
This commit is contained in:
Francesco Mangiacrapa 2024-06-28 16:34:15 +02:00
commit 6347b32450
11 changed files with 361 additions and 102 deletions

View File

@ -4,6 +4,13 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v2.2.0-SNAPSHOT] - 2024-05-17
#### Enhancements
- [#27488] In edit mode allowed to erase (not mandatory) fields according to data type
- [#27627] Moved logs at TRACE level
## [v2.1.1] - 2024-03-19
#### Enhancements

View File

@ -14,7 +14,7 @@
<groupId>org.gcube.portlets.widgets</groupId>
<artifactId>metadata-profile-form-builder-widget</artifactId>
<packaging>jar</packaging>
<version>2.1.1</version>
<version>2.2.0-SNAPSHOT</version>
<name>Metadata Profile Form Builder</name>
<description>
The Metadata Profile Form Builder is a widget able to build dynamically a web form by reading "gCube Metadata Profile/s"

View File

@ -30,6 +30,7 @@ import com.github.gwtbootstrap.client.ui.TextBox;
import com.github.gwtbootstrap.client.ui.constants.AlertType;
import com.github.gwtbootstrap.client.ui.constants.ControlGroupType;
import com.github.gwtbootstrap.client.ui.constants.IconType;
import com.github.gwtbootstrap.client.ui.constants.ResizeType;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.SpanElement;
@ -58,10 +59,24 @@ import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
/**
* The Class MetaDataFieldSkeleton.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* May 20, 2024
*/
public class MetaDataFieldSkeleton extends Composite {
private static MetaDataFieldSkeletonUiBinder uiBinder = GWT.create(MetaDataFieldSkeletonUiBinder.class);
/**
* The Interface MetaDataFieldSkeletonUiBinder.
*
* @author Francesco Mangiacrapa at ISTI-CNR francesco.mangiacrapa@isti.cnr.it
*
* May 20, 2024
*/
interface MetaDataFieldSkeletonUiBinder extends UiBinder<Widget, MetaDataFieldSkeleton> {
}
@ -70,7 +85,7 @@ public class MetaDataFieldSkeleton extends Composite {
@UiField
SpanElement name;
@UiField
SimplePanel elementPanel;
FlowPanel elementPanel;
@UiField
FlowPanel noteFieldContainer;
@UiField
@ -86,6 +101,11 @@ public class MetaDataFieldSkeleton extends Composite {
@UiField
ControlGroup metafieldControlGroup;
@UiField
Button eraseButton;
@UiField
FlowPanel eraseFieldContainer;
// private static final String REGEX_IS_NUMBER = "[0-9]+[.]?[0-9]+";
// the element that holds the value (it could be a checkbox, textbox or listbox,
@ -122,16 +142,26 @@ public class MetaDataFieldSkeleton extends Composite {
private static final String UPLOAD_MISSING_FILE = "You must upload a file";
/**
* Instantiates a new meta data field skeleton.
*
* @param field the field
* @param eventBus the event bus
* @param operation the operation
* @throws Exception the exception
*/
public MetaDataFieldSkeleton(final MetadataFieldWrapper field, HandlerManager eventBus, OPERATION operation)
throws Exception {
initWidget(uiBinder.createAndBindUi(this));
// prepare information
this.field = field;
// event bus
this.eventBus = eventBus;
eraseFieldContainer.setVisible(false);
eraseButton.setIcon(IconType.BAN_CIRCLE);
// bind
bind();
@ -165,6 +195,7 @@ public class MetaDataFieldSkeleton extends Composite {
final TextArea textArea = new TextArea();
textArea.setWidth("100%");
textArea.setResize(ResizeType.VERTICAL);
if (field.getDefaultValue() != null)
textArea.setText(field.getDefaultValue());
@ -237,14 +268,16 @@ public class MetaDataFieldSkeleton extends Composite {
case Text:
holder = new TextArea();
TextArea txtArea = ((TextArea) holder);
txtArea.setResize(ResizeType.VERTICAL);
if (field.getDefaultValue() != null)
((TextArea) holder).setText(field.getDefaultValue());
txtArea.setText(field.getDefaultValue());
if (operation.equals(OPERATION.UPDATE)) {
try {
if (field.getCurrentSingleValue() != null)
((TextArea) holder).setText((String) field.getCurrentSingleValue());
txtArea.setText((String) field.getCurrentSingleValue());
} catch (Exception e) {
// TODO: handle exception
}
@ -420,11 +453,7 @@ public class MetaDataFieldSkeleton extends Composite {
// if it is not mandatory and not multi-selection, add a disabled option
// (placeholder)
if (!field.getMandatory() && !field.isMultiSelection()) {
tempListBox.addItem("Select " + field.getFieldName());
tempListBox.setValue(0, "");
tempListBox.getElement().getElementsByTagName("option").getItem(0).setAttribute("disabled",
"disabled");
tempListBox.setSelectedValue("Select " + field.getFieldName());
listBoxSelectPlaceholder(tempListBox);
}
// get vocabulary fields
@ -498,13 +527,18 @@ public class MetaDataFieldSkeleton extends Composite {
mandatorySymbol.getStyle().setDisplay(Display.NONE);
// add to the elementPanel
elementPanel.add(holder);
elementPanel.insert(holder, 0);
// set holder width
if (holder.getClass().equals(ListBox.class))
holder.setWidth("96%");
holder.setWidth("99%");
else
holder.setWidth("95%");
holder.setWidth("97%");
//If the field is erasable views the erase panel
if(field.isErasableField()) {
eraseFieldContainer.setVisible(true);
}
// set the notes, if any, and the popover
if (field.getNote() != null && !field.getNote().isEmpty()) {
@ -541,7 +575,7 @@ public class MetaDataFieldSkeleton extends Composite {
}
/**
* Bind on events
* Bind on events.
*/
private void bind() {
@ -557,8 +591,22 @@ public class MetaDataFieldSkeleton extends Composite {
}
});
eraseButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
erase();
}
});
}
/**
* On info icon click.
*
* @param c the c
*/
@UiHandler("focusPanelIconContainer")
void onInfoIconClick(ClickEvent c) {
@ -577,7 +625,7 @@ public class MetaDataFieldSkeleton extends Composite {
}
/**
* Check if this field has valid values
* Check if this field has valid values.
*
* @return a string with the occurred error on error, null otherwise
*/
@ -764,10 +812,10 @@ public class MetaDataFieldSkeleton extends Composite {
}
/**
* Check if this string is a number
* Check if this string is a number.
*
* @param numberValue
* @return
* @param numberValue the number value
* @return true, if is a number
*/
private boolean isANumber(String numberValue) {
return numberValue.matches("-?\\d+(\\.\\d+)?");
@ -777,8 +825,8 @@ public class MetaDataFieldSkeleton extends Composite {
* Check if value matches validator (regex). In case validator is null, true is
* returned.
*
* @param value
* @param validator
* @param value the value
* @param validator the validator
* @return true if validator is null OR value.matches(reges), false otherwise
*/
private boolean checkValidator(String value, String validator) {
@ -794,7 +842,7 @@ public class MetaDataFieldSkeleton extends Composite {
* Returns the current value of the field. In case of TimeInterval or TimeList
* see getTimeIntervalOrTimeListWithoutMissing()
*
* @return
* @return the field current value
*/
public List<String> getFieldCurrentValue() {
@ -918,9 +966,9 @@ public class MetaDataFieldSkeleton extends Composite {
}
/**
* Returns the current name of the field
* Returns the current name of the field.
*
* @return
* @return the field name original
*/
public String getFieldNameOriginal() {
@ -929,9 +977,9 @@ public class MetaDataFieldSkeleton extends Composite {
}
/**
* Returns the current name of the field
* Returns the current name of the field.
*
* @return
* @return the field name qualified
*/
public String getFieldNameQualified() {
@ -940,8 +988,10 @@ public class MetaDataFieldSkeleton extends Composite {
return field.getFieldId();
}
//Using the getFieldNameFromCategory if the category is present in the model as cateogory:fieldName
if (field.getFieldNameFromCategory() != null && field.getFieldNameFromCategory().compareTo(field.getFieldName())!=0) {
// Using the getFieldNameFromCategory if the category is present in the model as
// cateogory:fieldName
if (field.getFieldNameFromCategory() != null
&& field.getFieldNameFromCategory().compareTo(field.getFieldName()) != 0) {
return field.getFieldNameFromCategory();
}
@ -950,7 +1000,126 @@ public class MetaDataFieldSkeleton extends Composite {
}
/**
* Freeze this widget (after on create)
* Erase the field. Reset the field
*/
private void erase() {
if (field.isErasableField()) {
switch (field.getType()) {
case Boolean:
((CheckBox) holder).setValue(false);
break;
case GeoJSON:
case Text:
((TextArea) holder).setText("");
break;
case Time:
DataTimeBox dtbox = ((DataTimeBox) holder);
dtbox.setStartDate(null, null);
dtbox.setEndDate(null, null);
break;
case Time_Interval:
DataTimeBox dtboxTI = rangesList.get(0);
dtboxTI.setStartDate(null, null);
dtboxTI.setEndDate(null, null);
break;
case Times_ListOf:
for (DataTimeBox el : rangesList) {
el.setStartDate(null, null);
el.setEndDate(null, null);
}
break;
case Number:
((TextBox) holder).setText("");
break;
case String:
if (holder.getClass().equals(ListBox.class)) {
ListBox tempListBox = (ListBox) holder;
// if it is not mandatory and not multi-selection, add a disabled option
// (placeholder)
//selecting the default value of the list
// if (field.getDefaultValue() != null) {
// tempListBox.setSelectedValue(field.getDefaultValue());
// return;
// }
//selecting unique element of the list
// if(tempListBox.getItemCount()==1) {
// tempListBox.setSelectedValue(tempListBox.getItemText(0));
// return;
// }
if (!field.isMultiSelection()) {
listBoxSelectPlaceholder(tempListBox);
} else {
// TODO
}
} else
((TextBox) holder).setText("");
break;
case File:
if (holder.getClass().equals(MultipleDilaogUpload.class)
|| holder.getClass().equals(DialogUpload.class)) {
DialogUpload dUpload = (DialogUpload) holder;
dUpload.eraseLastUpload();
}
break;
default:
break;
}
}
}
/**
* List box select placeholder.
*
* @param listBox the list box
*/
private void listBoxSelectPlaceholder(ListBox listBox) {
String placeholder = "Select " + field.getFieldName();
if(listBox.getItemCount()==0) {
//create
listBox.addItem(placeholder);
listBox.setValue(0, "");
listBox.getElement().getElementsByTagName("option").getItem(0).setAttribute("disabled", "disabled");
listBox.setSelectedIndex(0);
}else {
//update
String itemText = listBox.getItemText(0);
//if the first element is the placeholder, select it
if(itemText!=null && itemText.compareTo(placeholder)==0) {
listBox.setValue(0, "");
listBox.getElement().getElementsByTagName("option").getItem(0).setAttribute("disabled", "disabled");
listBox.setSelectedIndex(0);
}
}
}
/**
* Freeze this widget (after on create).
*
* @param bool the bool
*/
public void freeze(boolean bool) {
@ -1011,20 +1180,26 @@ public class MetaDataFieldSkeleton extends Composite {
}
/**
* Get the original MetadataFieldWrapper object
* Get the original MetadataFieldWrapper object.
*
* @return
* @return the field
*/
public MetadataFieldWrapper getField() {
return field;
}
/**
* Removes the error.
*/
public void removeError() {
metafieldControlGroup.setType(ControlGroupType.NONE);
}
/**
* Show error.
*/
public void showError() {
metafieldControlGroup.setType(ControlGroupType.ERROR);
@ -1032,10 +1207,10 @@ public class MetaDataFieldSkeleton extends Composite {
}
/**
* Build the range interval
* Build the range interval.
*
* @param rangeValues
* @param tb
* @param rangeValues the range values
* @param tb the tb
*/
private void setRangeTimeInTimeBox(String rangeValues, DataTimeBox tb) {
// set time, if present
@ -1096,9 +1271,9 @@ public class MetaDataFieldSkeleton extends Composite {
}
/**
* Check if the group associated (if it exists) should be forced
* Check if the group associated (if it exists) should be forced.
*
* @return
* @return true, if is group to force
*/
public boolean isGroupToForce() {
FieldAsGroup asGroup = field.getAsGroup();
@ -1109,9 +1284,9 @@ public class MetaDataFieldSkeleton extends Composite {
}
/**
* Check if the propagateUp is set
* Check if the propagateUp is set.
*
* @return
* @return true, if is propagate up
*/
public boolean isPropagateUp() {
FieldAsGroup asGroup = field.getAsGroup();

View File

@ -1,15 +1,15 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b="urn:import:com.github.gwtbootstrap.client.ui"
xmlns:b2="urn:import:com.github.gwtbootstrap.datetimepicker.client.ui"
xmlns:b3="urn:import:com.github.gwtbootstrap.datepicker.client.ui">
<ui:style>
.note-container {
display: inline-block;
float: right;
width: 5%;
.button-container {
color: #aaaaaa;
height: 100%;
text-align: center;
}
.note-field-text {
@ -22,6 +22,10 @@
.element-panel {
display: inline-block;
}
.flex-display-panel {
display: flex;
}
</ui:style>
<g:HTMLPanel width="100%">
<b:ControlGroup ui:field="metafieldControlGroup">
@ -30,20 +34,41 @@
<span ui:field="name"></span>
</b:ControlLabel>
<b:Controls ui:field="controls">
<g:FlowPanel width="95%">
<g:SimplePanel ui:field="elementPanel" styleName="{style.element-panel}"
width="95%">
<g:HTMLPanel width="95%">
<table style="width:100%; table-layout:fixed; cellspacing:2;"><!-- you might want to use CSS instead of cellspacing -->
<colgroup>
<col style="width:95%;" />
<col style="width:5%;" />
</colgroup>
<tr>
<td>
<g:FlowPanel styleName="{style.flex-display-panel}">
<g:FlowPanel ui:field="elementPanel" width="95%">
<!-- Listbox, Checkbox, Textbox, Calendar etc -->
</g:SimplePanel>
<g:FlowPanel ui:field="noteFieldContainer" styleName="{style.note-container}">
</g:FlowPanel>
<g:FlowPanel ui:field="eraseFieldContainer"
width="5%">
<b:Button ui:field="eraseButton"
title="Reset this field" type="LINK"></b:Button>
</g:FlowPanel>
</g:FlowPanel>
</td>
<td style="vertical-align: top;">
<g:FlowPanel styleName="{style.button-container}">
<g:FlowPanel ui:field="noteFieldContainer">
<b:Popover ui:field="noteFieldPopover" html="true"
animation="true" placement="LEFT">
<g:FocusPanel ui:field="focusPanelIconContainer">
<b:Icon type="INFO_SIGN" size="TWO_TIMES" ui:field="infoIcon" />
<b:Icon type="INFO_SIGN" size="TWO_TIMES"
ui:field="infoIcon" />
</g:FocusPanel>
</b:Popover>
</g:FlowPanel>
</g:FlowPanel>
</td>
</tr>
</table>
</g:HTMLPanel>
</b:Controls>
</b:ControlGroup>
</g:HTMLPanel>

View File

@ -17,6 +17,8 @@ import com.google.gwt.user.client.ui.Widget;
/**
* Widget for handling date-like fields.
* @author Costantino Perciante at ISTI-CNR (costantino.perciante@isti.cnr.it)
*
* @author updated by Francesco Mangiacrapa at ISTI-CNR
*/
public class DataTimeBox extends Composite{
@ -83,23 +85,35 @@ public class DataTimeBox extends Composite{
public void setStartDate(String date, String time){
GWT.log("Date is " + date + " and time is " + time);
if(date!=null && !date.isEmpty()) {
startRangeDate.setValue(new Date(date));
}else {
startRangeDate.setValue(null);
}
if(time != null && !time.isEmpty()){
Date completeDate = new Date();
completeDate.setHours(Integer.parseInt(time.split(COLON)[0]));
completeDate.setMinutes(Integer.parseInt(time.split(COLON)[1]));
startRangeTime.setValue(completeDate);
}else {
startRangeTime.setValue(null);
}
}
public void setEndDate(String date, String time){
GWT.log("Date is " + date + " and time is " + time);
if(date!=null && !date.isEmpty()) {
endRangeDate.setValue(new Date(date));
}else {
endRangeDate.setValue(null);
}
if(time != null && !time.isEmpty()){
Date completeDate = new Date();
completeDate.setHours(Integer.parseInt(time.split(COLON)[0]));
completeDate.setMinutes(Integer.parseInt(time.split(COLON)[1]));
endRangeTime.setValue(completeDate);
}else {
endRangeTime.setValue(null);
}
}

View File

@ -1,29 +1,34 @@
<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui="urn:ui:com.google.gwt.uibinder"
xmlns:g="urn:import:com.google.gwt.user.client.ui" xmlns:b2="urn:import:com.github.gwtbootstrap.datetimepicker.client.ui"
xmlns:g="urn:import:com.google.gwt.user.client.ui"
xmlns:b2="urn:import:com.github.gwtbootstrap.datetimepicker.client.ui"
xmlns:b3="urn:import:com.github.gwtbootstrap.datepicker.client.ui">
<ui:style>
.flow-panel-style {
display: inline-block;
}
.margin-left-5 {
margin-left: 5px;
}
</ui:style>
<g:HTMLPanel width="100%">
<g:FlowPanel width="100%">
<g:FlowPanel width="100%" ui:field="singleDataStart" styleName="{style.flow-panel-style}"
visible="true">
<g:FlowPanel width="100%" ui:field="singleDataStart"
styleName="{style.flow-panel-style}" visible="true">
<b3:DateBox format="yyyy-mm-dd" autoClose="true"
language="en" ui:field="startRangeDate" width="70%" />
<b2:DateTimeBox format="hh:ii" autoClose="true"
maxView="HOUR" startView="HOUR" language="en"
width="20%" ui:field="startRangeTime" />
maxView="HOUR" startView="HOUR" language="en" width="25%"
ui:field="startRangeTime" addStyleNames="{style.margin-left-5}" />
</g:FlowPanel>
<g:FlowPanel width="100%" ui:field="singleDataEnd" visible="false"
styleName="{style.flow-panel-style}">
<b3:DateBox format="yyyy-mm-dd" autoClose="true" width="70%"
language="en" ui:field="endRangeDate" />
<g:FlowPanel width="100%" ui:field="singleDataEnd"
visible="false" styleName="{style.flow-panel-style}">
<b3:DateBox format="yyyy-mm-dd" autoClose="true"
width="70%" language="en" ui:field="endRangeDate" />
<b2:DateTimeBox format="hh:ii" autoClose="true"
maxView="HOUR" startView="HOUR" language="en"
width="20%" ui:field="endRangeTime" />
maxView="HOUR" startView="HOUR" language="en" width="25%"
ui:field="endRangeTime" addStyleNames="{style.margin-left-5}" />
</g:FlowPanel>
</g:FlowPanel>
</g:HTMLPanel>

View File

@ -24,7 +24,6 @@ import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.VerticalPanel;
// TODO: Auto-generated Javadoc
/**
* The Class DialogUploadStream.
*
@ -59,8 +58,6 @@ public class DialogUpload extends FormPanel implements HasWorskpaceUploadNotific
/** The vertical main panel. */
protected VerticalPanel verticalMainPanel;
// private MonitorPanel monitorPanel;
// protected String clientUploadKey;
/** The purged uploading file name. */
private String purgedUploadingFileName;
@ -73,7 +70,6 @@ public class DialogUpload extends FormPanel implements HasWorskpaceUploadNotific
*/
public DialogUpload() {
fileUpload = new FileUpload();
// fileUpload.getElement().setAttribute("multiple", "multiple");
setAction(ConstantsMPFormBuilder.METADATA_FORM_BUILDER_UPLOADING_SERVLET);
setEncoding(FormPanel.ENCODING_MULTIPART);
setMethod(FormPanel.METHOD_POST);
@ -98,7 +94,6 @@ public class DialogUpload extends FormPanel implements HasWorskpaceUploadNotific
verticalMainPanel.add(fileUpload);
HorizontalPanel hp = new HorizontalPanel();
// hp.getElement().setId("hpID");
hp.getElement().getStyle().setWidth(100, Unit.PCT);
hp.getElement().getStyle().setMarginTop(5, Unit.PX);
hp.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
@ -145,7 +140,6 @@ public class DialogUpload extends FormPanel implements HasWorskpaceUploadNotific
*/
public void bindEvents() {
this.addHandlers();
// this.addListeners();
}
/**
@ -165,8 +159,6 @@ public class DialogUpload extends FormPanel implements HasWorskpaceUploadNotific
if (result == null) {
removeLoading();
Window.alert("An error occurred during file upload");
// new DialogResult(null, "Error during upload", "An error occurred during file
// upload.").center();
return;
}
String strippedResult = new HTML(result).getText();
@ -276,6 +268,27 @@ public class DialogUpload extends FormPanel implements HasWorskpaceUploadNotific
fakeUploaders.clear();
}
public void eraseLastUpload() {
try {
if (upv != null) {
verticalMainPanel.remove(upv.getPanel());
}
} catch (Exception e) {
}
if (timer != null) {
FileUploadingState upload = timer.getLastWorkspaceUploader();
if (upload != null)
timer.resetLastWorkspaceUploader();
}
fakeUploaders.clear();
fileUpload.getElement().setNodeValue("");
fileUpload.getElement().setPropertyObject("value", "");
}
/**
* Gets the file uploading state.
*
@ -355,7 +368,6 @@ public class DialogUpload extends FormPanel implements HasWorskpaceUploadNotific
* @param itemId the item id
*/
protected void updateItemSubmitForm(String itemId) {
// hiddenOverwrite.setValue("true");
submitForm();
}

View File

@ -157,5 +157,9 @@ public class TimerUpload extends Timer{
return lastWorkspaceUploader;
}
protected void resetLastWorkspaceUploader() {
lastWorkspaceUploader = null;
}
}

View File

@ -19,12 +19,12 @@ public class UploadedFileHttpSessionListener implements HttpSessionListener {
@Override
public void sessionDestroyed(HttpSessionEvent event) {
LOG.info("sessionDestroyed called");
LOG.trace("sessionDestroyed called");
try {
HttpSession httpSession = event.getSession();
if(httpSession!=null) {
LOG.info("Sesson id is: "+httpSession.getId());
LOG.trace("Sesson id is: "+httpSession.getId());
List<FileUploaded> listFileUploaded = (List<FileUploaded>) httpSession.getAttribute(ConstantsMPFormBuilder.FILE_UPLOADED_SESSION_ATTR);
if(listFileUploaded!=null) {
LOG.info("found file uploded in session, removing it");
@ -41,6 +41,6 @@ public class UploadedFileHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent arg0) {
LOG.info("sessionCreated called. Session id is: "+arg0.getSession().getId());
LOG.trace("sessionCreated called. Session id is: "+arg0.getSession().getId());
}
}

View File

@ -0,0 +1,6 @@
package org.gcube.portlets.widgets.mpformbuilder.shared.metadata;
public interface ErasableField {
public boolean isErasableField();
}

View File

@ -11,7 +11,7 @@ import java.util.List;
*
* Mar 3, 2022
*/
public class MetadataFieldWrapper implements UpdatableField, Serializable {
public class MetadataFieldWrapper implements UpdatableField, ErasableField, Serializable {
private static final long serialVersionUID = -8476731365884466698L;
private String fieldId;
@ -363,6 +363,17 @@ public class MetadataFieldWrapper implements UpdatableField, Serializable {
return null;
}
@Override
public boolean isErasableField() {
if(mandatory)
return false;
return true;
}
/**
* To string.
*