All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.liferay.adaptive.media.image.internal.configuration.AMImageConfigurationHelperImpl Maven / Gradle / Ivy

/**
 * SPDX-FileCopyrightText: (c) 2000 Liferay, Inc. https://liferay.com
 * SPDX-License-Identifier: LGPL-2.1-or-later OR LicenseRef-Liferay-DXP-EULA-2.0.0-2023-06
 */

package com.liferay.adaptive.media.image.internal.configuration;

import com.liferay.adaptive.media.exception.AMImageConfigurationException;
import com.liferay.adaptive.media.exception.AMImageConfigurationException.InvalidStateAMImageConfigurationException;
import com.liferay.adaptive.media.exception.AMRuntimeException;
import com.liferay.adaptive.media.image.configuration.AMImageConfigurationEntry;
import com.liferay.adaptive.media.image.configuration.AMImageConfigurationHelper;
import com.liferay.adaptive.media.image.constants.AMImageDestinationNames;
import com.liferay.adaptive.media.image.service.AMImageEntryLocalService;
import com.liferay.portal.kernel.cache.MultiVMPool;
import com.liferay.portal.kernel.cache.PortalCache;
import com.liferay.portal.kernel.cache.PortalCacheHelperUtil;
import com.liferay.portal.kernel.messaging.Destination;
import com.liferay.portal.kernel.messaging.DestinationConfiguration;
import com.liferay.portal.kernel.messaging.DestinationFactory;
import com.liferay.portal.kernel.messaging.Message;
import com.liferay.portal.kernel.messaging.MessageBus;
import com.liferay.portal.kernel.settings.CompanyServiceSettingsLocator;
import com.liferay.portal.kernel.settings.ModifiableSettings;
import com.liferay.portal.kernel.settings.PortletPreferencesSettings;
import com.liferay.portal.kernel.settings.Settings;
import com.liferay.portal.kernel.settings.SettingsException;
import com.liferay.portal.kernel.settings.SettingsFactoryUtil;
import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
import com.liferay.portal.kernel.util.Validator;

import java.io.IOException;
import java.io.Serializable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.portlet.PortletPreferences;
import javax.portlet.ValidatorException;

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;

/**
 * @author Adolfo Pérez
 */
