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

com.day.cq.wcm.foundation.model.responsivegrid.ResponsiveColumn Maven / Gradle / Ivy

There is a newer version: 6.5.21
Show newest version
/*************************************************************************
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2017 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 **************************************************************************/
package com.day.cq.wcm.foundation.model.responsivegrid;

import com.adobe.cq.export.json.ComponentExporter;
import com.day.cq.wcm.api.NameConstants;
import com.day.cq.wcm.api.designer.ComponentStyle;
import com.day.cq.wcm.commons.WCMUtils;
import com.day.cq.wcm.foundation.model.responsivegrid.export.ResponsiveColumnExporter;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.resource.AbstractResource;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.models.factory.ModelFactory;
import org.osgi.annotation.versioning.ProviderType;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Represents a column of a responsive grid.
 * A responsive grid's column is basically a virtual wrapper of a component that is part of the grid.
 */
@ProviderType
@JsonSerialize(as = ResponsiveColumnExporter.class)
public class ResponsiveColumn extends AbstractResource implements ResponsiveColumnExporter {

    private Resource wrappedResource;

    private ComponentExporter componentModel;

    private String classNames;

    private ResponsiveConfiguration responsiveConfiguration;

    private Set columnOnlyBreakpointNames;
    private Map breakpoints;
    private Map gridBreakpoints;
    private SlingHttpServletRequest slingRequest;
    private ModelFactory modelFactory;

    public ResponsiveColumn(Resource resource,
                            Map gridBreakpoints,
                            String classNamePrefix) {
        this.wrappedResource = resource;

        Map breakpoints = getBreakpoints(this.wrappedResource, gridBreakpoints);
        this.classNames = createClassNames(
                this.wrappedResource,
                classNamePrefix + ResponsiveConstants.DEFAULT_COLUMN_CSS_PREFIX,
                breakpoints,
                gridBreakpoints);
        this.gridBreakpoints = gridBreakpoints;
        this.responsiveConfiguration = new ResponsiveConfiguration(breakpoints);
    }

    public ResponsiveColumn(Resource resource,
                                Map gridBreakpoints,
                                String classNamePrefix,
                                SlingHttpServletRequest slingRequest,
                                ModelFactory modelFactory) {
        this.slingRequest = slingRequest;
        this.modelFactory = modelFactory;
        this.wrappedResource = resource;
        Map breakpoints = getBreakpoints(this.wrappedResource, gridBreakpoints);
        this.classNames = createClassNames(
                this.wrappedResource,
                classNamePrefix + ResponsiveConstants.DEFAULT_COLUMN_CSS_PREFIX,
                breakpoints,
                gridBreakpoints);
        this.gridBreakpoints = gridBreakpoints;
        this.responsiveConfiguration = new ResponsiveConfiguration(breakpoints);
    }

    @Override
    public Map getBreakpoints() {
        return responsiveConfiguration != null ? responsiveConfiguration.getBreakpoints(): null;
    }

    @Override
    public String getColumnClassNames() {
        return this.classNames;
    }

    /**
     *
     * @deprecated Use {@link #getColumnClassNames()}
     */
    public String getCssClass() {
        return this.classNames;
    }

    /**
     *
     * @deprecated Use {@link #getBreakpoints()}
     */
    public Set getMissingBreakpointNames() {
        if (columnOnlyBreakpointNames == null) {
            columnOnlyBreakpointNames = new HashSet();
            if (gridBreakpoints != null && !gridBreakpoints.isEmpty()) {
                // Extract the breakpoints that the parent grid is missing
                List missingBreakpointNames = new ArrayList(breakpoints.keySet());
                missingBreakpointNames.removeAll(gridBreakpoints.keySet());
                columnOnlyBreakpointNames.addAll(missingBreakpointNames);
            } else {
                // The parent doesn't have the current column breakpoints
                columnOnlyBreakpointNames.addAll(breakpoints.keySet());
            }
        }
        return columnOnlyBreakpointNames;
    }

