swcl.product.pathProductClass

Class PathProduct

The PathProduct class is a convenience wrapper for accessing products with the JSMA products. By establishing the concept of path products it allows to model hierarchical product structures sharing attributes with complex business rules. One of the main goals of PathProduct is next to the path products to simplify working with product data for integrators and making the application code as long term stable as possible leveraging possible changes in the internal APIs. With adding extensibility it also allows to change the businesslogic for certain products or product groups without chaning the application code.

PathProduct provides:

  • Complex merging of multiple products (path products) to allow hierarchical access to product data
  • Functional properties wrapping the internal cmplexity allowing stable and simple integration code using product data
  • Flexible Extensibility for products via flexible attributes in the hierarchy to add new field and methods or change existing fields and methods

Index

The concept of "Path Products"

The JSMA products and JSMA product provide access to the IKONA Online PIM (PathProduct Information Management) which is 100% integrated into the IFE Management. For simple portals this is completely sufficient. But in more complex situations where different portals shall share the product database or products shall be provided to customers with little adaptions (i.e. a christmas edition with speical layouts) it might quickly get tedious to always copy the whole product data.

So it seems valuable to be able to provide a way to access product data in a hierarchical manner, where child products can inherit values from parent products. Thinking through that concept it appears that the rules of how to inherit, when to inherit and probably how to join the inherited data can be complex and always provide new requirements. So allowing to functionally combine/inherit/replace certain attributes and functions within the hierarchy is deemed to be necessary.

To solve this requirement the PathProduct wrapper provides the concept of "path products" which means that a product name (hrid) is defined to contain dots to split each hierarchy layer. So a standard cup could be named testing.fotogifts.cups.StandardCup in the system where a product with the name testing is the root path product and so forth. This leads to 4 products which get blended into one final product for the StandardCup.

Possible path product setup:

This allows to store informations in the 4 layers which are then blended together in the StandardCup. PathProduct provides many default fields to access the merged product data. Most of them can be overloaded by PathProductDelegates.

Use the PathProduct

Using the PathProduct is very simple just use the defined properties like simple properties. i.e. pathProduct.fqn resolves the Full Qualified Name of the product.

Some usage examples

...
var pathProduct = new PathProduct(productName);

//count path products with defined delegates
var delegateCount = 0;

pathProduct.each(function () {
  if (this.get("pathProductDelegateClass")) { delegateCount++; }
});

//create a visual pattern with + indicating path product has a delegate and - that it has none from top to bottom
var delegatePattern = pathProduct.reduceInv(function (last) {
  if (this.get("pathProductDelegateClass")) { last += "+"; }
  else { last += "-"; }
  return last;
}, "");

//resolve the first product name and capacity with a defined capacity from top to bottom
var firstProductWithCapacity = pathProduct.resolveInv(function () {
  if (this.get("capacity")) { return this.name + ", " + this.get("capacity"); }
});

//returns the flex attribute capacity defaulting to "" from bottom to top
var capacity = pathProduct.get("capacity", "");

//checks if the flex attribute capacity exists in one of the path product
var capacityHas = pathProduct.has("capacity");

//returns the flex attribute capacity2 defaulting to "" from bottom to top
var capacity2 = pathProduct.get("capacity2", "-");

//checks if the flex attribute capacity2 exists in one of the path product
var capacity2Has = pathProduct.has("capacity2");

//returns the set of flex attribute names of all path products
var flexAttributes = pathProduct.getFlexAttributeNames();

//create an array of tags properties from bottom to top
var tags = pathProduct.concat("tags");

//create an array of displayNames from top to bottom
var displayNames = pathProduct.concatInv("name1");

//create an array of pathProductDelegateClass flex attributes from top to bottom
var pathProductDelegateClasses = pathProduct.concatInvFlexAttribute("pathProductDelegateClass");

//create a string of joined tags from bottom to top
var tagsJoined = pathProduct.join("tags");

//create a string using | as separator from top to bottom
var displayNamesJoined = pathProduct.joinInv("name", " | ");

//create a string of pathProductDelegateClass flex attributes separated by :: from bottom to top
var pathProductDelegateClassesJoined = pathProduct.joinFlexAttribute("pathProductDelegateClass", "::");

//create a string of pathProductDelegateClass flex attributes separated by :: from top to bottom
var pathProductDelegateClassesJoinedInv = pathProduct.joinInvFlexAttribute("pathProductDelegateClass", "::");
...

Setup the PathProduct

In setting up the path product it wraps the complex business logic of retrieveing the properties into simple properties you know from every simple JS object. For that PathProduct provides the different define... methods to simplify the setup process.

The most common way to reflect a property in that structure is to do a bottom to top path product matching which means that the first defined attribute or flexible attribute from bottom to top in the product hierarchy is used which is great for names, formats, description and so forth, where the child can override the parents attributes. See method defineProperty and defineFlexAttributeProperty.

Another common approach is to join the values from all path products into one array or string which is great for preview images, tags, keyword and so forth. See method join.

If you need to evaluate from top to bottom use the ...Inv... flavors of the methods.

In general the PathProduct wrapper defines properties with the default JS Object defineProperty to hide the functional nature of the properties and allow to define if the property will be enumerated when i.e. generating a string with JSON stringify or is allowed to be changed (see configurable) or written. This makes the application use the properties very intuitive within its code and provides to change internal mappings without having to change the application code.

Some examples of setting up a PathProduct

...
//defines metaTitle to return the first not nul, undefied and not "" value from bottom to top
pathProduct.defineProperty("metaTitle", "metaTitle", true, "");

//defines metaKeywords to join the metaKeywords property of the path products bottom to top
Object.defineProperty(this, "metaKeywords", {

  get: function () {
    return self.join("metaKeywords", ", ");
  },
  configurable: true,
  enumerable: true
});

//defines price to return the internal value multiplied by 100 (EUR to Cent)
Object.defineProperty(this, "price", {
  get: function () {
    var price = self.getProperty("price", 0);
    return Math.round(price * 100);
  },
  configurable: true,
  enumerable: true
});
...

One of the most important additional feature to the path product concept is the extensibility, which can be driven by the products in the hierarchy, which is explained in the next paragraph.

Extend PathProduct with PathProductDelegates

Each of the path products can extend the PathProduct wrapper by providing a flex attribute pathProductDelegateClass which is set to a name of a macro in the system which has to provide a method extendPathProduct(pathProduct). This method will be called with the PathProduct instance allowing the delegate to modify, extend and remove properties and methods from the PathProduct wrapper. The call order is top to bottom providing an OOP like behaviour where the child overloads the parent.

PathProduct details showing how to wire a PathProductDelegate

For simplifying the extension in the PathProduct wrapper pattern PathProduct provides many useful methods in the pattern define...

Putting it all together

In the follwing chapter you will see how easy it is to use the PathProduct wrapper.

Using the PathProduct wrapper

Whenever you need to access product data in a macro:

1. Include the content swcl.product.pathProductClass

2. Construct a new PathProduct with the name of the desired path products

3. Thats it! You can now access all fields and methods like it was a "simple" product

Example

include("swcl.product.pathProductClass"); //<-- 1. include PathProduct Wrapper

function main(productName) {

  if ((productName === undefined) || (productName.length === 0)) {

    return JSON.stringify({
      status: "ERROR_PRODUCTNAME_INVALID"
    });
  }

  var result;

  try {
    var pathProduct = new PathProduct(productName); //<-- 2. Construct PathProduct

    result = {
      status: "OK",
      pathProduct: pathProduct, //<-- 3. Will print all fields into the return string generated below
      productDisplay: pathProduct.display //<-- 3. Just access the fields like simple JS values
    };
  } catch (ex) {

    result = {
      status: "ERROR_RESOLVING_PRODUCT",
      message: ex.message,
      stack: ex.stack
    };
  }
  
  return JSON.stringify(result);
}

Define a PathProductDelegate

Whenever you want to extend the PathProduct with a PathProductDelegate:

1. Define the flex attribute pathProductClass in one of the path products pointing to a macro you create

2. Define a method extendProduct(product) in your macro and extend the product instance within

3. Thats it! You extended the path product with your ProductDelegate.

Example

function extendPathProduct(pathProduct) //<-- 2.
{
  //extend with static value
  pathProduct.myValue = 42;

  //use helper methods from pathProduct to provide funtional properties
  pathProduct.defineFlexAttributeProperty("deliveryTime", "deliveryTime", true, "");

  //extend with own method (prototype is not needed as you just want to extend this instance)
  pathProduct.myMethod = function (param) {
    return param * this.myValue;
  }
}

Synopsis

By now you should see using the PathProduct wrapper is very simple and intuitive and the possibilities of managing complex product data setups is unlimited!

Intended usage

The PathProduct wrapper is intended to provide:

  • Flexibility
  • Extensibility
  • Convenience
  • Stable application code

Not intended usage

The wrapper might cause a performance impact if you need to access many products within one page as the wrapping is a pretty complex and time consuming process as the main focus was to provide flexibility and convenience. For that cases it is in any way considerable to use own SQLQuery or SQLCommand contents to acess the data directly in the database or just materialize the really needed data from the products table.


Fields

The following fields are defined in the class PathProduct:


category, currency, deliveryInformation, description, display, editUrl, flexAttributeNames, format1, format2, fqn, fqnClass, hasTemplate, id, isDeleted, isDirectDelivery, isInPortal, isShopDelivery, mergedProductCount, mergedProducts, mergedProductsInv, metaDescription, metaKeywords, metaTitle, name, name1, name2, originalPrice, previewImages, price, printApiId, productImage, shortDescription, sku, specLis, tags, template, type, url, vat


string PathProduct.category

(default: "") Returns the products category property resolving bottom to top of the path products

string PathProduct.currency

(default: €) Returns current portals flex attribute currency for convenience

string PathProduct.deliveryInformation

(default: "") Returns the deliveryInformation property resolving bottom to top of the path products

string PathProduct.description

(default: "") Returns the products description property resolving bottom to top of the path products

string PathProduct.display

(default: "") Returns the products name1 property resolving bottom to top of the path products (renaming is here for allowing to extend displayment rules without overloading the name1 by that)

int PathProduct.editUrl

(default: /products/<productFqn>/edit)

string[] PathProduct.flexAttributeNames

(default: []) Returns all different flexAttribute names as joined array bottom to top of the path products

string PathProduct.format1

(default: "") Returns the products format1 property resolving bottom to top of the path products

string PathProduct.format2

(default: "") Returns the products format2 property resolving bottom to top of the path products

string PathProduct.fqn

(required; not configurable) Returns the full qualified name resolving bottom to top of the path products - the product is required to have a valid name property

string PathProduct.fqnClass

Returns the products fqn with - instead of . for usage in CSS property in cents resolving bottom to top of the path products

boolean PathProduct.hasTemplate

(default: false; configurable) Returns true if the product has a template false otherwise

int PathProduct.id

(required; not configurable) Returns the the id resolving bottom to top of the path products - the product is required to have a valid name property - ATTENTION: This value might change when changing the product db

boolean PathProduct.isDeleted

(default: true; not configurable) Returns true if the product is deleted resolving bottom to top of the path products

boolean PathProduct.isDirectDelivery

(default: false; not configurable) Returns true if the product is activated for home delivery resolving bottom to top of the path products

boolean PathProduct.isInPortal

(default: false; not configurable) Returns true if the product is mapped in the portal resolving bottom to top of the path products

boolean PathProduct.isShopDelivery

(default: false) Returns true if the product is activated for shop delivery resolving bottom to top of the path products

int PathProduct.mergedProductCount

(enumerable: false, readonly; not configurable) Returns the path product count

product[] PathProduct.mergedProducts

(enumerable: false, readonly; not configurable) Returns the path products as reversed list from bottom to top - see JSMA product

product[] PathProduct.mergedProductsInv

(enumerable: false; readonly; not configurable) Returns the path products as list from top to bottom - see JSMA product

string PathProduct.metaDescription

(default: "") Returns the products metaDescription property resolving bottom to top of the path products

string PathProduct.metaKeywords

(default: "") Returns the products metaKeywords property as joined string of the path products from bottom to top of the path products

string PathProduct.metaTitle

(default: "") Returns the products metaTitle property resolving bottom to top of the path products

string PathProduct.name

(required; not configurable) Returns the full qualified name resolving bottom to top of the path products - the product is required to have a valid name property

string PathProduct.name1

(default: "") Returns the products name1 property resolving bottom to top of the path products

string PathProduct.name2

(default: "") Returns the products name2 property resolving bottom to top of the path products

int PathProduct.originalPrice

(default: 0) Returns the products originalPrice property in cents resolving bottom to top of the path products

UUID[] PathProduct.previewImages

(default: []) Returns the products previewImageIds properties as joined array from bottom to top of the path products

int PathProduct.price

(default: 0) Returns the products price property in cents resolving bottom to top of the path products

UUID PathProduct.printApiId

(default: "") Returns the products print API ID which is needed for giving the product in orders to the backend resolving bottom to top of the path products

UUID PathProduct.productImage

(default: "") Returns the products productImageId property resolving bottom to top of the path products

string PathProduct.shortDescription

(default: "") Returns the products shortDescription property resolving bottom to top of the path products

string PathProduct.sku

(default: "") Returns the products sku property resolving bottom to top of the path products

t PathProduct.specLis

string[] PathProduct.tags

(default: []) Returns the products tags properties as joined array from bottom to top of the path products

string PathProduct.template

(default: null) Returns the first template bottom to top of the product chain which has a template

string PathProduct.type

(default: "") Returns the products typ property resolving bottom to top of the path products (renaming is currently done for correcting the typo in the JSMA product)

int PathProduct.url

(default: /products/<productFqn>)

int PathProduct.vat

(default: 0) Returns the products vat property resolving bottom to top of the path products

Methods

The following functions are methods of the class PathProduct:


PathProduct, concat, concatFlexAttribute, concatInv, concatInvFlexAttribute, defineFlexAttributeProperty, defineInvFlexAttributeProperty, defineInvProperty, defineProperty, each, eachInv, get, getFlexAttributeNames, getFlexAttributeProperty, getInvFlexAttributeProperty, getInvProperty, getProperty, has, join, joinFlexAttribute, joinInv, joinInvFlexAttribute, reduce, reduceInv, resolve, resolveInv


Constructor PathProduct(string path) throws Error

Constructs a new path product wrapper with a given product path

  • Loads path products with JSMA products getProductsForNamePath
  • Defines basic properties for a product
  • Loads productDelegates for each path product from top to bottom

Parameter string path

The path of the product to be resolved

Returns PathProduct

A new instance of PathProduct

Throws Error

on:

  • null or empty string for path
  • empty list of found path products

object PathProduct.concat(string name)

Allows to concat an array of all the properties from all path products from bottom to top.

Parameter string name

Name of the property to concat

Returns object

Returns the concatenation of the values

object PathProduct.concatFlexAttribute(string name)

Allows to concat an array of all the flex attributes from all path products from bottom to top.

Parameter string name

Name of the property to concat

Returns object

Returns the concatenation of the values or []

object PathProduct.concatInv(string name)

Allows to concat an array of all the properties from all path products from top to bottom.

Parameter string name

Name of the property to concat

Returns object

Returns the concatenation of the values or []

object PathProduct.concatInvFlexAttribute(string name)

Allows to concat an array of all the flex attributes from all path products from top to bottom.

Parameter string name

Name of the property to concat

Returns object

Returns the concatenation of the values or []

PathProduct PathProduct.defineFlexAttributeProperty(string externalName, string internalName, boolean configurable, object defaultValue)

Retrieves a product flex attribute property resolving from bottom to top path product, which means the first not null, not undefined or not default value will be returned.

Parameter string externalName

Under this name the property will be mapped in the product wrapper allowing product.<externalName> or product["<externalName>"] to access it

Parameter string internalName

(optional; default: externalName) The name of the property to be retrieved from the path products

Parameter boolean configurable

(optional; default: false) Defined the property to allow to be overridden or not (see JS Object.setProperty() for more details on that)

Parameter object defaultValue

(optional; default: undefined) The value which is returned if no value in the path products is defined

Returns PathProduct

this for chaining statements

PathProduct PathProduct.defineInvFlexAttributeProperty(string externalName, string internalName, boolean configurable, object defaultValue)

Retrieves a product flex attribute property resolving from top to bottom path product, which means the first not null, not undefined or not default value will be returned.

Parameter string externalName

Under this name the property will be mapped in the product wrapper allowing product.<externalName> or product["<externalName>"] to access it

Parameter string internalName

(optional; default: externalName) The name of the property to be retrieved from the path products

Parameter boolean configurable

(optional; default: false) Defined the property to allow to be overridden or not (see JS Object.setProperty() for more details on that)

Parameter object defaultValue

(optional; default: undefined) The value which is returned if no value in the path products is defined

Returns PathProduct

this for chaining statements

PathProduct PathProduct.defineInvProperty(string externalName, string internalName, boolean configurable, object defaultValue)

Retrieves a product property resolving top to bottom path product, which means the first not null, not undefined or not default value will be returned.

Parameter string externalName

Under this name the property will be mapped in the product wrapper allowing product.<externalName> or product["<externalName>"] to access it

Parameter string internalName

(optional; default: externalName) The name of the property to be retrieved from the path products

Parameter boolean configurable

(optional; default: false) Defined the property to allow to be overridden or not (see JS Object.setProperty() for more details on that)

Parameter object defaultValue

(optional; default: undefined) The value which is returned if no value in the path products is defined

Returns PathProduct

this for chaining statements

PathProduct PathProduct.defineProperty(string externalName, string internalName, boolean configurable, object defaultValue)

Retrieves a product property using resolving from bottom to top path product, which means the first not null, not undefined or not default value will be returned.

Parameter string externalName

Under this name the property will be mapped in the product wrapper allowing product.<externalName> or product["<externalName>"] to access it

Parameter string internalName

(optional; default: externalName) The name of the property to be retrieved from the path products

Parameter boolean configurable

(optional; default: false) Defined the property to allow to be overridden or not (see JS Object.setProperty() for more details on that)

Parameter object defaultValue

(optional; default: undefined) The value which is returned if no value in the path products is defined

Returns PathProduct

this for chaining statements

PathProduct PathProduct.each(function callback)

Iterates through the path products from bottom to top calling the callback with this set to the certain product for each. See JSMA product for the this parameter of the callback.

Parameter function callback

Called with this set to the certain product for each path product

Returns PathProduct

this for chaining statements

PathProduct PathProduct.eachInv(function callback)

Iterates through the path products from top to bottom calling the callback with this set to the certain product for each. See JSMA product for the this parameter of the callback.

Parameter function callback

Called with this set to the certain product for each path product

Returns PathProduct

this for chaining statements

object PathProduct.get(string name, object defaultValue)

Returns the first not null, undefined and not defaultValue flex attribute with name by calling the callback set with this to the certain path product from bottom to top. This function is a shorthand for getFlexAttributeProperty.

Parameter string name

The flex attribute name to be retrieved from the path products

Parameter object defaultValue

(optional; default: undefined) Any default value you want want to be returned if no other result is found

Returns object

The first not null,undefined and not defaultValue flexible attribute in the path products

string[] PathProduct.getFlexAttributeNames()

Joins the different existing flex attributes of the path products to one array. Each flex attribute name may only exist once.

Returns string[]

All different flex attribute names of the path products which can then be retrieved using get

object PathProduct.getFlexAttributeProperty(string name, object defaultValue)

Returns the first not null, undefined and not defaultValue flex attribute with name by calling the callback set with this to the certain path product from bottom to top.

Parameter string name

The flex attribute name to be retrieved from the path products

Parameter object defaultValue

(optional; default: undefined) Any default value you want want to be returned if no other result is found

Returns object

The first not null,undefined and not defaultValue flexible attribute in the path products

object PathProduct.getInvFlexAttributeProperty(string name, object defaultValue)

Returns the first not null, undefined and not defaultValue flex attribute with name by calling the callback set with this to the certain path product from top to bottom.

Parameter string name

The flex attribute name to be retrieved from the path products

Parameter object defaultValue

(optional; default: undefined) Any default value you want want to be returned if no other result is found

Returns object

The first not null,undefined and not defaultValue flexible attribute in the path products

object PathProduct.getInvProperty(string name, object defaultValue)

Returns the first not null, undefined and not defaultValue attribute with name by calling the callback set with this to the certain path product from top to bottom.

Parameter string name

The flex attribute name to be retrieved from the path products

Parameter object defaultValue

(optional; default: undefined) Any default value you want want to be returned if no other result is found

Returns object

The first not null,undefined and not defaultValue flexible attribute in the path products

object PathProduct.getProperty(string name, object defaultValue)

Returns the first not null, undefined and not defaultValue attribute with name by calling the callback set with this to the certain path product from bottom to top.

Parameter string name

The flex attribute name to be retrieved from the path products

Parameter object defaultValue

(optional; default: undefined) Any default value you want want to be returned if no other result is found

Returns object

The first not null,undefined and not defaultValue flexible attribute in the path products

boolean PathProduct.has(string name)

Checks if one of the path products has a flex attribute with name from bottom to top which is not null or undefined.

Parameter string name

The flex attribute name to be checked if present from the path products

Returns boolean

True if one of the path products contains the flex attribute with name which is not undefined or null

object PathProduct.join(string name, string separator)

Allows to join all the properties name from all path products from bottom to top.

Parameter string name

Name of the property to join

Parameter string separator

Separator between elements

Returns object

Returns the concatenation of the values

object PathProduct.joinFlexAttribute(string name, string separator)

Allows to join all flex attributes name from all path products from bottom to top.

Parameter string name

Name of the property to join

Parameter string separator

Separator between elements

Returns object

Returns the concatenation of the values

object PathProduct.joinInv(string name, string separator)

Allows to join all the properties name from all path products from top to bottom.

Parameter string name

Name of the property to join

Parameter string separator

Separator between elements

Returns object

Returns the concatenation of the values

object PathProduct.joinInvFlexAttribute(string name, string separator)

Allows to join all flex attributes name from all path products from top to bottom.

Parameter string name

Name of the property to join

Parameter string separator

Separator between elements

Returns object

Returns the concatenation of the values

object PathProduct.reduce(function callback, function intialValue)

Allows to reduce a value from all path products from bottom to top. The callback is called with this as the certain path product. the initial value will be passed to the callback and the callback is expected to return a value for the call to the next callback. It is evaluated from top to bottom path product. See JSMA product for the this parameter of the callback.

Parameter function callback

Called with the lastValue (initialValue for the first) and this set to the certain product

Parameter function intialValue

(optional; default: undefined) Startvalue for the callback

Returns object

Returns the last return of the callback calls

object PathProduct.reduceInv(function callback, function intialValue)

Allows to reduce a value from all path products from top to bottom. The callback is called with this as the certain path product. the initial value will be passed to the callback and the callback is expected to return a value for the call to the next callback. It is evaluated from top to bottom path product. See JSMA product for the this parameter of the callback.

Parameter function callback

Called with the lastValue (initialValue for the first) and this set to the certain product

Parameter function intialValue

(optional; default: undefined) Startvalue for the callback

Returns object

Returns the last return of the callback calls

object PathProduct.resolve(function callback, object defaultValue)

Resolves a value by calling the callback set with this to the certain path product from bottom to top. The first callback return that is not null,undefined and not defaultValue will be returned by this function. See JSMA product for the this parameter of the callback.

Parameter function callback

Called with this set to the certain product for each path product and the defaultValue as parameter

Parameter object defaultValue

(optional; default: undefined) Any default value you want want to be returned if no other result is found

Returns object

The first not null,undefined and not defaultValue which is retrned by the callback

object PathProduct.resolveInv(function callback, object defaultValue)

Resolves a value by calling the callback set with this to the certain path product from top to bottom. The first callback return that is not null,undefined and not defaultValue will be returned by this function. See JSMA product for the this parameter of the callback.

Parameter function callback

Called with this set to the certain product for each path product and the defaultValue as parameter

Parameter object defaultValue

(optional; default: undefined) Any default value you want want to be returned if no other result is found

Returns object

The first not null,undefined and not defaultValue which is retrned by the callback