Controllers and Models for the authoring steps of Expertise

pull/1/head
Jens Pelzetter 2022-08-22 11:01:27 +02:00
parent 3bfe09d8c9
commit 9db50c895c
5 changed files with 881 additions and 5 deletions

View File

@ -1,8 +1,3 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.scientificcms.publications; package org.scientificcms.publications;
import org.hibernate.envers.Audited; import org.hibernate.envers.Audited;

View File

@ -0,0 +1,161 @@
package org.scientificcms.publications.ui.contenttypes;
import org.libreccm.security.AuthorizationRequired;
import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef;
import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
import org.scientificcms.publications.Expertise;
import org.scientificcms.publications.contenttypes.ExpertiseItem;
import org.scientificcms.publications.ui.SciPublicationsUiConstants;
import javax.enterprise.context.RequestScoped;
import javax.mvc.Controller;
import javax.transaction.Transactional;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Path(MvcAuthoringSteps.PATH_PREFIX + "expertise-extendedproeprties")
@Controller
@MvcAuthoringStepDef(
bundle = SciPublicationsUiConstants.BUNDLE,
descriptionKey = "authoringsteps.extendedproperties.description",
labelKey = "authoringsteps.extendedproperties.label",
supportedDocumentType = ExpertiseItem.class
)
public class ExpertiseExtendedPropertiesStep
extends AbstractPublicationExtendedPropertiesStep<ExpertiseItem, Expertise> {
@Override
public Class<ExpertiseExtendedPropertiesStep> getStepClass() {
return ExpertiseExtendedPropertiesStep.class;
}
@Override
protected Class<Expertise> getPublicationClass() {
return Expertise.class;
}
@Override
public String getEditStepUrlFragment() {
return "experise-extendedproperties";
}
@Override
protected String getStepTemplatePath() {
return "org/scientificcms/contenttypes/ui/expertise/edit-extended-properties.xhtml";
}
@GET
@Path("/")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String showStep(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath
) {
return super.showStep(sectionIdentifier, documentPath);
}
@POST
@Path("/properties")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String updateProperties(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@FormParam("languageOfPublication")
final String languageOfPublicationParam,
@FormParam("peerReviewed")
final String peerReviewedParam,
@FormParam("yearFirstPublished")
final String yearFirstPublishedParam
) {
return super.updateProperties(
sectionIdentifier,
documentPath,
languageOfPublicationParam,
peerReviewedParam,
yearFirstPublishedParam
);
}
@POST
@Path("/series")
@AuthorizationRequired
@Transactional
@Override
public String addSeries(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@FormParam("seriesIdentifier")
final String seriesIdentifier,
@FormParam("volumeOfSeries")
final String volumeOfSeries
) {
return super.addSeries(
sectionIdentifier,
documentPath,
seriesIdentifier,
volumeOfSeries
);
}
@POST
@Path("/series/{volumeInSeriesUuid}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String editVolumeInSeries(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@PathParam("volumeInSeriesUuid")
final String volumeInSeriesUuid,
@FormParam("volumeOfSeries")
final String volumeOfSeries
) {
return super.editVolumeInSeries(
sectionIdentifier,
documentPath,
volumeInSeriesUuid,
volumeOfSeries
);
}
@POST
@Path("/series/{volumeInSeriesUuid}/remove")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String removeVolumeInSeries(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@PathParam("volumeInSeriesUuid")
final String volumeInSeriesUuid
) {
return super.removeVolumeInSeries(
sectionIdentifier,
documentPath,
volumeInSeriesUuid
);
}
}

View File