    /**
     * Returns the number of columns for the given breakpoint name
     * @param breakpointName The name of the breakpoint
     * @return The number of columns for given breakpoint name.
     * @deprecated
     */
    public Integer getColumnCount(String breakpointName) {
        return breakpoints.get(breakpointName).getWidth();
    }

    @Nonnull
    @Override
    public ComponentExporter getExportedComponent() {
        if (componentModel == null) {
            componentModel = modelFactory.getModelFromWrappedRequest(slingRequest, wrappedResource, ComponentExporter.class);
        }
        return componentModel;
    }

    @Override
    @Nonnull
    public String getExportedType() {
        return wrappedResource.getResourceType();
    }

    /**
     *
     * @return The wrapped {@link Resource} associated with the column.
     */
    @Nonnull
    public Resource getResource() { return wrappedResource; }

    /**
     *
     * @return The path of the wrapped {@link Resource} associated with the column.
     */
    @Nonnull
    public String getPath() { return wrappedResource.getPath(); }

    /**
     *
     * @deprecated
     */
    @Nonnull
    public String getResourceType() {
        return wrappedResource.getResourceType();
    }

    /**
     *
     * @deprecated
     */
    public String getResourceSuperType() {
        return wrappedResource.getResourceSuperType();
    }

    /**
     *
     * @deprecated
     */
    @Nonnull
    public ResourceMetadata getResourceMetadata() {
        return wrappedResource.getResourceMetadata();
    }

    /**
     *
     * @deprecated
     */
    @Nonnull
    public ResourceResolver getResourceResolver() {
        return wrappedResource.getResourceResolver();
    }

    /**
     *
     * @deprecated
     */
    public ValueMap getProperties() {
        return wrappedResource.adaptTo(ValueMap.class);
    }

    /**
     * Generates the class names to be applied to the column
     */
    private String createClassNames(Resource resource,
                                    String columnCssClassPrefix,
                                    Map columnBreakpoints,
                                    Map referenceBreakpoints) {
        StringBuilder cssClass = new StringBuilder(columnCssClassPrefix);

        com.day.cq.wcm.api.components.Component component = WCMUtils.getComponent(resource);
        ValueMap componentProperties = null;

        if (component != null) {
            componentProperties = component.getProperties();
        }

        for (Breakpoint breakpoint : columnBreakpoints.values()) {
            String breakpointName = breakpoint.getName();
            int offset = breakpoint.getOffset();
            int width = breakpoint.getWidth();
            Breakpoint.ResponsiveBehavior behavior = breakpoint.getResponsiveBehavior();

            if (breakpoint.getWidth() > 0) {
                cssClass.append(" ").append(columnCssClassPrefix).append("--").append(breakpointName).append("--").append(width);
            }

            cssClass.append(" ").append(columnCssClassPrefix).append("--").append(ResponsiveConstants.OFFSET_CSS_VARIANT_NAME).append("--")
                    .append(breakpointName).append("--").append(offset);

            cssClass.append(" ").append(columnCssClassPrefix).append("--").append(breakpointName).append("--").append(behavior);
        }

        // Consolidate the local breakpoints of the column
        // with the ones that only exist on the parent Grid
        if (referenceBreakpoints != null && !referenceBreakpoints.isEmpty()) {
            // Missing breakpoints originating from the parent
            List missingGridBreakpointNames = new ArrayList(referenceBreakpoints.keySet());
            missingGridBreakpointNames.removeAll(columnBreakpoints.keySet());

            for (String missingGridBreakpointName: missingGridBreakpointNames) {
                // Get the default width
                int width = 0;
                int offset = 0;
                int gridWidth = 0;

                // Default breakpoint
                Breakpoint breakPointVariant = columnBreakpoints
                        .get(ResponsiveConstants.BREAKPOINT_VARIANT_NAME_DEFAULT);

                if (breakPointVariant != null) {
                    width = breakPointVariant.getWidth();
                    offset = breakPointVariant.getOffset();
                }

                // Breakpoint provided by the parent
                Breakpoint gridBreakPointVariant = referenceBreakpoints.get(missingGridBreakpointName);

                if (gridBreakPointVariant != null) {
                    gridWidth = gridBreakPointVariant.getWidth();
                }

                // If all the width offset
                if (width == 0 || width + offset > gridWidth) {
                    // Get the parent corresponding width
                    width = gridWidth;
                    offset = 0;
                }

                if (width == 0 || width > ResponsiveConstants.DEFAULT_COLUMNS) {
                    width = ResponsiveConstants.DEFAULT_COLUMNS;
                }

                cssClass.append(" ").append(columnCssClassPrefix).append("--").append(missingGridBreakpointName).append("--").append(width);

                if (offset > 0) {
                    cssClass.append(" ").append(columnCssClassPrefix).append("--").append(ResponsiveConstants.OFFSET_CSS_VARIANT_NAME)
                            .append("--").append(missingGridBreakpointName).append("--").append(width);
                }

                columnBreakpoints.put(
                        ResponsiveConstants.BREAKPOINT_VARIANT_NAME_DEFAULT,
                        new Breakpoint(
                                ResponsiveConstants.BREAKPOINT_VARIANT_NAME_DEFAULT,
                                width,
                                offset,
                                gridBreakPointVariant.getResponsiveBehavior()));
            }
        }

        if (!columnBreakpoints.keySet().contains(ResponsiveConstants.BREAKPOINT_VARIANT_NAME_DEFAULT)) {
            cssClass.append(" ").append(columnCssClassPrefix).append("--").append(ResponsiveConstants.BREAKPOINT_VARIANT_NAME_DEFAULT)
                    .append("--").append(ResponsiveConstants.DEFAULT_COLUMNS);
        }

        if (componentProperties != null) {
            cssClass.append(" ").append(componentProperties.get(ComponentStyle.PN_CSS_CLASS, ""));
        }

        return cssClass.toString().trim();
    }