@Component(immediate = true, service = AMImageConfigurationHelper.class)
public class AMImageConfigurationHelperImpl
	implements AMImageConfigurationHelper {

	@Override
	public AMImageConfigurationEntry addAMImageConfigurationEntry(
			long companyId, String name, String description, String uuid,
			Map properties)
		throws AMImageConfigurationException, IOException {

		_checkName(name);
		_checkProperties(properties);

		_normalizeProperties(properties);

		String normalizedUuid = FriendlyURLNormalizerUtil.normalize(uuid);

		_checkUuid(normalizedUuid);

		Collection amImageConfigurationEntries =
			getAMImageConfigurationEntries(
				companyId, amImageConfigurationEntry -> true);

		_checkDuplicatesName(amImageConfigurationEntries, name);

		_checkDuplicatesUuid(amImageConfigurationEntries, normalizedUuid);

		List updatedAMImageConfigurationEntries =
			new ArrayList<>(amImageConfigurationEntries);

		updatedAMImageConfigurationEntries.removeIf(
			amImageConfigurationEntry -> normalizedUuid.equals(
				amImageConfigurationEntry.getUUID()));

		AMImageConfigurationEntry amImageConfigurationEntry =
			new AMImageConfigurationEntryImpl(
				name, description, normalizedUuid, properties, true);

		updatedAMImageConfigurationEntries.add(amImageConfigurationEntry);

		_updateConfiguration(companyId, updatedAMImageConfigurationEntries);

		_triggerConfigurationEvent(amImageConfigurationEntry);

		return amImageConfigurationEntry;
	}

	@Override
	public void deleteAMImageConfigurationEntry(long companyId, String uuid)
		throws InvalidStateAMImageConfigurationException, IOException {

		Optional amImageConfigurationEntryOptional =
			getAMImageConfigurationEntry(companyId, uuid);

		if (!amImageConfigurationEntryOptional.isPresent()) {
			return;
		}

		AMImageConfigurationEntry amImageConfigurationEntry =
			amImageConfigurationEntryOptional.get();

		if (amImageConfigurationEntry.isEnabled()) {
			throw new InvalidStateAMImageConfigurationException();
		}

		forceDeleteAMImageConfigurationEntry(companyId, uuid);
	}

	@Override
	public void disableAMImageConfigurationEntry(long companyId, String uuid)
		throws IOException {

		Optional amImageConfigurationEntryOptional =
			getAMImageConfigurationEntry(companyId, uuid);

		if (!amImageConfigurationEntryOptional.isPresent()) {
			return;
		}

		AMImageConfigurationEntry amImageConfigurationEntry =
			amImageConfigurationEntryOptional.get();

		if (!amImageConfigurationEntry.isEnabled()) {
			return;
		}

		Collection amImageConfigurationEntries =
			getAMImageConfigurationEntries(
				companyId, curConfigurationEntry -> true);

		List updatedAMImageConfigurationEntries =
			new ArrayList<>(amImageConfigurationEntries);

		updatedAMImageConfigurationEntries.removeIf(
			curConfigurationEntry -> uuid.equals(
				curConfigurationEntry.getUUID()));

		AMImageConfigurationEntry newAMImageConfigurationEntry =
			new AMImageConfigurationEntryImpl(
				amImageConfigurationEntry.getName(),
				amImageConfigurationEntry.getDescription(),
				amImageConfigurationEntry.getUUID(),
				amImageConfigurationEntry.getProperties(), false);

		updatedAMImageConfigurationEntries.add(newAMImageConfigurationEntry);

		_updateConfiguration(companyId, updatedAMImageConfigurationEntries);

		_triggerConfigurationEvent(amImageConfigurationEntry);
	}

	@Override
	public void enableAMImageConfigurationEntry(long companyId, String uuid)
		throws IOException {

		Optional amImageConfigurationEntryOptional =
			getAMImageConfigurationEntry(companyId, uuid);

		if (!amImageConfigurationEntryOptional.isPresent()) {
			return;
		}

		AMImageConfigurationEntry amImageConfigurationEntry =
			amImageConfigurationEntryOptional.get();

		if (amImageConfigurationEntry.isEnabled()) {
			return;
		}

		Collection amImageConfigurationEntries =
			getAMImageConfigurationEntries(
				companyId, curConfigurationEntry -> true);

		List updatedAMImageConfigurationEntries =
			new ArrayList<>(amImageConfigurationEntries);

		updatedAMImageConfigurationEntries.removeIf(
			curConfigurationEntry -> uuid.equals(
				curConfigurationEntry.getUUID()));

		AMImageConfigurationEntry newAMImageConfigurationEntry =
			new AMImageConfigurationEntryImpl(
				amImageConfigurationEntry.getName(),
				amImageConfigurationEntry.getDescription(),
				amImageConfigurationEntry.getUUID(),
				amImageConfigurationEntry.getProperties(), true);

		updatedAMImageConfigurationEntries.add(newAMImageConfigurationEntry);

		_updateConfiguration(companyId, updatedAMImageConfigurationEntries);

		_triggerConfigurationEvent(amImageConfigurationEntry);
	}

	@Override
	public void forceDeleteAMImageConfigurationEntry(
			long companyId, String uuid)
		throws IOException {

		Optional amImageConfigurationEntryOptional =
			getAMImageConfigurationEntry(companyId, uuid);

		if (!amImageConfigurationEntryOptional.isPresent()) {
			return;
		}

		AMImageConfigurationEntry amImageConfigurationEntry =
			amImageConfigurationEntryOptional.get();

		_amImageEntryLocalService.deleteAMImageEntries(
			companyId, amImageConfigurationEntry);

		Collection amImageConfigurationEntries =
			getAMImageConfigurationEntries(
				companyId, curConfigurationEntry -> true);

		List updatedAMImageConfigurationEntries =
			new ArrayList<>(amImageConfigurationEntries);

		updatedAMImageConfigurationEntries.removeIf(
			curConfigurationEntry -> uuid.equals(
				curConfigurationEntry.getUUID()));

		_updateConfiguration(companyId, updatedAMImageConfigurationEntries);

		_triggerConfigurationEvent(amImageConfigurationEntry);
	}

	@Override
	public Collection getAMImageConfigurationEntries(
		long companyId) {

		Stream amImageConfigurationEntryStream =
			_getAMImageConfigurationEntries(companyId);

		return amImageConfigurationEntryStream.filter(
			AMImageConfigurationEntry::isEnabled
		).sorted(
			Comparator.comparing(AMImageConfigurationEntry::getName)
		).collect(
			Collectors.toList()
		);
	}

	@Override
	public Collection getAMImageConfigurationEntries(
		long companyId,
		Predicate predicate) {

		Stream amImageConfigurationEntryStream =
			_getAMImageConfigurationEntries(companyId);

		return amImageConfigurationEntryStream.filter(
			predicate
		).sorted(
			Comparator.comparing(AMImageConfigurationEntry::getName)
		).collect(
			Collectors.toList()
		);
	}

	@Override
	public Optional getAMImageConfigurationEntry(
		long companyId, String configurationEntryUUID) {

		Stream amImageConfigurationEntryStream =
			_getAMImageConfigurationEntries(companyId);

		return amImageConfigurationEntryStream.filter(
			amImageConfigurationEntry -> configurationEntryUUID.equals(
				amImageConfigurationEntry.getUUID())
		).findFirst();
	}

	@Override
	public AMImageConfigurationEntry updateAMImageConfigurationEntry(
			long companyId, String oldUuid, String name, String description,
			String newUuid, Map properties)
		throws AMImageConfigurationException, IOException {

		_checkName(name);
		_checkProperties(properties);

		_normalizeProperties(properties);

		String normalizedUuid = FriendlyURLNormalizerUtil.normalize(newUuid);

		_checkUuid(normalizedUuid);

		Collection amImageConfigurationEntries =
			getAMImageConfigurationEntries(
				companyId, amImageConfigurationEntry -> true);

		Stream amImageConfigurationEntryStream =
			amImageConfigurationEntries.stream();

		Optional
			oldAMImageConfigurationEntryOptional =
				amImageConfigurationEntryStream.filter(
					amImageConfigurationEntry -> oldUuid.equals(
						amImageConfigurationEntry.getUUID())
				).findFirst();

		AMImageConfigurationEntry oldAMImageConfigurationEntry =
			oldAMImageConfigurationEntryOptional.orElseThrow(
				() ->
					new AMImageConfigurationException.
						NoSuchAMImageConfigurationException(
							"{uuid=" + oldUuid + "}"));

		if (!name.equals(oldAMImageConfigurationEntry.getName())) {
			_checkDuplicatesName(amImageConfigurationEntries, name);
		}

		if (!oldUuid.equals(normalizedUuid)) {
			_checkDuplicatesUuid(amImageConfigurationEntries, normalizedUuid);
		}

		List updatedAMImageConfigurationEntries =
			new ArrayList<>(amImageConfigurationEntries);

		updatedAMImageConfigurationEntries.removeIf(
			amImageConfigurationEntry -> oldUuid.equals(
				amImageConfigurationEntry.getUUID()));

		AMImageConfigurationEntry amImageConfigurationEntry =
			new AMImageConfigurationEntryImpl(
				name, description, normalizedUuid, properties,
				oldAMImageConfigurationEntry.isEnabled());

		updatedAMImageConfigurationEntries.add(amImageConfigurationEntry);

		_updateConfiguration(companyId, updatedAMImageConfigurationEntries);

		_triggerConfigurationEvent(
			new AMImageConfigurationEntry[] {
				oldAMImageConfigurationEntry, amImageConfigurationEntry
			});

		return amImageConfigurationEntry;
	}

	@Activate
	protected void activate() {
		DestinationConfiguration destinationConfiguration =
			new DestinationConfiguration(
				DestinationConfiguration.DESTINATION_TYPE_SYNCHRONOUS,
				AMImageDestinationNames.ADAPTIVE_MEDIA_IMAGE_CONFIGURATION);

		Destination destination = _destinationFactory.createDestination(
			destinationConfiguration);

		_messageBus.addDestination(destination);

		_portalCache =
			(PortalCache)_multiVMPool.getPortalCache(
				AMImageConfigurationHelperImpl.class.getName());
	}

	@Deactivate
	protected void deactivate() {
		_messageBus.removeDestination(
			AMImageDestinationNames.ADAPTIVE_MEDIA_IMAGE_CONFIGURATION);

		_multiVMPool.removePortalCache(
			AMImageConfigurationHelperImpl.class.getName());
	}

	@Reference(unbind = "-")
	protected void setAMImageConfigurationEntryParser(
		AMImageConfigurationEntryParser amImageConfigurationEntryParser) {

		_amImageConfigurationEntryParser = amImageConfigurationEntryParser;
	}

	private static final boolean _isPositiveNumber(String s) {
		Matcher matcher = _positiveNumberPattern.matcher(s);

		return matcher.matches();
	}

	private void _checkDuplicatesName(
			Collection amImageConfigurationEntries,
			String name)
		throws AMImageConfigurationException {

		Stream amImageConfigurationEntryStream =
			amImageConfigurationEntries.stream();

		Optional
			duplicateNameAMImageConfigurationEntryOptional =
				amImageConfigurationEntryStream.filter(
					amImageConfigurationEntry -> name.equals(
						amImageConfigurationEntry.getName())
				).findFirst();

		if (duplicateNameAMImageConfigurationEntryOptional.isPresent()) {
			throw new AMImageConfigurationException.
				DuplicateAMImageConfigurationNameException();
		}
	}

	private void _checkDuplicatesUuid(
			Collection amImageConfigurationEntries,
			String uuid)
		throws AMImageConfigurationException {

		Stream amImageConfigurationEntryStream =
			amImageConfigurationEntries.stream();

		Optional
			duplicateUuidAMImageConfigurationEntryOptional =
				amImageConfigurationEntryStream.filter(
					amImageConfigurationEntry -> uuid.equals(
						amImageConfigurationEntry.getUUID())
				).findFirst();

		if (duplicateUuidAMImageConfigurationEntryOptional.isPresent()) {
			throw new AMImageConfigurationException.
				DuplicateAMImageConfigurationUuidException();
		}
	}

	private void _checkName(String name) throws AMImageConfigurationException {
		if (Validator.isNull(name)) {
			throw new AMImageConfigurationException.InvalidNameException();
		}
	}

	private void _checkProperties(Map properties)
		throws AMImageConfigurationException {

		String maxHeightString = properties.get("max-height");

		if (Validator.isNotNull(maxHeightString) &&
			!maxHeightString.equals("0") &&
			!_isPositiveNumber(maxHeightString)) {

			throw new AMImageConfigurationException.InvalidHeightException();
		}

		String maxWidthString = properties.get("max-width");

		if (Validator.isNotNull(maxWidthString) &&
			!maxWidthString.equals("0") && !_isPositiveNumber(maxWidthString)) {

			throw new AMImageConfigurationException.InvalidWidthException();
		}

		if ((Validator.isNull(maxHeightString) ||
			 maxHeightString.equals("0")) &&
			(Validator.isNull(maxWidthString) || maxWidthString.equals("0"))) {

			throw new AMImageConfigurationException.
				RequiredWidthOrHeightException();
		}
	}

	private void _checkUuid(String uuid) throws AMImageConfigurationException {
		if (Validator.isNull(uuid)) {
			throw new AMImageConfigurationException.InvalidUuidException();
		}
	}

	private Stream _getAMImageConfigurationEntries(
		long companyId) {

		ArrayList amImageConfigurationEntries =
			(ArrayList)_portalCache.get(companyId);

		if (amImageConfigurationEntries != null) {
			return amImageConfigurationEntries.stream();
		}

		try {
			Settings settings = SettingsFactoryUtil.getSettings(
				new CompanyServiceSettingsLocator(
					companyId, AMImageCompanyConfiguration.class.getName()));

			Optional nullableImageVariants =
				_getNullableImageVariants(settings);

			String[] imageVariants = nullableImageVariants.orElseGet(
				() -> settings.getValues("imageVariants", new String[0]));

			amImageConfigurationEntries = Stream.of(
				imageVariants
			).map(
				_amImageConfigurationEntryParser::parse
			).collect(
				Collectors.toCollection(ArrayList::new)
			);

			PortalCacheHelperUtil.putWithoutReplicator(
				_portalCache, companyId, amImageConfigurationEntries);

			return amImageConfigurationEntries.stream();
		}
		catch (SettingsException se) {
			throw new AMRuntimeException.InvalidConfiguration(se);
		}
	}

	private Optional _getNullableImageVariants(Settings settings) {
		PortletPreferencesSettings portletPreferencesSettings =
			(PortletPreferencesSettings)settings;

		PortletPreferences portletPreferences =
			portletPreferencesSettings.getPortletPreferences();

		Map map = portletPreferences.getMap();

		return Optional.ofNullable(map.get("imageVariants"));
	}

	private void _normalizeProperties(Map properties) {
		String maxHeightString = properties.get("max-height");
		String maxWidthString = properties.get("max-width");

		if (Validator.isNotNull(maxHeightString) &&
			Validator.isNotNull(maxWidthString)) {

			return;
		}

		if (Validator.isNull(maxHeightString)) {
			properties.put("max-height", "0");
		}

		if (Validator.isNull(maxWidthString)) {
			properties.put("max-width", "0");
		}
	}

	private void _triggerConfigurationEvent(Object payload) {
		Message message = new Message();

		message.setPayload(payload);

		_messageBus.sendMessage(
			AMImageDestinationNames.ADAPTIVE_MEDIA_IMAGE_CONFIGURATION,
			message);
	}

	private void _updateConfiguration(
			long companyId,
			List amImageConfigurationEntries)
		throws IOException {

		try {
			Settings settings = SettingsFactoryUtil.getSettings(
				new CompanyServiceSettingsLocator(
					companyId, AMImageCompanyConfiguration.class.getName()));

			ModifiableSettings modifiableSettings =
				settings.getModifiableSettings();

			Stream amImageConfigurationEntryStream =
				amImageConfigurationEntries.stream();

			List imageVariants = amImageConfigurationEntryStream.map(
				_amImageConfigurationEntryParser::getConfigurationString
			).collect(
				Collectors.toList()
			);

			modifiableSettings.setValues(
				"imageVariants", imageVariants.toArray(new String[0]));

			modifiableSettings.store();

			amImageConfigurationEntryStream =
				amImageConfigurationEntries.stream();

			_portalCache.put(
				companyId,
				amImageConfigurationEntryStream.collect(
					Collectors.toCollection(ArrayList::new)));
		}
		catch (SettingsException | ValidatorException e) {
			throw new AMRuntimeException.InvalidConfiguration(e);
		}
	}

	private static final Pattern _positiveNumberPattern = Pattern.compile(
		"\\d*[1-9]\\d*");

	private AMImageConfigurationEntryParser _amImageConfigurationEntryParser;

	@Reference
	private AMImageEntryLocalService _amImageEntryLocalService;

	@Reference
	private DestinationFactory _destinationFactory;

	@Reference
	private MessageBus _messageBus;

	@Reference
	private MultiVMPool _multiVMPool;

	private PortalCache _portalCache;

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy