/*
* Copyright (c) 2010 Lockheed Martin Corporation
*
* Licensed 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.eurekastreams.server.action.validation.start;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import org.eurekastreams.commons.actions.ValidationStrategy;
import org.eurekastreams.commons.actions.context.PrincipalActionContext;
import org.eurekastreams.commons.exceptions.ValidationException;
import org.eurekastreams.server.action.request.start.ReorderGadgetRequest;
import org.eurekastreams.server.domain.Gadget;
import org.eurekastreams.server.domain.Layout;
import org.eurekastreams.server.domain.Tab;
import org.eurekastreams.server.domain.TabTemplate;
import org.eurekastreams.server.persistence.TabMapper;
/**
* This class handles validation for the Reorder Gadget Execution. This ensures that the inputs are valid and will
* result in a consistent Tab/Gadget data model.
*
*/
public class ReorderGadgetValidation implements ValidationStrategy<PrincipalActionContext>
{
/**
* Local instance of the {@link TabMapper}.
*/
private final TabMapper tabMapper;
/**
* Constructor.
*
* @param inTabMapper
* - instance of the {@link TabMapper} to lookup tabs from the inputs.
*/
public ReorderGadgetValidation(final TabMapper inTabMapper)
{
tabMapper = inTabMapper;
}
/**
* {@inheritDoc}.
*
* This method ensures that the following conditions are met:
* - The target zone is in the range of what the layout allows.
* - The provided tab exists and is valid. - The source template where the gadget can be found exists.
* - The target zone index is consistent with the gadgets that are already in place.
*/
@Override
public void validate(final PrincipalActionContext inActionContext) throws ValidationException
{
ValidationException vex = new ValidationException();
ReorderGadgetRequest request = (ReorderGadgetRequest) inActionContext.getParams();
Long targetTabId = request.getCurrentTabId();
Long gadgetId = request.getGadgetId();
Integer targetZoneNumber = request.getTargetZoneNumber();
Integer targetZoneIndex = request.getTargetZoneIndex();
TabTemplate sourceTemplate = tabMapper.findByGadgetId(gadgetId);
Tab destinationTab = tabMapper.findById(targetTabId);
// Ensure that the destination tab exists.
if (destinationTab == null)
{
vex.addError("invalidTab", "Destination zone does not exist.");
throw vex;
}
TabTemplate destinationTemplate = destinationTab.getTemplate();
Layout destinationLayout = destinationTemplate.getTabLayout();
// Save the Source and Destination TabTemplate to state so they can be reused in execution.
inActionContext.getState().put("destinationTemplate", destinationTemplate);
inActionContext.getState().put("sourceTemplate", sourceTemplate);
// Destination zone is within the valid number of destination zones.
if (targetZoneNumber + 1 > destinationLayout.getNumberOfZones())
{
vex.addError("invalidZone", "ReorderGadgetAction told to move a gadget to a nonexistent zone.");
throw vex;
}
// Ensure that the gadget to be moved exists.
if (sourceTemplate == null)
{
vex.addError("invalidGadget", "Gadget to be moved is invalid.");
throw vex;
}
// Create a map of the zonenumbers and a list of the corresponding zone indexes.
HashMap<Integer, List<Integer>> gadgetZoneIndexes = new HashMap<Integer, List<Integer>>();
for (Gadget currentGadget : destinationTemplate.getGadgets())
{
if (gadgetZoneIndexes.containsKey(currentGadget.getZoneNumber()))
{
gadgetZoneIndexes.get(currentGadget.getZoneNumber()).add(currentGadget.getZoneIndex());
}
else
{
ArrayList<Integer> currentZoneIndexes = new ArrayList<Integer>();
currentZoneIndexes.add(currentGadget.getZoneIndex());
gadgetZoneIndexes.put(currentGadget.getZoneNumber(), currentZoneIndexes);
}
}
//Test the zone boundaries only if the target zone contains gadgets.
if (gadgetZoneIndexes.containsKey(targetZoneNumber))
{
List<Integer> targetZoneIndexes = gadgetZoneIndexes.get(targetZoneNumber);
Collections.sort(targetZoneIndexes);
// Test the targetzoneindex to be sure it is within the range of the indexes in the target zone.
// Test that the target zone index is not greater than the last position in the list of indexes
// or less than the first position in the list of indexes.
if (targetZoneIndex > targetZoneIndexes.get(targetZoneIndexes.size() - 1) + 1
|| targetZoneIndex < targetZoneIndexes.get(0) - 1)
{
vex.addError("invalidZoneIndex",
"Destination zone index is outside of the acceptable bounds for the target zone index.");
throw vex;
}
}
//If the target zone number does not have any gadgets in it, then the index should always be 0.
else if (targetZoneIndex != 0)
{
vex.addError("invalidZoneIndex",
"Destination zone index should be zero when moving to an empty zone.");
}
}
}