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

com.adobe.granite.crx2oak.pipeline.PipeData Maven / Gradle / Ivy

The newest version!
/*************************************************************************
 * ADOBE CONFIDENTIAL
 * ___________________
 *
 * Copyright 2016 Adobe
 * All Rights Reserved.
 *
 * NOTICE: All information contained herein is, and remains
 * the property of Adobe and its suppliers, if any. The intellectual
 * and technical concepts contained herein are proprietary to Adobe
 * and its suppliers and are protected by all applicable intellectual
 * property laws, including trade secret and copyright laws.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe.
 **************************************************************************/
package com.adobe.granite.crx2oak.pipeline;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static java.util.Objects.requireNonNull;

/**
 * Represents an abstract generic data passed through pipeline for each pipe.
 * The implementation assumes that you have any complex composition of objects
 * identifiable via keys like for maps. In this case it is called topic.
 * 

* Therefore pipe data consist of multiple topics. Each topic accepts one type/class * of information in which the concrete value might be passed. *

* It is dependent from concrete pipeline use what topics are passed there.

*/ public final class PipeData { /** * Empty pipe data without any topics defined. */ public static final PipeData EMPTY = new PipeData(Collections.emptyMap()); private Map map; @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final PipeData pipeData = (PipeData) o; return Objects.equals(map, pipeData.map); } @Override public int hashCode() { return Objects.hash(map); } /** * Use topics that exist in the provided pipe data to build a new pipe data using returned builder. * @param pipeData the pipe data that will be used as initial state of pipe data builder * @return the new instance of pipe data builder */ public static PipeDataBuilder use(final PipeData pipeData) { return new PipeDataBuilder(pipeData.map); } private PipeData(final Map map) { this.map = requireNonNull(map); } /** * Create a new builder instance of empty pipe data that allows you to add more data. * * @return a not null instance of builder */ public static PipeDataBuilder empty() { return new PipeDataBuilder(Collections.emptyMap()); } /** * Put the topic with the specified value into currently built pipe data. * * @param topic the topic that will be placed * @param value the value object of the topic * @param the type of the value that is inferred from topic * @return the instance of the pipe data builder */ public static PipeDataBuilder put(final Topic topic, @Nonnull final T value) { return empty().put(topic, value); } /** * Conditionally put the topic into currently built pipe data if the value is not null. * * @param topic the topic that will be optionally put * @param value the nullable value that will be put into built pipe data if it is not null * @param the the of the value derived from topic * @return the instance of this builder */ public static PipeDataBuilder putOptionally(final Topic topic, @Nullable final T value) { return empty().putOptionally(topic, value); } /** * Joins the specified topic from the input pipe data that represents list values with * new joiners values and stores them together as defined topic into the builder state. * If this topic already existed it will be overridden. * If some other topic were defined before this operation they will remain as it were before. * * @param input the input to apply * @param topic the topic to apply * @param newjoiners the new values that will be added to topic and joined for the current topic content * @return the instance of this builder * @param the type of elements that are stored in list * @param the type of the topic which needs to be a list of parameter V. */ @SuppressWarnings("unchecked") public static > PipeDataBuilder join(final PipeData input, final Topic topic, final V... newjoiners) { return empty().join(input, topic, newjoiners); } /** * Joins the specified topic from the input pipe data that represents list values with * new joiners values and stores them together as defined topic into the builder state. * If this topic already existed it will be overridden. * If some other topic were defined before this operation they will remain as it were before. * * @param input the input to apply * @param topic the topic to apply * @param newjoiners the new values that will be added to topic and joined for the current topic content * @return the instance of this builder * @param the type of elements that are stored in list * @param the type of the topic which needs to be a list of parameter V. */ @SuppressWarnings("unchecked") public static > PipeDataBuilder join(final PipeData input, final Topic topic, final List newjoiners) { return empty().join(input, topic, newjoiners); } /** * Joins the specified topic from 2 input pipe data objects that in both topic represents list values * stores them together as defined topic into the builder state. * If this topic already existed it will be overridden. * If some other topic were defined before this operation they will remain as it were before. * * @param input the input to apply * @param topic the topic to apply * @param inputToJoin the input from which new values of the specified topic that will be added to the same * topic and joined for the current topic state * @return the instance of this builder * @param the type of elements that are stored in list * @param the type of the topic which needs to be a list of parameter V. */ @SuppressWarnings("unchecked") public static > PipeDataBuilder join(final PipeData input, final Topic topic, final PipeData inputToJoin) { return empty().join(input, topic, inputToJoin); } /** * Get the specified optional topic from pipe data. * * @param topic the topic that holds identifier and type of value of that topic * @param the type of topic for which the value of T will be returned * @return the optional value of type defined by the topic */ @SuppressWarnings("unchecked") public Optional get(final Topic topic) { return Optional.fromNullable((T) map.get(topic.getName())); } /** * Require the specified topic to be present in pipe data. If it is the value is returned but * if not, the {@linkplain IllegalStateException} is immediately thrown. * * @param topic the topic that holds identifier and type of value of that topic * @param the type of topic for which the value of T will be returned * @return the value of type defined by the topic * @throws IllegalStateException if the topic is not available */ public T require(final Topic topic) { final Optional optionalValue = get(topic); if (optionalValue.isPresent()) { return optionalValue.get(); } else { throw new IllegalStateException(String.format("The value of %s is required", topic.getName())); } } @Override public String toString() { return "PipeData" + map; } /** * The topic of data passed though pipe. *

* An equivalent of key from a map but additionally defining the accepted type * of the value of such key - value entry a map can store. * * @param the class/type of value that this topic accepts for storage/retrieval */ public static final class Topic { private final String name; /** * Create a topic with the specified name that needs to be unique across all entries * in the pipe data. * * @param name any not null name */ public Topic(final String name) { this.name = requireNonNull(name); } /** * Get the name of the topic. * * @return the not null string */ public String getName() { return name; } @Override public String toString() { return "Topic{" + "name='" + name + '\'' + '}'; } } public static final class PipeDataBuilder { private Map map; private PipeDataBuilder(final Map pipeData) { map = new HashMap<>(pipeData); } /** * Put the topic with the specified value into currently built pipe data. * * @param topic the topic that will be placed * @param value the value object of the topic * @param the type of the value that is inferred from topic * @return the instance of this builder */ public PipeDataBuilder put(final Topic topic, @Nonnull final T value) { map.put(topic.getName(), requireNonNull(value)); return this; } /** * Drops the specified topic from currently built pipe data. * * @param topic the topic to drop * @return the instance of this builder */ public PipeDataBuilder drop(final Topic topic) { map.remove(topic.getName()); return this; } /** * Returns the current state of builder as immutable pipe data new instance. * * @return the always not null snapshot of builder state */ public PipeData toPipe() { return new PipeData(ImmutableMap.copyOf(map)); } /** * Applies all topics from the into the builder state. If some topics already existed * they will be overridden. If some topic were defined before this operation * and they aren't redefined by the input they will remain as it were before. * * @param input the input to apply * @return the instance of this builder */ public PipeDataBuilder apply(final PipeData input) { map.putAll(input.map); return this; } /** * Conditionally put the topic into currently built pipe data if the value is not null. * * @param topic the topic that will be optionally put * @param value the nullable value that will be put into built pipe data if it is not null * @param the the of the value derived from topic * @return the instance of this builder */ public PipeDataBuilder putOptionally(final Topic topic, @Nullable final T value) { if (value != null) put(topic, value); return this; } /** * Joins the specified topic from the input pipe data that represents list values with * new joiners values and stores them together as defined topic into the builder state. * If this topic already existed it will be overridden. * If some other topic were defined before this operation they will remain as it were before. * * @param input the input to apply * @param topic the topic to apply * @param newjoiners the new values that will be added to topic and joined for the current topic content * @return the instance of this builder * @param the type of elements that are stored in list * @param the type of the topic which needs to be a list of parameter V. */ @SuppressWarnings("unchecked") public > PipeDataBuilder join(final PipeData input, final Topic topic, final V... newjoiners) { join(input, topic, Arrays.asList(newjoiners)); return this; } /** * Joins the specified topic from 2 input pipe data objects that in both topic represents list values * stores them together as defined topic into the builder state. * If this topic already existed it will be overridden. * If some other topic were defined before this operation they will remain as it were before. * * @param input the input to apply * @param topic the topic to apply * @param inputToJoin the input from which new values of the specified topic that will be added to the same * topic and joined for the current topic state * @return the instance of this builder * @param the type of elements that are stored in list * @param the type of the topic which needs to be a list of parameter V. */ @SuppressWarnings("unchecked") public > PipeDataBuilder join(final PipeData input, final Topic topic, final PipeData inputToJoin) { final List existingValues = getTopicValueAsList(inputToJoin, (Topic>) topic); join(input, topic, existingValues); return this; } /** * Joins the specified topic from the input pipe data that represents list values with * new joiners values and stores them together as defined topic into the builder state. * If this topic already existed it will be overridden. * If some other topic were defined before this operation they will remain as it were before. * * @param input the input to apply * @param topic the topic to apply * @param newjoiners the new values that will be added to topic and joined for the current topic content * @return the instance of this builder * @param the type of elements that are stored in list * @param the type of the topic which needs to be a list of parameter V. */ @SuppressWarnings("unchecked") public > PipeDataBuilder join(final PipeData input, final Topic topic, final List newjoiners) { //noinspection unchecked final List existingValues = getTopicValueAsList(input, (Topic>) topic); final List newList = new ArrayList<>(existingValues); newList.addAll(newjoiners); //noinspection unchecked put((Topic>)topic, newList); return this; } private > List getTopicValueAsList(final PipeData input, final Topic> topic) { return input.get(topic).or(Collections.emptyList()); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy