/******************************************************************************* * Copyright (c) 2015 IBM Corp. * * 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 com.ibm.ws.repository.strategies.writeable; import java.util.ArrayList; import java.util.List; import com.ibm.ws.repository.common.enums.State; import com.ibm.ws.repository.exceptions.RepositoryBackendException; import com.ibm.ws.repository.exceptions.RepositoryBadDataException; import com.ibm.ws.repository.exceptions.RepositoryResourceCreationException; import com.ibm.ws.repository.exceptions.RepositoryResourceException; import com.ibm.ws.repository.exceptions.RepositoryResourceUpdateException; import com.ibm.ws.repository.exceptions.RepositoryResourceValidationException; import com.ibm.ws.repository.resources.internal.RepositoryResourceImpl; import com.ibm.ws.repository.resources.internal.RepositoryResourceImpl.AttachmentResourceImpl; /** * This strategy will overwrite an existing resource if it finds a matching one. This strategy uses the default mechanism * for setting the state of the overwritten resource, which is: If there is a matching resource and a * desiredStateIfMatchingFound state has been set then use it. If a desiredStateIfMatchingFound has not been set (its * null) then use the matching resource's state */ public class UpdateInPlaceStrategy extends BaseStrategy { private boolean _forceReplace; private List<RepositoryResourceImpl> _matchingResources = null; /** * Delegate so super class for states */ public UpdateInPlaceStrategy() {} /** * Sets the desired state of the asset after uploading it * * @param desiredStateIfMatchingFound Set the resource to this state if a matching resource was found. If this * is set to null then it will set the state to whatever state the matching resource is set to. * @param desiredStateIfNoMatchingFound If no matching resource is found then set the state to this value * @param forceReplace Set to true if you wish to perform a replace even if a matching resource was found. */ public UpdateInPlaceStrategy(State desiredStateIfMatchingFound, State desiredStateIfNoMatchingFound, boolean forceReplace) { super(desiredStateIfMatchingFound, desiredStateIfNoMatchingFound); _forceReplace = forceReplace; } /** * Sets the desired state of the asset after uploading it * * @param desiredStateIfMatchingFound Set the resource to this state if a matching resource was found. If this * is set to null then it will set the state to whatever state the matching resource is set to. * @param desiredStateIfNoMatchingFound If no matching resource is found then set the state to this value * @param forceReplace Set to true if you wish to perform a replace even if a matching resource was found. * @param matchingResource Set this if you wish to specify the resource to be replaced rather than letting * the resource try and find a matching. This is of use in scenarios where there may be more than one matching * resource and the caller can decide which one to use, as the resource logic will select the first matching one * it finds */ public UpdateInPlaceStrategy(State desiredStateIfMatchingFound, State desiredStateIfNoMatchingFound, boolean forceReplace, RepositoryResourceImpl matchingResource) { super(desiredStateIfMatchingFound, desiredStateIfNoMatchingFound); _forceReplace = forceReplace; if (matchingResource != null) { _matchingResources = new ArrayList<RepositoryResourceImpl>(); _matchingResources.add(matchingResource); } } @Override public List<RepositoryResourceImpl> findMatchingResources(RepositoryResourceImpl resource) throws RepositoryResourceValidationException, RepositoryBackendException, RepositoryBadDataException { if (_matchingResources != null) { return _matchingResources; } else { return resource.findMatchingResource(); } } /** * {@inheritDoc} * * @throws RepositoryResourceException * @throws RepositoryBackendException */ @Override public void uploadAsset(RepositoryResourceImpl resource, List<RepositoryResourceImpl> matchingResources) throws RepositoryBackendException, RepositoryResourceException { RepositoryResourceImpl firstMatch = (matchingResources == null || matchingResources.isEmpty()) ? null : matchingResources.get(0); State targetState = calculateTargetState(firstMatch); // We need to unpublish in order to overwrite if (firstMatch != null && firstMatch.getState() == State.PUBLISHED) { firstMatch.unpublish(); } // Is this an update or an add? switch (resource.updateRequired(firstMatch)) { case ADD: resource.addAsset(); break; case NOTHING: if (!_forceReplace) { // Use the asset from massive, although it's identical as far as we are concerned it // also has the fields massive sets onto an asset when it gets uploaded, including // the id itself. resource.copyAsset(firstMatch); break; } // If force replace is true then drop through to the update logic. case UPDATE: // Partial updates don't work so copy our data into the one // we found in massive and then set our asset to point to that // merged asset resource.overWriteAssetData(firstMatch, true); resource.updateAsset(); break; } // Now iterate over the attachments for (AttachmentResourceImpl attachment : resource.getAttachmentImpls()) { uploadAttachment(resource, attachment, firstMatch); } // Read back from massive to get the fields massive generated into our resource resource.refreshFromMassive(); resource.moveToState(targetState); } /** * Goes through each attachment and adds/updates the attachment as needed. * * @throws RepositoryResourceException * @throws RepositoryBackendException * @throws RepositoryResourceUpdateException * @throws RepositoryBadDataException * @throws RepositoryResourceCreationException */ public void uploadAttachment(RepositoryResourceImpl resource, AttachmentResourceImpl attachment, RepositoryResourceImpl matchingResource) throws RepositoryResourceCreationException, RepositoryBadDataException, RepositoryResourceUpdateException, RepositoryBackendException, RepositoryResourceException { switch (attachment.updateRequired(matchingResource)) { case ADD: resource.addAttachment(attachment); break; case UPDATE: resource.updateAttachment(attachment); break; case NOTHING: // Nothing to do but have to include this to stop findbugs crying break; } } }