text:
namespace CPF
{
	namespace Concurrency {
		class ThreadContext;
	}

	class ExperimentalD3D12;

	static constexpr GOM::ClassID kRenderSystemCID = GOM::ClassID("RenderSystemCID"_crc64);

	class RenderSystem : public tRefCounted<MultiCore::iSystem>
	{
	public:
		static constexpr GOM::InterfaceID kIID = GOM::InterfaceID("RenderSystem"_crc64);
		//
		static constexpr MultiCore::SystemID kID = Hash::Create<MultiCore::SystemID_tag>("Render System"_hashString);

		static constexpr MultiCore::StageID kBeginFrame = Hash::Create<MultiCore::StageID_tag>("Begin Frame"_hashString);
		static constexpr MultiCore::StageID kDrawInstances = Hash::Create<MultiCore::StageID_tag>("Draw Instances"_hashString);
		static constexpr MultiCore::StageID kDebugUI = Hash::Create<MultiCore::StageID_tag>("Debug UI"_hashString);
		static constexpr MultiCore::StageID kEndFrame = Hash::Create<MultiCore::StageID_tag>("End Frame"_hashString);

		// Construction/Destruction.
		RenderSystem(Plugin::iRegistry*, GOM::iUnknown*);
		virtual ~RenderSystem();

		// Registration.
		static GOM::Result Install(Plugin::iRegistry*);
		static GOM::Result Remove(Plugin::iRegistry*);

		struct Desc : iSystem::Desc
		{
			MultiCore::SystemID mTimerID;
			ExperimentalD3D12* mpApplication;
		};

		// iBase
		GOM::Result CPF_STDCALL QueryInterface(uint64_t id, void** outIface) override;

		// iSystem
		GOM::Result CPF_STDCALL Initialize(Plugin::iRegistry* rgy, const char* name, const iSystem::Desc* desc) override;
		MultiCore::SystemID CPF_STDCALL GetID() const override;
		GOM::Result CPF_STDCALL Configure(MultiCore::iExecutionPlan*) override { return GOM::kOK; }

		// iStageList
		GOM::Result CPF_STDCALL FindStage(MultiCore::StageID id, MultiCore::iStage** outStage) const override;
		GOM::Result CPF_STDCALL GetStages(int32_t* count, MultiCore::iStage** outStages) const override;
		GOM::Result CPF_STDCALL GetInstructions(int32_t*, MultiCore::Instruction*) override;
		void CPF_STDCALL AddDependency(MultiCore::BlockDependency dep) override;
		GOM::Result CPF_STDCALL GetDependencies(MultiCore::iExecutionPlan* owner, int32_t*, MultiCore::BlockDependency*) override;

		GOM::Result CPF_STDCALL AddStage(MultiCore::iStage*) override;
		GOM::Result CPF_STDCALL RemoveStage(MultiCore::StageID) override;

	private:
		//
		static void _BeginFrame(const Concurrency::WorkContext* tc, void* context);
		static void _Clear(const Concurrency::WorkContext* tc, void* context);
		static void _Draw(const Concurrency::WorkContext* tc, void* context);
		static void _DebugUI(const Concurrency::WorkContext* tc, void* context);
		static void _PreparePresent(const Concurrency::WorkContext* tc, void* context);
		static void _EndFrame(const Concurrency::WorkContext* tc, void* context);

		ExperimentalD3D12* mpApp;

		//////////////////////////////////////////////////////////////////////////
		static const int kBufferCount = 3;

		//////////////////////////////////////////////////////////////////////////
		IntrusivePtr<Graphics::iDevice> mpDevice;

		int mCurrentBackBuffer;
		IntrusivePtr<Graphics::iCommandPool> mpPreCommandPool[kBufferCount];
		IntrusivePtr<Graphics::iCommandBuffer> mpPreCommandBuffer[kBufferCount];
		IntrusivePtr<Graphics::iCommandPool> mpPostCommandPool[kBufferCount];
		IntrusivePtr<Graphics::iCommandBuffer> mpPostCommandBuffer[kBufferCount];

		MultiCore::SystemID mID;
		IntrusivePtr<iStageList> mpStages;
	};
}


text:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/main_content"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_scrollFlags="scroll|exitUntilCollapsed">
      <!--  <include layout="@layout/activity_toolbar"></include>-->
        <android.support.design.widget.TabLayout
            android:id="@+id/friends_tab"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="?attr/colorPrimary"
            app:tabIndicatorColor="@android:color/white"
            app:tabSelectedTextColor="@android:color/white"
            app:tabTextColor="@android:color/darker_gray" />
    </android.support.design.widget.AppBarLayout>
    <android.support.v4.view.ViewPager
        android:id="@+id/friends_viewpager"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="5dp"
        android:background="@android:color/white"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>

redpajama_set_name: RedPajamaGithub


text:
static_assert(__has_feature(objc_arc), "Djinni requires ARC to be enabled for this file");

@class DBTestDuration;

namespace djinni_generated {

class TestDuration
{
public:
    using CppType = std::shared_ptr<::testsuite::TestDuration>;
    using CppOptType = std::shared_ptr<::testsuite::TestDuration>;
    using ObjcType = DBTestDuration*;

    using Boxed = TestDuration;

    static CppType toCpp(ObjcType objc);
    static ObjcType fromCppOpt(const CppOptType& cpp);
    static ObjcType fromCpp(const CppType& cpp) { return fromCppOpt(cpp); }

private:
    class ObjcProxy;
};

}  // namespace djinni_generated


text:
.oo-ui-icon-beta {
	background-image: url("themes/mediawiki/images/icons/beta.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/beta.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/beta.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/beta.png");
}
.oo-ui-icon-betaLaunch {
	background-image: url("themes/mediawiki/images/icons/betaLaunch.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/betaLaunch.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/betaLaunch.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/betaLaunch.png");
}
.oo-ui-icon-bookmark {
	background-image: url("themes/mediawiki/images/icons/bookmark-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/bookmark-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/bookmark-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/bookmark-rtl.png");
}
.oo-ui-icon-browser {
	background-image: url("themes/mediawiki/images/icons/browser-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/browser-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/browser-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/browser-rtl.png");
}
.oo-ui-icon-clock {
	background-image: url("themes/mediawiki/images/icons/clock.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/clock.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/clock.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/clock.png");
}
.oo-ui-icon-closeInput {
	background-image: url("themes/mediawiki/images/icons/closeInput.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/closeInput.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/closeInput.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/closeInput.png");
}
.oo-ui-icon-funnel {
	background-image: url("themes/mediawiki/images/icons/funnel-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/funnel-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/funnel-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/funnel-rtl.png");
}
.oo-ui-icon-heart {
	background-image: url("themes/mediawiki/images/icons/heart.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/heart.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/heart.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/heart.png");
}
.oo-ui-icon-key {
	background-image: url("themes/mediawiki/images/icons/key-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/key-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/key-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/key-rtl.png");
}
.oo-ui-icon-keyboard {
	background-image: url("themes/mediawiki/images/icons/keyboard-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/keyboard-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/keyboard-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/keyboard-rtl.png");
}
.oo-ui-icon-logOut {
	background-image: url("themes/mediawiki/images/icons/logOut-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/logOut-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/logOut-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/logOut-rtl.png");
}
.oo-ui-icon-magnifyingGlass {
	background-image: url("themes/mediawiki/images/icons/magnifyingGlass-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/magnifyingGlass-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/magnifyingGlass-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/magnifyingGlass-rtl.png");
}
.oo-ui-icon-newWindow {
	background-image: url("themes/mediawiki/images/icons/newWindow-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/newWindow-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/newWindow-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/newWindow-rtl.png");
}
.oo-ui-icon-printer {
	background-image: url("themes/mediawiki/images/icons/printer-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/printer-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/printer-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/printer-rtl.png");
}
.oo-ui-icon-ribbonPrize {
	background-image: url("themes/mediawiki/images/icons/ribbonPrize.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/ribbonPrize.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/ribbonPrize.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/ribbonPrize.png");
}
.oo-ui-icon-sun {
	background-image: url("themes/mediawiki/images/icons/sun-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/sun-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/sun-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/sun-rtl.png");
}
.oo-ui-icon-watchlist {
	background-image: url("themes/mediawiki/images/icons/watchlist-rtl.png");
	background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/watchlist-rtl.svg");
	background-image:         linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/watchlist-rtl.svg");
	background-image:      -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/watchlist-rtl.png");
}