@ -0,0 +1,55 @@
package org.scientificcms.publications.ui.contenttypes;
import org.libreccm.l10n.GlobalizationHelper;
import org.scientificcms.publications.Expertise;
import org.scientificcms.publications.contenttypes.ExpertiseItem;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemai l.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named("SciPublicationsExpertiseCreateStep")
public class ExpertiseItemCreateStep
extends AbstractPublicationItemCreateStep<ExpertiseItem, Expertise>{
@Inject
private GlobalizationHelper globalizationHelper;
@Override
public String getDocumentType() {
return ExpertiseItem.class.getName();
}
@Override
public String getDescription() {
return globalizationHelper
.getLocalizedTextsUtil(getBundle())
.getText("expertiseitem.createstep.description");
}
@Override
public String showCreateStep() {
return "org/scientificcms/contenttypes/ui/expertise/create-expertise.xhtml";
}
@Override
public Class<ExpertiseItem> getPublicationItemClass() {
return ExpertiseItem.class;
}
@Override
public Expertise createPublication() {
return new Expertise();
}
@Override
public String getEditStepName() {
return ExpertisePropertiesStep.EDIT_STEP_URL_FRAGMENT;
}
}

View File

@ -0,0 +1,601 @@
package org.scientificcms.publications.ui.contenttypes;
import org.libreccm.api.Identifier;
import org.libreccm.api.IdentifierParser;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.security.AuthorizationRequired;
import org.librecms.assets.Organization;
import org.librecms.contentsection.AssetRepository;
import org.librecms.ui.contentsections.ContentSectionNotFoundException;
import org.librecms.ui.contentsections.ItemPermissionChecker;
import org.librecms.ui.contentsections.documents.DocumentNotFoundException;
import org.librecms.ui.contentsections.documents.DocumentUi;
import org.librecms.ui.contentsections.documents.MvcAuthoringStepDef;
import org.librecms.ui.contentsections.documents.MvcAuthoringSteps;
import org.scientificcms.publications.Expertise;
import org.scientificcms.publications.PublicationRepository;
import org.scientificcms.publications.SciPublicationsConstants;
import org.scientificcms.publications.contenttypes.ExpertiseItem;
import org.scientificcms.publications.ui.SciPublicationsUiMessageBundle;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.mvc.Controller;
import javax.mvc.Models;
import javax.transaction.Transactional;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Path(
MvcAuthoringSteps.PATH_PREFIX
+ ExpertisePropertiesStep.EDIT_STEP_URL_FRAGMENT
)
@Controller
@MvcAuthoringStepDef(
bundle = SciPublicationsConstants.BUNDLE,
descriptionKey = "authoringsteps.basicproperties.description",
labelKey = "authoringsteps.basicproperties.label",
supportedDocumentType = ExpertiseItem.class
)
public class ExpertisePropertiesStep
extends AbstractPublicationPropertiesStep<ExpertiseItem, Expertise> {
public static final String EDIT_STEP_URL_FRAGMENT
= "expertise-basicproperties";
@Inject
private AssetRepository assetRepo;
private DocumentUi documentUi;
@Inject
private ExpertisePropertiesStepModel propertiesStepModel;
@Inject
private GlobalizationHelper globalizationHelper;
@Inject
private IdentifierParser identifierParser;
@Inject
private ItemPermissionChecker itemPermissionChecker;
@Inject
private Models models;
@Inject
private PublicationRepository publicationRepo;
@Inject
private SciPublicationsUiMessageBundle messageBundle;
@Override
public Class<ExpertisePropertiesStep> getStepClass() {
return ExpertisePropertiesStep.class;
}
@Override
protected String getEditStepUrlFragment() {
return EDIT_STEP_URL_FRAGMENT;
}
@Override
protected String getStepTemplatePath() {
return "org/scientificcms/contenttypes/ui/expertise/edit-expertise.xhtml";
}
@Override
public Class<Expertise> getPublicationClass() {
return Expertise.class;
}
@Override
@Transactional(Transactional.TxType.REQUIRED)
protected void init() throws ContentSectionNotFoundException,
DocumentNotFoundException {
super.init();
propertiesStepModel.setNumberOfPages(
getPublication().getNumberOfPages()
);
propertiesStepModel.setOrderer(
Optional
.ofNullable(getPublication().getOrderer())
.map(Organization::getName)
.orElse(null)
);
propertiesStepModel.setOrganization(
Optional
.ofNullable(getPublication().getOrganization())
.map(Organization::getName)
.orElse(null)
);
propertiesStepModel.setPlace(getPublication().getPlace());
}
@GET
@Path("/")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String showStep(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath
) {
return super.showStep(sectionIdentifier, documentPath);
}
@POST
@Path("/name")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String updateName(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@FormParam("name") @DefaultValue("")
final String name
) {
return super.updateName(sectionIdentifier, documentPath, name);
}
@POST
@Path("/title/@add")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String addTitle(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@FormParam("locale") final String localeParam,
@FormParam("value") final String value
) {
return super.addTitle(
sectionIdentifier,
documentPath,
localeParam,
value
);
}
@POST
@Path("/title/@edit/{locale}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String editTitle(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@PathParam("locale") final String localeParam,
@FormParam("value") final String value
) {
return super.editTitle(
sectionIdentifier,
documentPath,
localeParam,
value
);
}
@POST
@Path("/title/@remove/{locale}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String removeTitle(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@PathParam("locale") final String localeParam
) {
return super.removeTitle(sectionIdentifier, documentPath, localeParam);
}
@POST
@Path("/shortdescription/@add")
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String addShortDescription(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@FormParam("locale") final String localeParam,
@FormParam("value") final String value
) {
return super.addShortDescription(
sectionIdentifier,
documentPath,
localeParam,
value
);
}
@POST
@Path("/shortdescription/@edit/{locale}")
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String editShortDescription(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@PathParam("locale") final String localeParam,
@FormParam("value") final String value
) {
return super.editShortDescription(
sectionIdentifier,
documentPath,
localeParam,
value
);
}
@POST
@Path("/shortdescription/@remove/{locale}")
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String removeShortDescription(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@PathParam("locale") final String localeParam
) {
return super.removeShortDescription(
sectionIdentifier,
documentPath,
localeParam
);
}
@POST
@Path("/authors")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String addAuthor(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@FormParam("authorIdentifier")
final String authorIdentifier,
@FormParam("editor")
final String editorParam
) {
return super.addAuthor(
sectionIdentifier,
documentPath,
authorIdentifier,
editorParam
);
}
@POST
@Path("/authors/{authorshipUuid}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String editAuthorship(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@PathParam("authorshipUuid")
final String authorshipUuid,
@FormParam("editor")
final String editorParam
) {
return super.editAuthorship(
sectionIdentifier,
documentPath,
authorshipUuid,
editorParam
);
}
@POST
@Path("/authors/{authorshipUuid}/remove")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String removeAuthorship(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@PathParam("authorshipUuid")
final String authorshipUuid
) {
return super.removeAuthorship(
sectionIdentifier,
documentPath,
authorshipUuid
);
}
@POST
@Path("/orderer")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String setOrderer(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@FormParam("ordererIdentifier")
final String ordererIdentifier
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) {
return ex.showErrorMessage();
}
if (itemPermissionChecker.canEditItem(getDocument())) {
final Identifier identifier = identifierParser.parseIdentifier(
ordererIdentifier
);
final Optional<Organization> ordererResult;
switch (identifier.getType()) {
case ID:
ordererResult = assetRepo.findById(
Long.parseLong(identifier.getIdentifier()),
Organization.class
);
break;
case UUID:
ordererResult = assetRepo.findByUuidAndType(
identifier.getIdentifier(),
Organization.class
);
break;
default:
ordererResult = Optional.empty();
break;
}
if (ordererResult.isEmpty()) {
return showOrdererNotFound(
sectionIdentifier,
documentPath,
ordererIdentifier
);
}
final Organization orderer = ordererResult.get();
getPublication().setOrderer(orderer);
publicationRepo.save(getPublication());
return buildRedirectPathForStep();
} else {
return documentUi.showAccessDenied(
getContentSection(),
getDocument(),
getLabel()
);
}
}
@POST
@Path("/orderer/remove")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String removeOrderer(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) {
return ex.showErrorMessage();
}
if (itemPermissionChecker.canEditItem(getDocument())) {
getPublication().setOrderer(null);
publicationRepo.save(getPublication());
return buildRedirectPathForStep();
} else {
return documentUi.showAccessDenied(
getContentSection(),
getDocument(),
getLabel()
);
}
}
@POST
@Path("/organization")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String setOrganization(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@FormParam("organizationIdentifier")
final String organizationIdentifier
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) {
return ex.showErrorMessage();
}
if (itemPermissionChecker.canEditItem(getDocument())) {
final Identifier identifier = identifierParser.parseIdentifier(
organizationIdentifier
);
final Optional<Organization> organizationResult;
switch (identifier.getType()) {
case ID:
organizationResult = assetRepo.findById(
Long.parseLong(identifier.getIdentifier()),
Organization.class
);
break;
case UUID:
organizationResult = assetRepo.findByUuidAndType(
identifier.getIdentifier(),
Organization.class
);
break;
default:
organizationResult = Optional.empty();
break;
}
if (organizationResult.isEmpty()) {
return showOrganizationNotFound(
sectionIdentifier,
documentPath,
organizationIdentifier
);
}
final Organization organization = organizationResult.get();
getPublication().setOrganization(organization);
publicationRepo.save(getPublication());
return buildRedirectPathForStep();
} else {
return documentUi.showAccessDenied(
getContentSection(),
getDocument(),
getLabel()
);
}
}
@POST
@Path("/organization/remove")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String removeOrganization(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) {
return ex.showErrorMessage();
}
if (itemPermissionChecker.canEditItem(getDocument())) {
getPublication().setOrganization(null);
publicationRepo.save(getPublication());
return buildRedirectPathForStep();
} else {
return documentUi.showAccessDenied(
getContentSection(),
getDocument(),
getLabel()
);
}
}
@POST()
@Path("/properties")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String updateProperties(
@PathParam(MvcAuthoringSteps.SECTION_IDENTIFIER_PATH_PARAM)
final String sectionIdentifier,
@PathParam(MvcAuthoringSteps.DOCUMENT_PATH_PATH_PARAM_NAME)
final String documentPath,
@FormParam("yearOfPublication")
final String yearOfPublicationParam,
@FormParam("numberOfPages")
final String numberOfPagesParam,
@FormParam("place")
final String place
) {
try {
init();
} catch (ContentSectionNotFoundException ex) {
return ex.showErrorMessage();
} catch (DocumentNotFoundException ex) {
return ex.showErrorMessage();
}
if (itemPermissionChecker.canEditItem(getDocument())) {
updateProperties(
sectionIdentifier,
documentPath,
yearOfPublicationParam
);
if (numberOfPagesParam.matches("\\d*")) {
getPublication().setNumberOfPages(
Integer.parseInt(numberOfPagesParam)
);
}
getPublication().setPlace(place);
publicationRepo.save(getPublication());
return buildRedirectPathForStep();
} else {
return documentUi.showAccessDenied(
getContentSection(),
getDocument(),
messageBundle.getMessage("publication.edit.denied")
);
}
}
private String showOrdererNotFound(
final String sectionIdentifier,
final String documentPath,
final String ordererIdentifier
) {
models.put("ordererNotFound", ordererIdentifier);
return showStep(sectionIdentifier, documentPath);
}
private String showOrganizationNotFound(
final String sectionIdentifier,
final String documentPath,
final String organizationIdentifier
) {
models.put("organizationNotFound", organizationIdentifier);
return showStep(sectionIdentifier, documentPath);
}
}

View File

@ -0,0 +1,64 @@
package org.scientificcms.publications.ui.contenttypes;
import org.librecms.assets.Organization;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named("SciCmsExpertisePropertiesStepModel")
public class ExpertisePropertiesStepModel {
private String place;
private Integer numberOfPages;
private String organization;
private String orderer;
public String getPlace() {
return place;
}
public void setPlace(final String place) {
this.place = place;
}
public Integer getNumberOfPages() {
return numberOfPages;
}
public void setNumberOfPages(final Integer numberOfPages) {
this.numberOfPages = numberOfPages;
}
public String getOrganization() {
return organization;
}
public void setOrganization(final String organization) {
this.organization = organization;
}
public String getOrderer() {
return orderer;
}
public void setOrderer(final String orderer) {
this.orderer = orderer;
}
public String getOrganizationType() {
return Organization.class.getName();
}
public String getOrdererType() {
return Organization.class.getName();
}
}