/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the License at the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apereo.portal.portlets.portletadmin;
import java.util.Date;
import org.apache.commons.lang.StringUtils;
import org.apereo.portal.dao.usertype.FunctionalNameType;
import org.apereo.portal.portlet.registry.IPortletDefinitionRegistry;
import org.apereo.portal.portletpublishing.xml.Parameter;
import org.apereo.portal.portletpublishing.xml.PortletPublishingDefinition;
import org.apereo.portal.portletpublishing.xml.Step;
import org.apereo.portal.portlets.portletadmin.xmlsupport.IChannelPublishingDefinitionDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.binding.validation.ValidationContext;
import org.springframework.stereotype.Service;
@Service("portletValidator")
public class PortletDefinitionFormValidator {
private IChannelPublishingDefinitionDao channelPublishingDefinitionDao;
private IPortletDefinitionRegistry portletDefinitionRegistry;
@Autowired(required = true)
public void setChannelPublishingDefinitionDao(
IChannelPublishingDefinitionDao channelPublishingDefinitionDao) {
this.channelPublishingDefinitionDao = channelPublishingDefinitionDao;
}
@Autowired(required = true)
public void setPortletDefinitionRegistry(IPortletDefinitionRegistry portletDefinitionRegistry) {
this.portletDefinitionRegistry = portletDefinitionRegistry;
}
public void validateChooseType(PortletDefinitionForm def, MessageContext context) {
final int selectedTypeId = def.getTypeId();
switch (selectedTypeId) {
case 0:
// No type selected...
context.addMessage(
new MessageBuilder()
.error()
.source("typeId")
.code("please.choose.portlet.type")
.build());
break;
default:
// User specified a typeId; validate that it exists
final PortletPublishingDefinition cpd =
channelPublishingDefinitionDao.getChannelPublishingDefinition(
selectedTypeId);
if (cpd == null) {
context.addMessage(
new MessageBuilder()
.error()
.source("typeId")
.code("please.choose.portlet.type")
.build());
}
break;
}
}
public void validatePortletConfig(PortletDefinitionForm def, ValidationContext context) {
validateChooseType(def, context.getMessageContext());
doBasicInfo(def, context.getMessageContext());
doPublishingParameters(def, context.getMessageContext());
doLifecycle(def, context.getMessageContext());
}
/*
* Private Methods (break validation work into smaller parts)
*/
private void doBasicInfo(PortletDefinitionForm def, MessageContext context) {
// fname
if (StringUtils.isEmpty(def.getFname())) {
context.addMessage(
new MessageBuilder()
.error()
.source("fName")
.code("please.enter.fname")
.build());
} else if (!FunctionalNameType.isValid(def.getFname())) {
context.addMessage(
new MessageBuilder().error().source("fName").code("fname.invalid").build());
} else if (def.getId() == null
&& portletDefinitionRegistry.getPortletDefinitionByFname(def.getFname()) != null) {
// This is a new portlet and the fname is already taken
context.addMessage(
new MessageBuilder().error().source("fName").code("fname.in.use").build());
}
// Title
if (StringUtils.isEmpty(def.getTitle())) {
context.addMessage(
new MessageBuilder()
.error()
.source("title")
.code("please.enter.title")
.build());
}
// Name
if (StringUtils.isEmpty(def.getName())) {
context.addMessage(
new MessageBuilder().error().source("name").code("please.enter.name").build());
}
if (def.getId() == null
&& portletDefinitionRegistry.getPortletDefinitionByName(def.getName()) != null) {
// This is a new portlet and the name is already taken
context.addMessage(
new MessageBuilder().error().source("name").code("name.in.use").build());
}
}
private void doPublishingParameters(PortletDefinitionForm def, MessageContext context) {
PortletPublishingDefinition cpd =
channelPublishingDefinitionDao.getChannelPublishingDefinition(def.getTypeId());
for (Step step : cpd.getSteps()) {
if (step.getParameters() != null) {
for (Parameter param : step.getParameters()) {
// if the user has entered a value for this parameter,
// check it against the CPD
if (def.getParameters().containsKey(param.getName())
&& !StringUtils.isEmpty(
def.getParameters().get(param.getName()).getValue())) {
/*
* NOTE: Looks like this method used to provide
* validation logic for publishing parameters, but no
* longer does. TODO: Look into re-implementing it
* based on the updated model.
*
* Further Reading:
* - https://issues.jasig.org/browse/UP-2973
* - https://github.com/Jasig/uPortal/commit/a21bdb181b7e03aabd926d96f3cea66dcdf2d979#diff-41ca747cf5d1a6b00f0ab31ee88d49d7L111
*/
}
}
}
}
}
private void doLifecycle(PortletDefinitionForm def, MessageContext context) {
if (def.getLifecycleState() == null) {
context.addMessage(
new MessageBuilder()
.error()
.source("lifecycle")
.code("please.select.lifecycle.stage")
.build());
}
Date now = new Date();
if (def.getPublishDate() != null) {
if (def.getPublishDateTime().before(now)) {
context.addMessage(
new MessageBuilder()
.error()
.source("publishDate")
.code("auto.publish.date.must.be.future")
.build());
}
}
if (def.getExpirationDate() != null) {
if (def.getExpirationDateTime().before(now)) {
context.addMessage(
new MessageBuilder()
.error()
.source("expirationDate")
.code("auto.expire.date.must.be.future")
.build());
}
}
if (def.getPublishDate() != null && def.getExpirationDate() != null) {
if (def.getExpirationDateTime().before(def.getPublishDateTime())) {
context.addMessage(
new MessageBuilder()
.error()
.source("expirationDate")
.code("auto.expire.date.must.be.after.publish")
.build());
}
}
}
}