text:
import java.util.*;
import java.util.stream.*;

/**
 * On old cell phones, users typed on a numeric keypad and the phone would provide a list
 * of words that matched these numbers. Each digit mapped to a set of O - 4 letters.
 * Implement an algorithm to return a list of matching words, given a sequence of digits.
 * You are provided a set of valid words
 */
public class T9Trie {

    char [][] t9Letters = {null, null, {'a', 'b', 'c'}, {'d', 'e', 'f'}, {'g', 'h', 'i'}, {'j', 'k', 'l'}, {'m', 'n', 'o'}, {'p', 'q', 'r', 's'}, {'t', 'u', 'v'}, {'w', 'x', 'y', 'z'}};

    public static void main(String[] args) {
        assert (testTrie());

        Trie trie = new Trie(new String[]{"apple", "ball", "tree", "used"});
        T9Trie t9 = new T9Trie();

        assert(t9.getValidT9Words("8733", trie)
               .equals(Arrays.asList(new String[]{"tree", "used"})));
    }

    ArrayList<String> getValidT9Words(String number, Trie trie) {
        ArrayList<String> results = new ArrayList<>();
        getValidWords(number, 0, "", trie.getRoot(), results);
        return results;
    }

    void getValidWords(String number,
                       int idx,
                       String prefix,
                       TrieNode trieNode,
                       ArrayList<String> result) {

        if (number.length() == idx) {
            if (trieNode.terminates()) {
                result.add(prefix);
            }
            return;
        }

        // get number from current idx
        char digit = number.charAt(idx);
        char[] letters = getT9Chars(digit);
        for (char c : letters) {
            TrieNode childNode = trieNode.getChild(c);
            if (childNode != null) { // traverse deeper
                getValidWords(number, idx+1, prefix+c, childNode, result);
            }
        }
    }

    char[] getT9Chars(char digit) {
        if (!Character.isDigit(digit)) {
            return null;
        }

        int dig = Character.getNumericValue(digit) - Character.getNumericValue('0');
        return t9Letters[dig];
    }

    static boolean testTrie() {
        List<String> list = Arrays.asList("sheldon",
                                          "cooper",
                                          "dinesh",
                                          "gilfoyle");
        Trie trie = new Trie(list);
        return trie.contains("gil") && trie.contains("dinesh");
    }
}

class Trie {
    // The root of this trie.
    private TrieNode root;

    /*
     * Takes a list of strings as an argument, and constructs a trie that stores
     * these strings
     */
    public Trie(List<String> list) {
        root = new TrieNode();
        list.forEach(word -> root.addWord(word));
    }

    public Trie(String[] list) {
        root = new TrieNode();
        for (String word : list) {
            root.addWord(word);
        }
    }

    /*
     * Checks whether this trie contains a string with the prefix passed in as argument
     * 'exact' is a flag which tells if the prefix is the word i.e. exact match
     *
     */
    public boolean contains(String prefix, boolean exact) {
        TrieNode lastNode = root;
        for (int i = 0; i < prefix.length(); i++) {
            lastNode = lastNode.getChild(prefix.charAt(i));
            if (lastNode == null) {
                return false;
            }
        }

        return !exact || lastNode.terminates();
    }

    public boolean contains(String prefix) {
        return contains(prefix, false);
    }

    public TrieNode getRoot() {
        return root;
    }
}

class TrieNode {

    /* The children of the node in the trie. */
    private HashMap<Character, TrieNode> children;
    private boolean terminates = false;

    /* The character stored in this node as data as well */
    private char character;

    /* Constructs an empty trie node and initializes the list of
     * its children to empty hash map. Used only to construct the
     * root node of the trie. */
    public TrieNode() {
        children = new HashMap<Character, TrieNode>();
    }

    public TrieNode(char character) {
        this();
        this.character = character;
    }

    /* Returns the character data stored in this node. */
    public char getChar() {
        return character;
    }

    public void addWord(String word) {
        if (word == null || word.isEmpty()) {
            return;
        }

        char firstChar = word.charAt(0);

        TrieNode child = getChild(firstChar);
        if (child == null) {
            child = new TrieNode(firstChar);
            children.put(firstChar, child);
        }

        if (word.length() > 1) {
            child.addWord(word.substring(1));
        } else {
            child.setTerminates(true);
        }
    }

    /**
     * Find a child node of this node that has the char argument as its data.
     * Return null if no such child node is present in the trie.
     */
    public TrieNode getChild(char c) {
        return children.get(c);
    }

    public boolean terminates() {
        return terminates;
    }

    public void setTerminates(boolean t) {
        terminates = t;
    }

}


text:
;
;	walkie_talkie_get.m
;
;	Action code for the answer-or-pickup walkie-talkie operation.
;	This is the 'get' behavior for walkie_talkie objects.
;
;	This file should be assembled as position independent code.
;
;	Chip Morningstar
;	Lucasfilm Ltd.
;	6-May-1986
;
	include	"action_head.i"

; This is the parameter returned by the GET request
define GET_SUCCESS = 0

	actionStart

	lda in_hand_noid
	if (zero) {				; Hand must be empty
	    containerAbort
	    doMyAction ACTION_GO		; My GO walks to this object
	    waitWhile animation_wait_bit	; Wait till we get there

	    sendMsg pointed_noid, MSG_GET, 0

	    getResponse GET_SUCCESS
	    if (!zero) {			; Non-zero is success
	        lda pointed_noid
	    	jsr v_get_subject_object
	        changeContainers 0, AVATAR_HAND, actor_noid
		lda #PHONE_ACTIVE
		chainTo v_answer_or_unhook
	    }
	}
	chainTo	v_beep				; If we get here we failed
	actionEnd


text:
#ifndef ScrollAnimationSmooth_h
#define ScrollAnimationSmooth_h

#include "ScrollAnimation.h"

#if ENABLE(SMOOTH_SCROLLING)

#if !ENABLE(REQUEST_ANIMATION_FRAME)
#error "SMOOTH_SCROLLING requires REQUEST_ANIMATION_FRAME to be enabled."
#endif

#include "Timer.h"

namespace WebCore {

class FloatPoint;
class ScrollableArea;

class ScrollAnimationSmooth final: public ScrollAnimation {
public:
    ScrollAnimationSmooth(ScrollableArea&, const FloatPoint&, std::function<void (FloatPoint&&)>&& notifyPositionChangedFunction);
    virtual ~ScrollAnimationSmooth();

    enum class Curve {
        Linear,
        Quadratic,
        Cubic,
        Quartic,
        Bounce
    };

private:
    bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier) override;
    void stop() override;
    void updateVisibleLengths() override;
    void setCurrentPosition(const FloatPoint&) override;
#if !USE(REQUEST_ANIMATION_FRAME_TIMER)
    void serviceAnimation() override;
#endif

    struct PerAxisData {
        PerAxisData() = delete;

        PerAxisData(float position, int length)
            : currentPosition(position)
            , desiredPosition(position)
            , visibleLength(length)
        {
        }

        float currentPosition { 0 };
        double currentVelocity { 0 };

        double desiredPosition { 0 };
        double desiredVelocity { 0 };

        double startPosition { 0 };
        double startTime { 0 };
        double startVelocity { 0 };

        double animationTime { 0 };
        double lastAnimationTime { 0 };

        double attackPosition { 0 };
        double attackTime { 0 };
        Curve attackCurve { Curve::Quadratic };

        double releasePosition { 0 };
        double releaseTime { 0 };
        Curve releaseCurve { Curve::Quadratic };

        int visibleLength { 0 };
    };

    bool updatePerAxisData(PerAxisData&, ScrollGranularity, float delta, float minScrollPosition, float maxScrollPosition);
    bool animateScroll(PerAxisData&, double currentTime);

#if USE(REQUEST_ANIMATION_FRAME_TIMER)
    void requestAnimationTimerFired();
    void startNextTimer(double delay);
#else
    void startNextTimer();
#endif
    void animationTimerFired();
    bool animationTimerActive() const;

    std::function<void (FloatPoint&&)> m_notifyPositionChangedFunction;

    PerAxisData m_horizontalData;
    PerAxisData m_verticalData;

    double m_startTime { 0 };
#if USE(REQUEST_ANIMATION_FRAME_TIMER)
    Timer m_animationTimer;
#else
    bool m_animationActive { false };
#endif

};

} // namespace WebCore