    /**
     *
     * @param resource The current resource
     * @param referenceBreakpoints The reference breakpoints (breakpoints of the grid parent)
     * @return Returns a map of processed breakpoints. If necessary, the breakpoints of the current resource are adjusted with the ones of the given reference (often the grid parent).
     */
    private Map getBreakpoints(Resource resource, Map referenceBreakpoints) {
        if (resource == null) {
            return null;
        }

        Resource responsiveCfg = resource.getChild(NameConstants.NN_RESPONSIVE_CONFIG);
        breakpoints = new HashMap();

        if (responsiveCfg != null) {
            // Add the respective class names for each of the breakpoints
            for (Iterator resCfgIt = responsiveCfg.listChildren(); resCfgIt.hasNext(); ) {
                Resource resCfg = resCfgIt.next();
                String breakpointName = resCfg.getName();
                ValueMap cfg = resCfg.getValueMap();
                int width = cfg.get("width", ResponsiveConstants.DEFAULT_COLUMNS);
                int offset = cfg.get("offset", 0);
                Breakpoint.ResponsiveBehavior behavior =
                        Breakpoint.ResponsiveBehavior.valueOf(
                                cfg.get("behavior",
                                        Breakpoint.ResponsiveBehavior.none.toString()));

                // Limit the width and offset to the grid width
                Breakpoint gridBreakpoint =
                        referenceBreakpoints != null ? referenceBreakpoints.get(breakpointName) : null;

                if (gridBreakpoint != null && width + offset > gridBreakpoint.getWidth()) {
                    if (width > gridBreakpoint.getWidth()) {
                        // The width is bigger than the parent
                        // We take the full size
                        width = gridBreakpoint.getWidth();
                        offset = 0;
                    } else if (offset < gridBreakpoint.getWidth()) {
                        // There is room for the offset and a width
                        width = gridBreakpoint.getWidth() - offset;
                    } else {
                        // There is no room for an offset
                        offset = 0;
                    }
                }

                breakpoints.put(breakpointName, new Breakpoint(breakpointName, width, offset, behavior));
            }
        }

        return breakpoints;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy