Which is the extension build order in hybris? - sap-commerce-cloud

I have these extensions in "extensioninfo.xml":
<extension dir="${HYBRIS_BIN_DIR}/ext-commerce/b2bapprovalprocess"/>
<extension dir="${HYBRIS_BIN_DIR}/ext-commerce/b2bcommerce"/>
<extension dir="${HYBRIS_BIN_DIR}/ext-template/b2bstore"/>
<extension dir="${HYBRIS_BIN_DIR}/ext-commerce/basecommerce"/>
<extension dir="${HYBRIS_BIN_DIR}/ext-content/bmecat"/>
How are these extensions built? Is there any order if I have them in the same "extensioninfo.xml" file? Will "b2bapprovalprocess" be built before "b2bcommerce", "b2bcommerce" before "b2bstore" and so on... ?

The order is defined by dependencies of extensions using requires-extension in extensions' extensioninfo.xml.
If C requires-extension B, and B requires-extension A, then the order is A, B, C.
If C requires-extension A, and B requires-extension A, then the order can be A, B, C or A, C, B. i.e. If 2 or more extensions are on the same level, then the order may be random at that level.
In the example code below from acceleratorcms extension, we can be sure that cms2lib or acceleratorservices will be processed first before acceleratorcms. However, we cannot be sure which one will be first: cms2lib or acceleratorservices.
<extensioninfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="extensioninfo.xsd">
<extension abstractclassprefix="Generated" classprefix="AcceleratorCms" managername="AcceleratorCmsManager" managersuperclass="de.hybris.platform.jalo.extension.Extension" name="acceleratorcms">
<requires-extension name="cms2lib"/>
<requires-extension name="acceleratorservices"/>
<coremodule generated="true" manager="de.hybris.platform.acceleratorcms.jalo.AcceleratorCmsManager" packageroot="de.hybris.platform.acceleratorcms"/>
</extension>
</extensioninfo>

Related

Recalculate XML child element

Using python3 I am trying to read an xml file and recalculate values based on the attributes within the Item, then write a copy of entire xml file with new values.
Example of xml file (about 10k rows in full file):
<?xml version="1.0" encoding="utf-8"?>
<Items>
<Item id="headscarf_d"
name="{=wW3iouiU}Hijab"
mesh="headscarf_d"
culture="Culture.aserai"
weight="0.5"
value="63"
appearance="1"
Type="HeadArmor">
<ItemComponent>
<Armor head_armor="3"
has_gender_variations="false"
beard_cover_type="type3"
hair_cover_type="all"
modifier_group="cloth_unarmoured"
material_type="Cloth"/>
</ItemComponent>
<Flags Civilian="true"
UseTeamColor="true" />
</Item>
<Item id="open_head_scarf"
name="{=qsVRoGUv}Open Head Scarf"
mesh="aserai_helmet_c"
culture="Culture.aserai"
weight="0.6"
value="174"
appearance="1"
Type="HeadArmor">
<ItemComponent>
<Armor head_armor="5"
has_gender_variations="false"
beard_cover_type="type3"
hair_cover_type="all"
modifier_group="cloth_unarmoured"
material_type="Cloth"/>
</ItemComponent>
<Flags Civilian="true"
UseTeamColor="true" />
</Item>
<Item id="woven_turban"
name="{=ArPvuBYK}Woven Turban"
subtype="head_armor"
mesh="aserai_helmet_h"
culture="Culture.aserai"
weight="0.8"
difficulty="0"
value="250"
appearance="1"
Type="HeadArmor">
<ItemComponent>
<Armor head_armor="6"
has_gender_variations="false"
beard_cover_type="type2"
hair_cover_type="all"
modifier_group="cloth_unarmoured"
material_type="Cloth"/>
</ItemComponent>
<Flags Civilian="true"
UseTeamColor="true" />
</Item>
</Items>
Taking a single item from the example xml,
<Item id="headscarf_d"
name="{=wW3iouiU}Hijab"
mesh="headscarf_d"
culture="Culture.aserai"
weight="0.5"
value="63"
appearance="1"
Type="HeadArmor">
<ItemComponent>
<Armor head_armor="3"
has_gender_variations="false"
beard_cover_type="type3"
hair_cover_type="all"
modifier_group="cloth_unarmoured"
material_type="Cloth"/>
</ItemComponent>
<Flags Civilian="true"
UseTeamColor="true" />
For simplicity say I wanted to take the Item value (63 above example) and divide by 2 (63/2=31.5). Then if the Item's ItemComponent material_type="Cloth" divide by 2 again (31.5/2=15.75). Finally round to an integer before updating the value and repeating for each item then writing the new updated xml file.
I attempted to use Reading, modifying and writing xml but could not get anything useful.
You are probably looking for something along these lines:
from lxml import etree
import math
inv="""[your xml above]"""
doc = etree.XML(inv)
values = doc.xpath('//Item')
materials = doc.xpath('Item//ItemComponent//Armor')
for t, m in zip(values,materials):
if m.attrib['material_type'] == 'Cloth':
val = float(t.attrib['value'])/4
t.attrib['value'] = str(math.ceil(val))
else:
t.attrib['value']= str(math.ceil(val*2))
print(etree.tostring(doc).decode())
The output is your xml with the Items/Item/#value attribute value divided by 2 or 4, as necessary, and rounded up by math.ceil(). Since all Items in your example have cloth as the value of the attribute material_type, they were all divided by 4 and rounded up to:
16
44
63