#endif // ENABLE(SMOOTH_SCROLLING)
#endif // ScrollAnimationSmooth_h


text:
Widgets are special kinds of messages. These include:

- polls
- TODO lists
- `/me` messages
- Trivia bot

Some widgets are used with a leading `/` (like `/poll Tea or coffee?`), similar
to [slash commands](/subsystems/slash-commands.md), but these two concepts
are very different. Slash commands have nothing to do with message sending.

The trivia_quiz_bot does not use `/`'s. Instead, it sends "extra_data"
in messages to invoke **zforms** (which enable button-based UIs in the
messages).

## `/me` messages

These are the least complex. We use our markdown processors to
detect if a message is a `/me` message, plumb the flag through
the message object (as `is_me_message`) and have the clients
format it correctly. Related code (for the web app) lies in
`message_list_view.js` in `_maybe_format_me_message`.

## Polls, todo lists, and games

The most interactive widgets that we built during
2018 are for polls, todo lists, and games. You
launch widgets by sending one of the following messages:

- /poll
- /todo

The web app client provides the "widget experience" by
default. Other clients just show raw messages like
"/poll", and should be adding support
for widgets soon.

Our customers have long requested a poll/survey widget.
See [this issue](https://github.com/zulip/zulip/issues/9736).
There are workaround ways to do polls using things like
emoji reactions, but our poll widget provides a more
interactive experience.

### Data flow

Some important code entities for the widget implementation are:

- `SubMessage` database table
- `/json/submessage` API endpoint
- `static/js/submessage.js`
- `static/js/poll_widget.js`
- `static/js/widgetize.js`
- `static/js/zform.js`
- `static/templates/widgets/`
- `zerver/lib/widget.py`
- `zerver/views/submessage.py`

Both **poll** and **todo** widgets use the "submessage" architecture.
We'll use the poll widget as an example.

The `SubMessage` table, as the name indicates, allows
you to associate multiple submessages to any given
`Message` row. When a message gets sent, there's a
hook inside of `widget.py` that will detect widgets
like "/poll". If a message needs to be
widgetized, an initial `SubMessage` row will be
created with an appropriate `msg_type` (and persisted
to the database). This data will also be included
in the normal Zulip message event payload. Clients
can choose to ignore the submessage-related data, in
which case they'll gracefully degrade to seeing "/poll".
Of course, the web app client actually recognizes the
appropriate widgets.

The web app client will next collect poll options and votes
from users. The web app client has
code in `submessage.js` that dispatches events
to `widgetize.js`, which in turn sends events to
individual widgets. The widgets know how to render
themselves and set up click/input handlers to collect
data. They can then post back to `/json/submessage`
to attach more data to the message (and the
details are encapsulated with a callback). The server
will continue to persist `SubMessage` rows in the
database. These rows are encoded as JSON, and the
schema of the messages is driven by the individual widgets.
Most of the logic is in the client; things are fairly opaque
to the server at this point.

If a client joins Zulip after a message has accumulated
several submessage events, it will see all of those
events the first time it sees the parent message. Clients
need to know how to build/rebuild their state as each
submessage comes in. They also need to tolerate
misformatted data, ideally just dropping data on the floor.
If a widget throws an exception, it's caught before the
rest of the message feed is affected.

As far as rendering is concerned, each widget module
is given a parent `elem` when its `activate` function
is called. This is just a `<div>` inside of the parent
message in the message pane. The widget has access to
jQuery and template.render, and the developer can create
new templates in `static/templates/widgets/`.

A good way to learn the system is to read the code
in `static/js/poll_widget.js`. It is worth noting that
writing a new widget requires only minor backend
changes in the current architecture. This could change
in the future, but for now, a frontend developer mostly
needs to know JS, CSS, and HTML.

It may be useful to think of widgets in terms of a
bunch of clients exchanging peer-to-peer messages. The
server's only real role is to decide who gets delivered
which submessages. It's a lot like a "subchat" system.

### Backward compatibility

Our "submessage" widgets are still evolving, and we want
to have a plan for allowing future progress without
breaking old messages.

Widget developers can revise code to improve a
widget's visual polish without too much concern
for breaking how old messages get widgetized. They will need to
be more cautious if they change the actual data
structures passed around in the submessage payloads.

For significant schema changes, it would be worthwhile to add
some kind of versioning scheme inside of `SubMessages`, either
at the DB level or more at the JSON level within fields.
This has yet to be designed. One thing to consider is that
most widgets are somewhat ephemeral in nature, so it's not
the end of the world if upgrades cause some older messages
to be obsolete, as long as the code degrades gracefully.

Mission-critical widgets should have a deprecation strategy.
For example, you could add optional features for one version
bump and then only make them mandatory for the next version,
as long as you don't radically change the data model. And
if you're truly making radical changes, you can always
write a Django migration for the `SubMessage` data.

### Adding widgets

Right now we don't have a plugin model for the above widgets;
they are served up by the core Zulip server implementation.
Of course, anybody who wishes to build their own widget
has the option of forking the server code and self-hosting,
but we want to encourage folks to submit widget
code to our codebase in PRs. If we get to a critical mass
of contributed widgets, we will want to explore a more
dynamic mechanism for "plugging in" code from outside sources,
but that is not in our immediate roadmap.

This is sort of a segue to the next section of this document.
Suppose you want to write your own custom bot, and you
want to allow users to click buttons to respond to options,
but you don't want to have to modify the Zulip server codebase
to turn on those features. This is where our "zform"
architecture comes to the rescue.

## zform (trivia quiz bot)

This section will describe our "zform" architecture.

For context, imagine a naive trivia bot. The trivia bot
sends a question with the answers labeled as A, B, C,
and D. Folks who want to answer the bot send back an
answer have to send an actual Zulip message with something
like `@trivia_bot answer A to Q01`, which is kind of
tedious to type. Wouldn't it be nice if the bot could
serve up some kind of buttons with canned replies, so
that the user just hits a button?

That is where zforms come in. Zulip's trivia bot sends
the Zulip server a JSON representation of a form it
wants rendered, and then the client renders a generic
"**zform**" with buttons corresponding to `short_name` fields
inside a `choices` list inside of the JSON payload.

Here is what an example payload looks like:

```json
{
    "extra_data": {
        "type": "choices",
        "heading": "05: What color is a blueberry?",
        "choices": [
            {
                "type": "multiple_choice",
                "reply": "answer 05 A",
                "long_name": "red",
                "short_name": "A"
            },
            {
                "type": "multiple_choice",
                "reply": "answer 05 B",
                "long_name": "blue",
                "short_name": "B"
            },
            {
                "type": "multiple_choice",
                "reply": "answer 05 C",
                "long_name": "yellow",
                "short_name": "C"
            },
            {
                "type": "multiple_choice",
                "reply": "answer 05 D",
                "long_name": "orange",
                "short_name": "D"
            }
        ]
    },
    "widget_type": "zform"
}
```

When users click on the buttons, **generic** click
handlers automatically simulate a client reply using
a field called `reply` (in `choices`) as the content
of the message reply. Then the bot sees the reply
and grades the answer using ordinary chat-bot coding.

The beautiful thing is that any third party developer
can enhance bots that are similar to the **trivia_quiz**
bot without touching any Zulip code, because **zforms**
are completely generic.

## Data flow

We can walk through the steps from the bot generating
the **zform** to the client rendering it.

First,
[here](https://github.com/zulip/python-zulip-api/blob/main/zulip_bots/zulip_bots/bots/trivia_quiz/trivia_quiz.py)
is the code that produces the JSON.

```py
def format_quiz_for_widget(quiz_id: str, quiz: Dict[str, Any]) -> str:
    widget_type = 'zform'
    question = quiz['question']
    answers = quiz['answers']

    heading = quiz_id + ': ' + question

    def get_choice(letter: str) -> Dict[str, str]:
        answer = answers[letter]
        reply = 'answer ' + quiz_id + ' ' + letter

        return dict(
            type='multiple_choice',
            short_name=letter,
            long_name=answer,
            reply=reply,
        )

    choices = [get_choice(letter) for letter in 'ABCD']

    extra_data = dict(
        type='choices',
        heading=heading,
        choices=choices,
    )

    widget_content = dict(
        widget_type=widget_type,
        extra_data=extra_data,
    )
    payload = json.dumps(widget_content)
    return payload
```

The above code processes data that is specific to a trivia
quiz, but it follows a generic schema.

The bot sends the JSON payload to the server using the
`send_reply` callback.

The bot framework looks for the optional `widget_content`
parameter in `send_reply` and includes that in the
message payload it sends to the server.

The server validates the schema of `widget_content` using
`check_widget_content`.

Then code inside of `zerver/lib/widget.py` builds a single
`SubMessage` row to contain the **zform** payload, and the
server also sends this payload to all clients who are
recipients of the parent message.

When the message gets to the client, the codepath for **zform**
is actually quite similar to what happens with a more
customized widget like **poll**. (In fact, **zform** is a
sibling of **poll** and **zform** just has a somewhat more
generic job to do.) In `static/js/widgetize.js` you will see
where this code converges, with snippets like this:

```js
widgets.poll = poll_widget;
widgets.todo = todo_widget;
widgets.zform = zform;
```

The code in `static/js/zform.js` renders the form (not
shown here) and then sets up a click handler like below:

```js
    $elem.find('button').on('click', function (e) {
        e.stopPropagation();

        // Grab our index from the markup.
        var idx = $(e.target).attr('data-idx');

        // Use the index from the markup to dereference our
        // data structure.
        var reply_content = data.choices[idx].reply;

        transmit.reply_message({
            message: opts.message,
            content: reply_content,
        });
    });
```

And then we are basically done!


text:
module.exports = {
  title: 'h1',
  form: 'form',
  continueButton: 'form button:contains("Continue")',
  submitButton: 'form button:contains("Add company")',
  backButton: 'form button:contains("Back")',
  subheader: 'form p',
  stepHeader: 'form h3',
  summary: 'form dl',
  regionSelect: 'form select#uk_region',
  sectorSelect: 'form select#sector',
  entitySearch: {
    companyNameField: 'input[name="dnbCompanyName"]',
    postalCodeField: 'input[name="dnbPostalCode"]',
    searchButton: 'form button:contains("Find company")',
    results: {
      someCompanyName: 'form ol li:nth-child(1)',
      someOtherCompany: 'form ol li:nth-child(2)',
      companyUnknownPostcode: 'form ol li:nth-child(3)',
    },
    cannotFind: {
      summary: 'details summary span',
      stillCannotFind: `button:contains("I still can't find what I'm looking for")`,
    },
  },
  newCompanyRecordForm: {
    whyAmISeeingThis: {
      summary: 'details summary span',
    },
    organisationType: {
      charity: 'label:contains("Charity") input[type="radio"]',
      governmentDepartmentOrOtherPublicBody:
        'label:contains("Government department or other public body") input[type="radio"]',
      limitedCompany: 'label:contains("Limited company") input[type="radio"]',
      limitedPartnership:
        'label:contains("Limited partnership") input[type="radio"]',
      partnership: 'label:contains("Partnership") input[type="radio"]',
      soleTrader: 'label:contains("Sole Trader") input[type="radio"]',
    },
    companyName: 'input[name="name"]',
    companyNameContainer: '#field-name',
    website: 'input[name="website"]',
    websiteContainer: '#field-website',
    telephone: 'input[name="telephone_number"]',
    telephoneContainer: '#field-telephone_number',
    address: {
      postcode: 'input[name="postcode"]',
      findUkAddress: 'form button:contains("Find UK address")',
      options: 'label:contains("Select an address") select',
    },
    region: 'select#uk_region',
    sector: 'select#sector',
    areaUS: 'select#area',
    areaCanada: 'select#areaCanada',
  },
  companyDetails: {
    subheader: 'form h2',
  },
}


text:
<?php

declare(strict_types=1);

namespace DiContainerBenchmarks\Container\Zen;

use WoohooLabs\Zen\Config\AbstractCompilerConfig;
use WoohooLabs\Zen\Config\FileBasedDefinition\FileBasedDefinitionConfig;
use WoohooLabs\Zen\Config\FileBasedDefinition\FileBasedDefinitionConfigInterface;

class ZenPrototypeCompilerConfig extends AbstractCompilerConfig
{
    public function getContainerNamespace(): string
    {
        return "DiContainerBenchmarks\\Container\\Zen\\Resource";
    }

    public function getContainerClassName(): string
    {
        return "CompiledPrototypeContainer";
    }

    public function useConstructorInjection(): bool
    {
        return true;
    }

    public function usePropertyInjection(): bool
    {
        return false;
    }

    public function getFileBasedDefinitionConfig(): FileBasedDefinitionConfigInterface
    {
        return FileBasedDefinitionConfig::disabledGlobally("PrototypeDefinitions");
    }

    public function getContainerConfigs(): array
    {
        return [
            new ZenPrototypeContainerConfig(),
        ];
    }
}


text:
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Linguofeng's Blog</title>
</head>
<body>
  <script type="text/javascript" src="/dist/bundle.js"></script>
</body>
</html>


text:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <LinearLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:orientation="vertical" >
    </LinearLayout>

    <TextView
        android:id="@+id/bottom_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/RegisterPrompt"
        android:textSize="14sp" />

</RelativeLayout>


text:
<?php
/**
 * ProductApi
 * PHP version 5
 *
 * @category Class
 * @package  Swagger\Client
 * @author   http://github.com/swagger-api/swagger-codegen
 * @license  http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
 * @link     https://github.com/swagger-api/swagger-codegen
 */

/**
 * Coupons Api
 *
 * TrustAndUse coupons api in the swagger-2.0 specification
 *
 * OpenAPI spec version: 1.0.0
 * Contact: sp@7indigo.com
 * Generated by: https://github.com/swagger-api/swagger-codegen.git
 *
 * 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.
 */

/**
 * NOTE: This class is auto generated by the swagger code generator program.
 * https://github.com/swagger-api/swagger-codegen
 * Do not edit the class manually.
 */

namespace Swagger\Client\Api;

use \Swagger\Client\Configuration;
use \Swagger\Client\ApiClient;
use \Swagger\Client\ApiException;
use \Swagger\Client\ObjectSerializer;

/**
 * ProductApi Class Doc Comment
 *
 * @category Class
 * @package  Swagger\Client
 * @author   http://github.com/swagger-api/swagger-codegen
 * @license  http://www.apache.org/licenses/LICENSE-2.0 Apache Licene v2
 * @link     https://github.com/swagger-api/swagger-codegen
 */
class ProductApi
{

    /**
     * API Client
     *
     * @var \Swagger\Client\ApiClient instance of the ApiClient
     */
    protected $apiClient;

    /**
     * Constructor
     *
     * @param \Swagger\Client\ApiClient|null $apiClient The api client to use
     */
    public function __construct(\Swagger\Client\ApiClient $apiClient = null)
    {
        if ($apiClient == null) {
            $apiClient = new ApiClient();
            $apiClient->getConfig()->setHost('http://api.trustanduse.com/v1.0');
        }

        $this->apiClient = $apiClient;
    }

    /**
     * Get API client
     *
     * @return \Swagger\Client\ApiClient get the API client
     */
    public function getApiClient()
    {
        return $this->apiClient;
    }

    /**
     * Set the API client
     *
     * @param \Swagger\Client\ApiClient $apiClient set the API client
     *
     * @return ProductApi
     */
    public function setApiClient(\Swagger\Client\ApiClient $apiClient)
    {
        $this->apiClient = $apiClient;
        return $this;
    }

    /**
     * Operation addProductBarcode
     *
     *
     *
     * @param string $id ID for the product to be updated. (required)
     * @param \Swagger\Client\Model\AddBarcode $addBarcode Barcode parameters for updating product (required)
     * @param string $companyID Company ID Parameter for the company that the product is connected to. Required only if the product is connected with a company. (optional)
     * @param string $brandID Brand ID Parameter for the Brand that the product is connected to. Required only if the product is connected with a Brand. (optional)
     * @param string $storeID Store ID Parameter for the Store that the product is connected to. Required only if the product is connected with a Store. (optional)
     * @param string $merchantID Merchant ID Parameter for the Merchant that the product is connected to. Required only if the product is connected with a Merchant. (optional)
     * @return \Swagger\Client\Model\ProductID
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function addProductBarcode($id, $addBarcode, $companyID = null, $brandID = null, $storeID = null, $merchantID = null)
    {
        list($response) = $this->addProductBarcodeWithHttpInfo($id, $addBarcode, $companyID, $brandID, $storeID, $merchantID);
        return $response;
    }

    /**
     * Operation addProductBarcodeWithHttpInfo
     *
     *
     *
     * @param string $id ID for the product to be updated. (required)
     * @param \Swagger\Client\Model\AddBarcode $addBarcode Barcode parameters for updating product (required)
     * @param string $companyID Company ID Parameter for the company that the product is connected to. Required only if the product is connected with a company. (optional)
     * @param string $brandID Brand ID Parameter for the Brand that the product is connected to. Required only if the product is connected with a Brand. (optional)
     * @param string $storeID Store ID Parameter for the Store that the product is connected to. Required only if the product is connected with a Store. (optional)
     * @param string $merchantID Merchant ID Parameter for the Merchant that the product is connected to. Required only if the product is connected with a Merchant. (optional)
     * @return Array of \Swagger\Client\Model\ProductID, HTTP status code, HTTP response headers (array of strings)
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function addProductBarcodeWithHttpInfo($id, $addBarcode, $companyID = null, $brandID = null, $storeID = null, $merchantID = null)
    {
        // verify the required parameter 'id' is set
        if ($id === null) {
            throw new \InvalidArgumentException('Missing the required parameter $id when calling addProductBarcode');
        }
        // verify the required parameter 'addBarcode' is set
        if ($addBarcode === null) {
            throw new \InvalidArgumentException('Missing the required parameter $addBarcode when calling addProductBarcode');
        }
        // parse inputs
        $resourcePath = "/product/{id}/barcodes";
        $httpBody = '';
        $queryParams = array();
        $headerParams = array();
        $formParams = array();
        $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json'));
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json'));

        // query params
        if ($companyID !== null) {
            $queryParams['companyID'] = $this->apiClient->getSerializer()->toQueryValue($companyID);
        }
        // query params
        if ($brandID !== null) {
            $queryParams['brandID'] = $this->apiClient->getSerializer()->toQueryValue($brandID);
        }
        // query params
        if ($storeID !== null) {
            $queryParams['storeID'] = $this->apiClient->getSerializer()->toQueryValue($storeID);
        }
        // query params
        if ($merchantID !== null) {
            $queryParams['merchantID'] = $this->apiClient->getSerializer()->toQueryValue($merchantID);
        }
        // path params
        if ($id !== null) {
            $resourcePath = str_replace(
                "{" . "id" . "}",
                $this->apiClient->getSerializer()->toPathValue($id),
                $resourcePath
            );
        }
        // default format to json
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // body params
        $_tempBody = null;
        if (isset($addBarcode)) {
            $_tempBody = $addBarcode;
        }

        // for model (json/xml)
        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }
        // this endpoint requires OAuth (access token)
        if (strlen($this->apiClient->getConfig()->getAccessToken()) !== 0) {
            $headerParams['Authorization'] = 'Bearer ' . $this->apiClient->getConfig()->getAccessToken();
        }
        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $resourcePath,
                'POST',
                $queryParams,
                $httpBody,
                $headerParams,
                '\Swagger\Client\Model\ProductID',
                '/product/{id}/barcodes'
            );

            return array($this->apiClient->getSerializer()->deserialize($response, '\Swagger\Client\Model\ProductID', $httpHeader), $statusCode, $httpHeader);
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\ProductID', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
                default:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Error', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
            }

            throw $e;
        }
    }

    /**
     * Operation addUserProduct
     *
     *
     *
     * @param string $id ID for the Product (required)
     * @param \Swagger\Client\Model\CreateProductUserRole $createProductUserRole Product's User Priveleges Parameters for the productID and UserID. (required)
     * @param string $couponID ID of the Coupon connected with the Product (only required for Authorization for the User making the request) (optional)
     * @return \Swagger\Client\Model\UserID
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function addUserProduct($id, $createProductUserRole, $couponID = null)
    {
        list($response) = $this->addUserProductWithHttpInfo($id, $createProductUserRole, $couponID);
        return $response;
    }

    /**
     * Operation addUserProductWithHttpInfo
     *
     *
     *
     * @param string $id ID for the Product (required)
     * @param \Swagger\Client\Model\CreateProductUserRole $createProductUserRole Product's User Priveleges Parameters for the productID and UserID. (required)
     * @param string $couponID ID of the Coupon connected with the Product (only required for Authorization for the User making the request) (optional)
     * @return Array of \Swagger\Client\Model\UserID, HTTP status code, HTTP response headers (array of strings)
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function addUserProductWithHttpInfo($id, $createProductUserRole, $couponID = null)
    {
        // verify the required parameter 'id' is set
        if ($id === null) {
            throw new \InvalidArgumentException('Missing the required parameter $id when calling addUserProduct');
        }
        // verify the required parameter 'createProductUserRole' is set
        if ($createProductUserRole === null) {
            throw new \InvalidArgumentException('Missing the required parameter $createProductUserRole when calling addUserProduct');
        }
        // parse inputs
        $resourcePath = "/product/{id}/user";
        $httpBody = '';
        $queryParams = array();
        $headerParams = array();
        $formParams = array();
        $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json'));
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json'));

        // query params
        if ($couponID !== null) {
            $queryParams['couponID'] = $this->apiClient->getSerializer()->toQueryValue($couponID);
        }
        // path params
        if ($id !== null) {
            $resourcePath = str_replace(
                "{" . "id" . "}",
                $this->apiClient->getSerializer()->toPathValue($id),
                $resourcePath
            );
        }
        // default format to json
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // body params
        $_tempBody = null;
        if (isset($createProductUserRole)) {
            $_tempBody = $createProductUserRole;
        }

        // for model (json/xml)
        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }
        // this endpoint requires OAuth (access token)
        if (strlen($this->apiClient->getConfig()->getAccessToken()) !== 0) {
            $headerParams['Authorization'] = 'Bearer ' . $this->apiClient->getConfig()->getAccessToken();
        }
        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $resourcePath,
                'POST',
                $queryParams,
                $httpBody,
                $headerParams,
                '\Swagger\Client\Model\UserID',
                '/product/{id}/user'
            );

            return array($this->apiClient->getSerializer()->deserialize($response, '\Swagger\Client\Model\UserID', $httpHeader), $statusCode, $httpHeader);
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\UserID', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
                default:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Error', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
            }

            throw $e;
        }
    }

    /**
     * Operation allProducts
     *
     *
     *
     * @param string $name Optional filter parameter to search for products with a name that contains value of parameter name. (optional)
     * @param string $productype Optional filter parameter to search for products with a productype that contains value of parameter productype. (optional)
     * @param string $description Optional filter parameter to search for products with description that contains value of parameter description. (optional)
     * @return \Swagger\Client\Model\ProductsArray
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function allProducts($name = null, $productype = null, $description = null)
    {
        list($response) = $this->allProductsWithHttpInfo($name, $productype, $description);
        return $response;
    }

    /**
     * Operation allProductsWithHttpInfo
     *
     *
     *
     * @param string $name Optional filter parameter to search for products with a name that contains value of parameter name. (optional)
     * @param string $productype Optional filter parameter to search for products with a productype that contains value of parameter productype. (optional)
     * @param string $description Optional filter parameter to search for products with description that contains value of parameter description. (optional)
     * @return Array of \Swagger\Client\Model\ProductsArray, HTTP status code, HTTP response headers (array of strings)
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function allProductsWithHttpInfo($name = null, $productype = null, $description = null)
    {
        // parse inputs
        $resourcePath = "/product/all";
        $httpBody = '';
        $queryParams = array();
        $headerParams = array();
        $formParams = array();
        $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json'));
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json'));

        // query params
        if ($name !== null) {
            $queryParams['name'] = $this->apiClient->getSerializer()->toQueryValue($name);
        }
        // query params
        if ($productype !== null) {
            $queryParams['productype'] = $this->apiClient->getSerializer()->toQueryValue($productype);
        }
        // query params
        if ($description !== null) {
            $queryParams['description'] = $this->apiClient->getSerializer()->toQueryValue($description);
        }
        // default format to json
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // for model (json/xml)
        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }
        // this endpoint requires OAuth (access token)
        if (strlen($this->apiClient->getConfig()->getAccessToken()) !== 0) {
            $headerParams['Authorization'] = 'Bearer ' . $this->apiClient->getConfig()->getAccessToken();
        }
        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $resourcePath,
                'GET',
                $queryParams,
                $httpBody,
                $headerParams,
                '\Swagger\Client\Model\ProductsArray',
                '/product/all'
            );

            return array($this->apiClient->getSerializer()->deserialize($response, '\Swagger\Client\Model\ProductsArray', $httpHeader), $statusCode, $httpHeader);
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\ProductsArray', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
                default:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Error', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
            }

            throw $e;
        }
    }

    /**
     * Operation createCouponProduct
     *
     *
     *
     * @param string $id ID of the Product (required)
     * @param \Swagger\Client\Model\ProductCouponCreateParameters $productCouponCreateParameters Coupon Parameters consisting of userid who initiated the creation proccess, products ids, categories ids, subcategories ids, primitives ids and optionally store ids. (required)
     * @return \Swagger\Client\Model\Coupon
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function createCouponProduct($id, $productCouponCreateParameters)
    {
        list($response) = $this->createCouponProductWithHttpInfo($id, $productCouponCreateParameters);
        return $response;
    }

    /**
     * Operation createCouponProductWithHttpInfo
     *
     *
     *
     * @param string $id ID of the Product (required)
     * @param \Swagger\Client\Model\ProductCouponCreateParameters $productCouponCreateParameters Coupon Parameters consisting of userid who initiated the creation proccess, products ids, categories ids, subcategories ids, primitives ids and optionally store ids. (required)
     * @return Array of \Swagger\Client\Model\Coupon, HTTP status code, HTTP response headers (array of strings)
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function createCouponProductWithHttpInfo($id, $productCouponCreateParameters)
    {
        // verify the required parameter 'id' is set
        if ($id === null) {
            throw new \InvalidArgumentException('Missing the required parameter $id when calling createCouponProduct');
        }
        // verify the required parameter 'productCouponCreateParameters' is set
        if ($productCouponCreateParameters === null) {
            throw new \InvalidArgumentException('Missing the required parameter $productCouponCreateParameters when calling createCouponProduct');
        }
        // parse inputs
        $resourcePath = "/product/{id}/coupon/create";
        $httpBody = '';
        $queryParams = array();
        $headerParams = array();
        $formParams = array();
        $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json'));
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json'));

        // path params
        if ($id !== null) {
            $resourcePath = str_replace(
                "{" . "id" . "}",
                $this->apiClient->getSerializer()->toPathValue($id),
                $resourcePath
            );
        }
        // default format to json
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // body params
        $_tempBody = null;
        if (isset($productCouponCreateParameters)) {
            $_tempBody = $productCouponCreateParameters;
        }

        // for model (json/xml)
        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }
        // this endpoint requires OAuth (access token)
        if (strlen($this->apiClient->getConfig()->getAccessToken()) !== 0) {
            $headerParams['Authorization'] = 'Bearer ' . $this->apiClient->getConfig()->getAccessToken();
        }
        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $resourcePath,
                'POST',
                $queryParams,
                $httpBody,
                $headerParams,
                '\Swagger\Client\Model\Coupon',
                '/product/{id}/coupon/create'
            );

            return array($this->apiClient->getSerializer()->deserialize($response, '\Swagger\Client\Model\Coupon', $httpHeader), $statusCode, $httpHeader);
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 201:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Coupon', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
                default:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Error', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
            }

            throw $e;
        }
    }

    /**
     * Operation createProduct
     *
     *
     *
     * @param \Swagger\Client\Model\ProductCreateParameters $productCreateParameters Product parameters for creating new product consisting of product type, name, description, brandID, images and optionally merchantids. (required)
     * @return \Swagger\Client\Model\Product
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function createProduct($productCreateParameters)
    {
        list($response) = $this->createProductWithHttpInfo($productCreateParameters);
        return $response;
    }

    /**
     * Operation createProductWithHttpInfo
     *
     *
     *
     * @param \Swagger\Client\Model\ProductCreateParameters $productCreateParameters Product parameters for creating new product consisting of product type, name, description, brandID, images and optionally merchantids. (required)
     * @return Array of \Swagger\Client\Model\Product, HTTP status code, HTTP response headers (array of strings)
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function createProductWithHttpInfo($productCreateParameters)
    {
        // verify the required parameter 'productCreateParameters' is set
        if ($productCreateParameters === null) {
            throw new \InvalidArgumentException('Missing the required parameter $productCreateParameters when calling createProduct');
        }
        // parse inputs
        $resourcePath = "/product/create";
        $httpBody = '';
        $queryParams = array();
        $headerParams = array();
        $formParams = array();
        $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json'));
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json'));

        // default format to json
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // body params
        $_tempBody = null;
        if (isset($productCreateParameters)) {
            $_tempBody = $productCreateParameters;
        }

        // for model (json/xml)
        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }
        // this endpoint requires OAuth (access token)
        if (strlen($this->apiClient->getConfig()->getAccessToken()) !== 0) {
            $headerParams['Authorization'] = 'Bearer ' . $this->apiClient->getConfig()->getAccessToken();
        }
        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $resourcePath,
                'POST',
                $queryParams,
                $httpBody,
                $headerParams,
                '\Swagger\Client\Model\Product',
                '/product/create'
            );

            return array($this->apiClient->getSerializer()->deserialize($response, '\Swagger\Client\Model\Product', $httpHeader), $statusCode, $httpHeader);
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Product', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
                default:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Error', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
            }

            throw $e;
        }
    }

    /**
     * Operation getProductDetails
     *
     *
     *
     * @param string $id ID for the product being searched for. (required)
     * @param string $companyID Company ID Parameter for the company that the product is connected to. Required only if the product is connected with a Company. (optional)
     * @param string $brandID Brand ID Parameter for the Brand that the product is connected to. Required only if the product is connected with a Brand. (optional)
     * @param string $storeID Store ID Parameter for the Store that the product is connected to. Required only if the product is connected with a Store. (optional)
     * @param string $merchantID Merchant ID Parameter for the Merchant that the product is connected to. Required only if the product is connected with a Merchant. (optional)
     * @return \Swagger\Client\Model\Product
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function getProductDetails($id, $companyID = null, $brandID = null, $storeID = null, $merchantID = null)
    {
        list($response) = $this->getProductDetailsWithHttpInfo($id, $companyID, $brandID, $storeID, $merchantID);
        return $response;
    }

    /**
     * Operation getProductDetailsWithHttpInfo
     *
     *
     *
     * @param string $id ID for the product being searched for. (required)
     * @param string $companyID Company ID Parameter for the company that the product is connected to. Required only if the product is connected with a Company. (optional)
     * @param string $brandID Brand ID Parameter for the Brand that the product is connected to. Required only if the product is connected with a Brand. (optional)
     * @param string $storeID Store ID Parameter for the Store that the product is connected to. Required only if the product is connected with a Store. (optional)
     * @param string $merchantID Merchant ID Parameter for the Merchant that the product is connected to. Required only if the product is connected with a Merchant. (optional)
     * @return Array of \Swagger\Client\Model\Product, HTTP status code, HTTP response headers (array of strings)
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function getProductDetailsWithHttpInfo($id, $companyID = null, $brandID = null, $storeID = null, $merchantID = null)
    {
        // verify the required parameter 'id' is set
        if ($id === null) {
            throw new \InvalidArgumentException('Missing the required parameter $id when calling getProductDetails');
        }
        // parse inputs
        $resourcePath = "/product/details/{id}";
        $httpBody = '';
        $queryParams = array();
        $headerParams = array();
        $formParams = array();
        $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json'));
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json'));

        // query params
        if ($companyID !== null) {
            $queryParams['companyID'] = $this->apiClient->getSerializer()->toQueryValue($companyID);
        }
        // query params
        if ($brandID !== null) {
            $queryParams['brandID'] = $this->apiClient->getSerializer()->toQueryValue($brandID);
        }
        // query params
        if ($storeID !== null) {
            $queryParams['storeID'] = $this->apiClient->getSerializer()->toQueryValue($storeID);
        }
        // query params
        if ($merchantID !== null) {
            $queryParams['merchantID'] = $this->apiClient->getSerializer()->toQueryValue($merchantID);
        }
        // path params
        if ($id !== null) {
            $resourcePath = str_replace(
                "{" . "id" . "}",
                $this->apiClient->getSerializer()->toPathValue($id),
                $resourcePath
            );
        }
        // default format to json
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // for model (json/xml)
        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }
        // this endpoint requires OAuth (access token)
        if (strlen($this->apiClient->getConfig()->getAccessToken()) !== 0) {
            $headerParams['Authorization'] = 'Bearer ' . $this->apiClient->getConfig()->getAccessToken();
        }
        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $resourcePath,
                'GET',
                $queryParams,
                $httpBody,
                $headerParams,
                '\Swagger\Client\Model\Product',
                '/product/details/{id}'
            );

            return array($this->apiClient->getSerializer()->deserialize($response, '\Swagger\Client\Model\Product', $httpHeader), $statusCode, $httpHeader);
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Product', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
                default:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Error', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
            }

            throw $e;
        }
    }

    /**
     * Operation productDelete
     *
     *
     *
     * @param string $id ID for the product to be deleted. (required)
     * @param string $companyID Company ID Parameter for the company that the product is connected to. Required only if the product is connected with a company. (optional)
     * @param string $brandID Brand ID Parameter for the Brand that the product is connected to. Required only if the product is connected with a Brand. (optional)
     * @param string $storeID Store ID Parameter for the Store that the product is connected to. Required only if the product is connected with a Store. (optional)
     * @param string $merchantID Merchant ID Parameter for the Merchant that the product is connected to. Required only if the product is connected with a Merchant. (optional)
     * @return \Swagger\Client\Model\Success
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function productDelete($id, $companyID = null, $brandID = null, $storeID = null, $merchantID = null)
    {
        list($response) = $this->productDeleteWithHttpInfo($id, $companyID, $brandID, $storeID, $merchantID);
        return $response;
    }

    /**
     * Operation productDeleteWithHttpInfo
     *
     *
     *
     * @param string $id ID for the product to be deleted. (required)
     * @param string $companyID Company ID Parameter for the company that the product is connected to. Required only if the product is connected with a company. (optional)
     * @param string $brandID Brand ID Parameter for the Brand that the product is connected to. Required only if the product is connected with a Brand. (optional)
     * @param string $storeID Store ID Parameter for the Store that the product is connected to. Required only if the product is connected with a Store. (optional)
     * @param string $merchantID Merchant ID Parameter for the Merchant that the product is connected to. Required only if the product is connected with a Merchant. (optional)
     * @return Array of \Swagger\Client\Model\Success, HTTP status code, HTTP response headers (array of strings)
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function productDeleteWithHttpInfo($id, $companyID = null, $brandID = null, $storeID = null, $merchantID = null)
    {
        // verify the required parameter 'id' is set
        if ($id === null) {
            throw new \InvalidArgumentException('Missing the required parameter $id when calling productDelete');
        }
        // parse inputs
        $resourcePath = "/product/{id}/delete";
        $httpBody = '';
        $queryParams = array();
        $headerParams = array();
        $formParams = array();
        $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json'));
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json'));

        // query params
        if ($companyID !== null) {
            $queryParams['companyID'] = $this->apiClient->getSerializer()->toQueryValue($companyID);
        }
        // query params
        if ($brandID !== null) {
            $queryParams['brandID'] = $this->apiClient->getSerializer()->toQueryValue($brandID);
        }
        // query params
        if ($storeID !== null) {
            $queryParams['storeID'] = $this->apiClient->getSerializer()->toQueryValue($storeID);
        }
        // query params
        if ($merchantID !== null) {
            $queryParams['merchantID'] = $this->apiClient->getSerializer()->toQueryValue($merchantID);
        }
        // path params
        if ($id !== null) {
            $resourcePath = str_replace(
                "{" . "id" . "}",
                $this->apiClient->getSerializer()->toPathValue($id),
                $resourcePath
            );
        }
        // default format to json
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // for model (json/xml)
        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }
        // this endpoint requires OAuth (access token)
        if (strlen($this->apiClient->getConfig()->getAccessToken()) !== 0) {
            $headerParams['Authorization'] = 'Bearer ' . $this->apiClient->getConfig()->getAccessToken();
        }
        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $resourcePath,
                'DELETE',
                $queryParams,
                $httpBody,
                $headerParams,
                '\Swagger\Client\Model\Success',
                '/product/{id}/delete'
            );

            return array($this->apiClient->getSerializer()->deserialize($response, '\Swagger\Client\Model\Success', $httpHeader), $statusCode, $httpHeader);
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Success', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
                default:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Error', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
            }

            throw $e;
        }
    }

    /**
     * Operation removeUserProduct
     *
     *
     *
     * @param string $id ID for the Product (required)
     * @param \Swagger\Client\Model\DeleteProductUserRole $deleteProductUserRole Product's User ID and privileges to be removed  for the product ID. (required)
     * @param string $couponID ID of the Coupon connected with the Product (only required for Authorization for the User making the request) (optional)
     * @return \Swagger\Client\Model\UserID
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function removeUserProduct($id, $deleteProductUserRole, $couponID = null)
    {
        list($response) = $this->removeUserProductWithHttpInfo($id, $deleteProductUserRole, $couponID);
        return $response;
    }

    /**
     * Operation removeUserProductWithHttpInfo
     *
     *
     *
     * @param string $id ID for the Product (required)
     * @param \Swagger\Client\Model\DeleteProductUserRole $deleteProductUserRole Product's User ID and privileges to be removed  for the product ID. (required)
     * @param string $couponID ID of the Coupon connected with the Product (only required for Authorization for the User making the request) (optional)
     * @return Array of \Swagger\Client\Model\UserID, HTTP status code, HTTP response headers (array of strings)
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function removeUserProductWithHttpInfo($id, $deleteProductUserRole, $couponID = null)
    {
        // verify the required parameter 'id' is set
        if ($id === null) {
            throw new \InvalidArgumentException('Missing the required parameter $id when calling removeUserProduct');
        }
        // verify the required parameter 'deleteProductUserRole' is set
        if ($deleteProductUserRole === null) {
            throw new \InvalidArgumentException('Missing the required parameter $deleteProductUserRole when calling removeUserProduct');
        }
        // parse inputs
        $resourcePath = "/product/{id}/user";
        $httpBody = '';
        $queryParams = array();
        $headerParams = array();
        $formParams = array();
        $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json'));
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json'));

        // query params
        if ($couponID !== null) {
            $queryParams['couponID'] = $this->apiClient->getSerializer()->toQueryValue($couponID);
        }
        // path params
        if ($id !== null) {
            $resourcePath = str_replace(
                "{" . "id" . "}",
                $this->apiClient->getSerializer()->toPathValue($id),
                $resourcePath
            );
        }
        // default format to json
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // body params
        $_tempBody = null;
        if (isset($deleteProductUserRole)) {
            $_tempBody = $deleteProductUserRole;
        }

        // for model (json/xml)
        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }
        // this endpoint requires OAuth (access token)
        if (strlen($this->apiClient->getConfig()->getAccessToken()) !== 0) {
            $headerParams['Authorization'] = 'Bearer ' . $this->apiClient->getConfig()->getAccessToken();
        }
        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $resourcePath,
                'DELETE',
                $queryParams,
                $httpBody,
                $headerParams,
                '\Swagger\Client\Model\UserID',
                '/product/{id}/user'
            );

            return array($this->apiClient->getSerializer()->deserialize($response, '\Swagger\Client\Model\UserID', $httpHeader), $statusCode, $httpHeader);
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\UserID', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
                default:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Error', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
            }

            throw $e;
        }
    }

    /**
     * Operation updateProduct
     *
     *
     *
     * @param string $id ID for the product to be updated. (required)
     * @param \Swagger\Client\Model\UpdateProductParameters $updateProductParameters Product parameters for updating product consisting of product type, name, description, brandID, images and merchantids. (required)
     * @param string $companyID Company ID Parameter for the company that the product is connected to. Required only if the product is connected with a company. (optional)
     * @param string $brandID Brand ID Parameter for the Brand that the product is connected to. Required only if the product is connected with a Brand. (optional)
     * @param string $storeID Store ID Parameter for the Store that the product is connected to. Required only if the product is connected with a Store. (optional)
     * @param string $merchantID Merchant ID Parameter for the Merchant that the product is connected to. Required only if the product is connected with a Merchant. (optional)
     * @return \Swagger\Client\Model\ProductID
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function updateProduct($id, $updateProductParameters, $companyID = null, $brandID = null, $storeID = null, $merchantID = null)
    {
        list($response) = $this->updateProductWithHttpInfo($id, $updateProductParameters, $companyID, $brandID, $storeID, $merchantID);
        return $response;
    }

    /**
     * Operation updateProductWithHttpInfo
     *
     *
     *
     * @param string $id ID for the product to be updated. (required)
     * @param \Swagger\Client\Model\UpdateProductParameters $updateProductParameters Product parameters for updating product consisting of product type, name, description, brandID, images and merchantids. (required)
     * @param string $companyID Company ID Parameter for the company that the product is connected to. Required only if the product is connected with a company. (optional)
     * @param string $brandID Brand ID Parameter for the Brand that the product is connected to. Required only if the product is connected with a Brand. (optional)
     * @param string $storeID Store ID Parameter for the Store that the product is connected to. Required only if the product is connected with a Store. (optional)
     * @param string $merchantID Merchant ID Parameter for the Merchant that the product is connected to. Required only if the product is connected with a Merchant. (optional)
     * @return Array of \Swagger\Client\Model\ProductID, HTTP status code, HTTP response headers (array of strings)
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function updateProductWithHttpInfo($id, $updateProductParameters, $companyID = null, $brandID = null, $storeID = null, $merchantID = null)
    {
        // verify the required parameter 'id' is set
        if ($id === null) {
            throw new \InvalidArgumentException('Missing the required parameter $id when calling updateProduct');
        }
        // verify the required parameter 'updateProductParameters' is set
        if ($updateProductParameters === null) {
            throw new \InvalidArgumentException('Missing the required parameter $updateProductParameters when calling updateProduct');
        }
        // parse inputs
        $resourcePath = "/product/details/{id}";
        $httpBody = '';
        $queryParams = array();
        $headerParams = array();
        $formParams = array();
        $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json'));
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json'));

        // query params
        if ($companyID !== null) {
            $queryParams['companyID'] = $this->apiClient->getSerializer()->toQueryValue($companyID);
        }
        // query params
        if ($brandID !== null) {
            $queryParams['brandID'] = $this->apiClient->getSerializer()->toQueryValue($brandID);
        }
        // query params
        if ($storeID !== null) {
            $queryParams['storeID'] = $this->apiClient->getSerializer()->toQueryValue($storeID);
        }
        // query params
        if ($merchantID !== null) {
            $queryParams['merchantID'] = $this->apiClient->getSerializer()->toQueryValue($merchantID);
        }
        // path params
        if ($id !== null) {
            $resourcePath = str_replace(
                "{" . "id" . "}",
                $this->apiClient->getSerializer()->toPathValue($id),
                $resourcePath
            );
        }
        // default format to json
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // body params
        $_tempBody = null;
        if (isset($updateProductParameters)) {
            $_tempBody = $updateProductParameters;
        }

        // for model (json/xml)
        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }
        // this endpoint requires OAuth (access token)
        if (strlen($this->apiClient->getConfig()->getAccessToken()) !== 0) {
            $headerParams['Authorization'] = 'Bearer ' . $this->apiClient->getConfig()->getAccessToken();
        }
        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $resourcePath,
                'PUT',
                $queryParams,
                $httpBody,
                $headerParams,
                '\Swagger\Client\Model\ProductID',
                '/product/details/{id}'
            );

            return array($this->apiClient->getSerializer()->deserialize($response, '\Swagger\Client\Model\ProductID', $httpHeader), $statusCode, $httpHeader);
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\ProductID', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
                default:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Error', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
            }

            throw $e;
        }
    }

    /**
     * Operation updateProductBarcodes
     *
     *
     *
     * @param string $id ID for the product to be updated. (required)
     * @param \Swagger\Client\Model\UpdateBarcode $updateBarcode Product parameters for updating product consisting of productID for which to update the barcodes, userID for Authorization to grand permission and barcodes array. (required)
     * @param string $companyID Company ID Parameter for the company that the product is connected to. Required only if the product is connected with a Company. (optional)
     * @param string $brandID Brand ID Parameter for the Brand that the product is connected to. Required only if the product is connected with a Brand. (optional)
     * @param string $storeID Store ID Parameter for the Store that the product is connected to. Required only if the product is connected with a Store. (optional)
     * @param string $merchantID Merchant ID Parameter for the Merchant that the product is connected to. Required only if the product is connected with a Merchant. (optional)
     * @return \Swagger\Client\Model\ProductID
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function updateProductBarcodes($id, $updateBarcode, $companyID = null, $brandID = null, $storeID = null, $merchantID = null)
    {
        list($response) = $this->updateProductBarcodesWithHttpInfo($id, $updateBarcode, $companyID, $brandID, $storeID, $merchantID);
        return $response;
    }

    /**
     * Operation updateProductBarcodesWithHttpInfo
     *
     *
     *
     * @param string $id ID for the product to be updated. (required)
     * @param \Swagger\Client\Model\UpdateBarcode $updateBarcode Product parameters for updating product consisting of productID for which to update the barcodes, userID for Authorization to grand permission and barcodes array. (required)
     * @param string $companyID Company ID Parameter for the company that the product is connected to. Required only if the product is connected with a Company. (optional)
     * @param string $brandID Brand ID Parameter for the Brand that the product is connected to. Required only if the product is connected with a Brand. (optional)
     * @param string $storeID Store ID Parameter for the Store that the product is connected to. Required only if the product is connected with a Store. (optional)
     * @param string $merchantID Merchant ID Parameter for the Merchant that the product is connected to. Required only if the product is connected with a Merchant. (optional)
     * @return Array of \Swagger\Client\Model\ProductID, HTTP status code, HTTP response headers (array of strings)
     * @throws \Swagger\Client\ApiException on non-2xx response
     */
    public function updateProductBarcodesWithHttpInfo($id, $updateBarcode, $companyID = null, $brandID = null, $storeID = null, $merchantID = null)
    {
        // verify the required parameter 'id' is set
        if ($id === null) {
            throw new \InvalidArgumentException('Missing the required parameter $id when calling updateProductBarcodes');
        }
        // verify the required parameter 'updateBarcode' is set
        if ($updateBarcode === null) {
            throw new \InvalidArgumentException('Missing the required parameter $updateBarcode when calling updateProductBarcodes');
        }
        // parse inputs
        $resourcePath = "/product/{id}/barcodes";
        $httpBody = '';
        $queryParams = array();
        $headerParams = array();
        $formParams = array();
        $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json'));
        if (!is_null($_header_accept)) {
            $headerParams['Accept'] = $_header_accept;
        }
        $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json'));

        // query params
        if ($companyID !== null) {
            $queryParams['companyID'] = $this->apiClient->getSerializer()->toQueryValue($companyID);
        }
        // query params
        if ($brandID !== null) {
            $queryParams['brandID'] = $this->apiClient->getSerializer()->toQueryValue($brandID);
        }
        // query params
        if ($storeID !== null) {
            $queryParams['storeID'] = $this->apiClient->getSerializer()->toQueryValue($storeID);
        }
        // query params
        if ($merchantID !== null) {
            $queryParams['merchantID'] = $this->apiClient->getSerializer()->toQueryValue($merchantID);
        }
        // path params
        if ($id !== null) {
            $resourcePath = str_replace(
                "{" . "id" . "}",
                $this->apiClient->getSerializer()->toPathValue($id),
                $resourcePath
            );
        }
        // default format to json
        $resourcePath = str_replace("{format}", "json", $resourcePath);

        // body params
        $_tempBody = null;
        if (isset($updateBarcode)) {
            $_tempBody = $updateBarcode;
        }

        // for model (json/xml)
        if (isset($_tempBody)) {
            $httpBody = $_tempBody; // $_tempBody is the method argument, if present
        } elseif (count($formParams) > 0) {
            $httpBody = $formParams; // for HTTP post (form)
        }
        // this endpoint requires OAuth (access token)
        if (strlen($this->apiClient->getConfig()->getAccessToken()) !== 0) {
            $headerParams['Authorization'] = 'Bearer ' . $this->apiClient->getConfig()->getAccessToken();
        }
        // make the API Call
        try {
            list($response, $statusCode, $httpHeader) = $this->apiClient->callApi(
                $resourcePath,
                'PUT',
                $queryParams,
                $httpBody,
                $headerParams,
                '\Swagger\Client\Model\ProductID',
                '/product/{id}/barcodes'
            );

            return array($this->apiClient->getSerializer()->deserialize($response, '\Swagger\Client\Model\ProductID', $httpHeader), $statusCode, $httpHeader);
        } catch (ApiException $e) {
            switch ($e->getCode()) {
                case 200:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\ProductID', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
                default:
                    $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Error', $e->getResponseHeaders());
                    $e->setResponseObject($data);
                    break;
            }

            throw $e;
        }
    }

}