Simple XSLT transformation into ABAP Object

I'm again stuck with a transformation from XML into ABAP. This time, I want to put the XML data directly into an ABAP Object.
My XML looks like this:
<qualityStatus>
<address>0</address>
<bounceRisk>0</bounceRisk>
<checked>1</checked>
<domain>1</domain>
<domainScores>
<domainScore>
<domain>gmx.de</domain>
<score>0.8333333134651184</score>
</domainScore>
<domainScore>
<domain>ggs.de</domain>
<score>0.6666666269302368</score>
</domainScore>
<domainScore>
<domain>xyz.de</domain>
<score>0.6666666269302368</score>
</domainScore>
</domainScores>
<extSyntax>1</extSyntax>
<mailserver>1</mailserver>
<mailserverDiagnosis>1</mailserverDiagnosis>
<probability>1</probability>
<syntax>1</syntax>
</qualityStatus>
Edit: I changed back to a XSLT transformation, shortened to one attribute it looks like this:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sap="http://www.sap.com/sapxsl" version="1.0">
<xsl:output encoding="iso-8859-1" indent="yes" method="xml" version="1.0"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/qualityStatus">
<asx:abap version="1.0" xmlns:asx="http://www.sap.com/abapxml">
<asx:values>
<ROOT href="#o26"/>
</asx:values>
<asx:heap xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:abap="http://www.sap.com/abapxml/types/built-in"
xmlns:cls="http://www.sap.com/abapxml/classes/global"
xmlns:dic="http://www.sap.com/abapxml/types/dictionary">
<cls:ZCL_ADDRESS_QUALITY id="o26" >
<local.ZCL_ADDRESS_QUALITY>
<W_ADDRESS>
<xsl:value-of select="address"/>
</W_ADDRESS>
<!--More attributes here-->
</local.ZCL_ADDRESS_QUALITY>
</cls:ZCL_ADDRESS_QUALITY>
</asx:heap>
</asx:abap>
</xsl:template>
My object attributes are all public right now, because I thought this could be the problem. However, setter and getter do exist. Yes, my class does implement the interface if_serializable_object.
DATA:
w_address TYPE char1,
w_bouncerisk TYPE char1,
w_checked TYPE char1,
w_decoded TYPE stringval,
w_domain TYPE char1,
w_domainscores TYPE z_domainscore_t, "Table type for name + score
w_extsyntax TYPE char1,
w_mailserver TYPE char1,
w_mailserverdiagnosis TYPE char1,
w_probability TYPE char1,
w_syntax TYPE char1,
w_syntaxwarnings TYPE z_syntaxwarnings_t. "Table of syntaxwarnings
Finally, I call my transformation with an instance of my class:
CALL TRANSFORMATION zst_addressquality
SOURCE XML lw_xml
RESULT result = lo_addressquality.
Now, when debugging through the transformation code, it successfully notices all fields of the given lw_xml and appears to write them into the object lo_addressquality. But the object attributes stay empty afterwards.
When testing the serialization, I can access result which contains my object, but result-w_address (and all others) are empty.
While testing, I created a structure with completely identical names and types. With it, it worked as intended.
What am I missing? Is there anything else I have to watch out for when working with transformation into ABAP Objects?
_Edit: After changing to the XSLT, I can get until W_ADDRESS before my code throws an CX_XSLT_ABAP_CALL_ERROR. So, I'm still not able to access the object'S attributes properly. :|_
Objects can be serialized/deserialized only with an XSL transformation. It's not possible to do it with a simple transformation, dixit ABAP documentation:
ST programs are restricted to the transformation of elementary and structured ABAP data, along with internal tables. The transformation of reference variables and referenced objects is not currently supported.
The XSL transformation must convert the XML into ASXML, which in short corresponds to a structure like this:
<?xml ...?>
<asx:abap xmlns:asx="http://www.sap.com/abapxml" version="1.0">
<asx:values>
...
</asx:values>
<asx:heap>
...
</asx:heap>
</asx:abap>
The easiest way to understand what the ASXML should look like is to serialize your object reference using the identity transformation (it's an XSL transformation), and then adapt your transformation to produce the same kind of asXML:
CALL TRANSFORMATION id SOURCE anyRootName = yourObjectReference RESULT XML asXMLutf8xstring.
Example:
REPORT.
CLASS serialization_demo DEFINITION.
PUBLIC SECTION.
INTERFACES if_serializable_object.
DATA attribute TYPE i.
ENDCLASS.
START-OF-SELECTION.
DATA obj_ref TYPE REF TO serialization_demo.
DATA xstring TYPE xstring.
CREATE OBJECT obj_ref.
obj_ref->attribute = 5.
CALL TRANSFORMATION id " serialize
SOURCE root = obj_ref
RESULT XML xstring.
CLEAR obj_ref.
CALL TRANSFORMATION id " deserialize
SOURCE XML xstring
RESULT root = obj_ref.
ASXML (in the xstring variable):
<?xml version="1.0" encoding="utf-8"?>
<asx:abap version="1.0" xmlns:asx="http://www.sap.com/abapxml">
<asx:values>
<ROOT href="#o3"/>
</asx:values>
<asx:heap xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:abap="http://www.sap.com/abapxml/types/built-in" xmlns:cls="http://www.sap.com/abapxml/classes/global" xmlns:dic="http://www.sap.com/abapxml/types/dictionary">
<prg:SERIALIZATION_DEMO id="o3" xmlns:prg="http://www.sap.com/abapxml/classes/program/ZZSRO_TEST16I">
<local.SERIALIZATION_DEMO>
<ATTRIBUTE>5</ATTRIBUTE>
</local.SERIALIZATION_DEMO>
</prg:SERIALIZATION_DEMO>
</asx:heap>
</asx:abap>

XML Schema multiple import effect

While looking at XML schema examples, I have seen the following case (in xml schema test suite, microsoft schema schG1_a/b/c.xsd):
Conceptually, schema document A (target a) imports schema document B (target b) which in turn imports schema document C (target c).
My reading of the schema specs is that A must directly import C in order to refer to anything in C (import is not transitive). It does not. This is not an issue because A itself does not refer to anything in C or even in B. It defines just an element 'root' that is a sequence of 'any' from '##any' namespace with processContents 'strict'.
Now the problem is that the instance document schG1.xml is referring to the schema A only although it uses global elements defined in A, B and C as children of the 'root' element in A. Because processContents is 'strict' the schema A should be used to validate the instance elements (as children of 'root'). I understand that it can do it for the elements defined in A and B (directly imported in A) but I fail to understand how it can validate elements from C since they were never directly seen in A.
However the test is supposed to be valid. I am sure I must be missing something...
schG1_a.xsd:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="ns-a" xmlns="ns-a">
<xsd:import namespace="ns-b" schemaLocation="schG1_b.xsd"/>
<xsd:element name="e1" type="xsd:int"/>
<xsd:element name="root">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:any namespace="##any" processContents="strict"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
schG1_b.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="ns-b" xmlns="ns-b">
<xsd:import namespace="ns-c" schemaLocation="schG1_c.xsd" />
<xsd:element name="e1" type="xsd:boolean" />
</xsd:schema>
schG1_c.xsd:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="ns-c" xmlns="ns-c">
<xsd:element name="e1" type="xsd:string" />
</xsd:schema>
schG1.xml:
<a:root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="ns-a schG1_a.xsd"
xmlns:a="ns-a" xmlns:b="ns-b" xmlns:c="ns-c">
<a:e1>123</a:e1>
<b:e1>true</b:e1>
<c:e1>foo</c:e1>
</a:root>

jxpath not honoring JAXB's XmlElement name of xjc-generated classes

I use an XML Schema Definition and JAXB to generate Java classes with proper #XmlElement or #XmlRootElement annotations.
Since the schema has some deep nesting in it (not my choice), I'd rather use jxpath to access deeply buried classes using an XPath (rather than cumbersome daisy-chain of .getThat() and that != null).
The problem is that some of the XML element names contain dashes, e.g. foo-bar. When I try to access elements using org.apache.jxpath, I need to rewrite my XPath so that such names are camel-cased instead (fooBar) like the name of the actual Java objects. Is there any way to tell jxpath to find the elements using the XPath corresponding to the XML element names (instead of the camel-cased Bean names)?
I think it is related to this question, however in my case I don't actually case what kind of tricks and decorations are used on the auto-generated classes, as long as xjc can do it.
Here is a simple example to illustrate the issue.
First, a small XSD file:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="record">
<xs:complexType>
<xs:sequence>
<xs:element name="foo-bar" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Compile it...
xjc -p org.pd.jx example.xsd
Here is the xjc-generated Record.java class (minus comments):
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {"fooBar"})
#XmlRootElement(name = "record")
public class Record {
#XmlElement(name = "foo-bar", required = true)
protected String fooBar;
public String getFooBar() {return fooBar;}
public void setFooBar(String value) {this.fooBar = value;}
}
Then, trying to access the data via jxpath (in practice I have to deal with lots of deeply nested classes), one can see below that the correct XPath ("foo-bar") doesn't work, but a camel-cased version does.
Record record = new Record();
record.setFooBar("hello world");
JXPathContext context = JXPathContext.newContext(record);
context.setLenient(true);
String a = (String)context.getValue("foo-bar", String.class); // is null
String b = (String)context.getValue("fooBar", String.class); // "hello world"
I believe JXPath operates on an objects properties and not the XML elements they correspond to. I do not believe that JXPath parses any of the JAXB metadata so it wouldn't know the XML nodea you have mapped. What you are seeing appears to be the expected behaviour.

Core Data: does delete an entity remove all relationships of other entities to it?

Say if I have two entities: MySubscription and AllSubscription, MySubscription has a one to one relationship to AllSubscription, thus AllSubscription has a inverse relationship to MySubscription, say:
MySub AllSubs
a <---> A
B
c <---> C
D
e <---> E
if I delete a, does Core Data automatically set A.mysub to nil?
All depends on your choice of delete rule, which can be specified for each relationship. The rule you are describing is called "nullify".

Resources