To start off, I have this XML file that contains recursive parent-child elements. Here is how the XML looks:
<VARS>
<VAR>
<id>var_starting_point</id>
<name>Starting Point</name>
<values>
<value>
<id>http://Environment1URL.com</id>
<name>Enviornment 1</name>
<sub_vars>
<VAR>
<id>var_env1_data</id>
<name>Env1 Data</name>
<values>
<value>
<name>Data1</name>
<sub_var>
<VAR>
<id>var_db</id>
<name>DB</name>
<values>
<values>place-holder 1</values>
</values>
</VAR>
</sub_var>
</value>
<value>
<name>Data2</name>
<sub_var>
<VAR>
<id>var_db</id>
<name>DB</name>
<values>
<values>place-holder 2</values>
</values>
</VAR>
</sub_var>
</value>
</values>
</VAR>
</sub_vars>
</value>
<value>
<id>http://Environment2URL.com</id>
<name>Enviornment 2</name>
<sub_vars>
<VAR>
<id>var_env2_data</id>
<name>Env2 Data</name>
<values>
<value>
<name>Data1</name>
<sub_var>
<VAR>
<id>var_db</id>
<name>DB</name>
<values>
<values>place-holder 1</values>
</values>
</VAR>
</sub_var>
</value>
<value>
<name>Data2</name>
<sub_var>
<VAR>
<id>var_db</id>
<name>DB</name>
<values>
<values>place-holder 2</values>
</values>
</VAR>
</sub_var>
</value>
</values>
</VAR>
</sub_vars>
</value>
</values>
</VAR>
<VAR>
<id>var_version_data1</id>
<name>Data1 Version</name>
<values>
<value>
<name>1.1.1</name>
</value>
</values>
</VAR>
<VAR>
<id>var_version_data2</id>
<name>Data2 Version</name>
<values>
<value>
<name>2.2.2</name>
</value>
</values>
</VAR>
</VARS>
I have a VARS element which contain 1 or more VAR element which has an id, name and
values array which contain 1 or more value elements.
The sub_var and id elements of the value element is optional, the name
element is not. The sub_var contains the exact same stuff as VARS
and so on.
Now I want to generate child combo boxes based on what was choosen in the
parent comboBox.
For example, if the user chooses "Enviornment 1" from the
Starting Point comboBox, than an Env1 Data combo box should spawn with
the Env1 values. Then if the user chooses "Data1", then the DB combo box
should be populated with "place-holder 1".
I've been working on this for hours and I'm not getting anywhere. I was able to get
1 layer working non recursivley, however multiple nested elements have been giving me a headache.
The way I do it now is, save the selected item to a temp variable, then on my selection changed event handler I clear my stack panel and recreate all the combo boxes based on what was selected last. However this does not seem to be working properly with multiple nested elements.
I'm just looking for ideas and how you would approach this problem.
First, I would deserialize your structure into a class that looked like this:
class XmlVar
{
public List<XmlVar> Children { get; set; }
public string ID { get; set; }
public string Name { get; set; }
}
Once you did this, you can add a method to XmlVar to create your ComboBox for that node. Something like this:
public ComboBox MakeNodeCombo()
{
ComboBox retval = new ComboBox();
if (Children != null)
{
foreach (XmlVar child in Children)
{
ComboBoxItem nextItem = new ComboBoxItem;
nextItem.Content = Name;
nextItem.Tag = child; // So we have an easy time choosing the child
retval.Add(nextItem);
}
}
return retval;
}
When you get a SelectedItem event, get the corresponding ComboBoxItem. It's Content is the Name, and its Tag is the child XmlVar node that you now want to target.
I would probably deserialize this to proper C# classes, that way you can define HierarchicalDataTemplates which can be implicitly applied via the DataType property. Then you should just need to create one such template and a root ContentControl or ItemsControl to which you can bind your root and it should generate everything as needed.
Related
When we have to use the same code base to work with Oracle or other MSSql databases, is there a way to tell how to choose the type of mapping inside entity classes? For oracle it uses sequences like
#Id
#GeneratedValue(generator="InvSeq")
#SequenceGenerator(name="InvSeq",sequenceName="INV_SEQ", allocationSize=5)
private long id;
and for MySQL it uses
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
Is there a way to configure this without duplicating entity classes?
Ok I figured this out. In Spring Boot there is a way we can override default persistence mappings that is there inside a persistence.xml file. We first need to create a bean in app config like this(entityManagerFactory name should be there since spring will look for it):
#Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factory =
new LocalContainerEntityManagerFactoryBean();
factory.setDataSource(springJpaDataSource());
factory.setPersistenceProviderClass(HibernatePersistenceProvider.class);
if(!db_url.contains("oracle"))// something that tells you it's not oracle
{
factory.setPersistenceXmlLocation("classpath:jpa/custom-persistance.xml");
}
else{
// this file will not contain any mapping files to override ID generation
factory.setPersistenceXmlLocation("classpath:jpa/custom-persistance-oracle.xml");
}
return factory;
}
Now add the file (custom-persistance.xml):
<persistence
xmlns="http://xmlns.jcp.org/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
version="2.1">
<persistence-unit name="persistenceUnit">
<provider>
org.hibernate.jpa.HibernatePersistenceProvider
</provider>
<mapping-file>
jpa/entity-mappings.xml
</mapping-file>
</persistence-unit>
For custom-persistance-oracle.xml file will be same without mapping-file xml tag. Then add the actual file having mappings:
<entity-mappings
xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence/orm"
version="2.1">
<package>com.example.pcakageto.classes</package>
<entity class="ClassA" access="FIELD">
<attributes>
<id name="id">
<generated-value strategy="IDENTITY"/>
</id>
</attributes>
</entity>
<entity class="ClassB" access="FIELD">
<attributes>
<id name="id">
<generated-value strategy="IDENTITY"/>
</id>
</attributes>
</entity>
Finally ID mappings in Java files should be using sequences as it normally would:
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_generator")
#SequenceGenerator(name="id_generator", sequenceName = "sequence_name", allocationSize=1)
private Integer id;
I am defining a list in the following way in my blueprint-bean.xml
<cm:default-properties>
<cm:property name="test-list">
<list>
<value type="java.lang.String"> "test 1" </value>
<value type ="java.lang.String"> "test 2." </value>
<value type ="java.lang.String"> "test 3." </value>
</list>
</cm:property>
...
And i have not found a way to successfully retrieve it as a list in my routebuilder class.
Which looks like the following:
public class TestRoute extends RouteBuilder {
#PropertyInject("testInt") int rate;
#PropertyInject("test-list") List<String> testlist;
...
I always get the exception:
No type converter available to convert from type: java.lang.String to the required type: java.util.List with value [ "test 1." , "test 2." , "test 3." ]
So the list seems to be converted to a String at some point and then cannot be converted back to a list at the point of injection.
Am i using the Annotation in a wrong way or is there another way to inject a list property into my JDSL route?
The annotation is working for all my other properties except for the List.
<multiRef id="id178" soapenc:root="0" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xsi:type="ns9:Map" xmlns:ns9="http://xml.apache.org/xml-soap" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/">
<key xsi:type="soapenc:string">templateContainerNames</key>
<value soapenc:arrayType="xsd:string[4]" xsi:type="soapenc:Array">
<value xsi:type="xsd:string">APM</value>
<value xsi:type="xsd:string">OPERATING_SYSTEM</value>
<value xsi:type="xsd:string">Unix_Virtual</value>
<value xsi:type="xsd:string">UNIX_HOST</value>
</value>
</item>
<key xsi:type="soapenc:string">Name</key>
<value xsi:type="soapenc:string">Unix_Remote_without_SSHKey</value>
</item>
</multiRef>
I have the sample xml file and I would like to get value of 'Name' by passing templateContainerNames array values: [APM,OPERATING_SYSTEM,Unix_Virtual,UNIX_HOST].
How can I do this?
I have got the solution myself. I found some clue on arrays somewhere and tried below query and it worked perfectly.
//value[value[1]='APM' and value[2]='OPERATING_SYSTEM' and value[3]='Unix_Virtual' and value[4]='UNIX_HOST']/../parent::*/item[key="Name"]/value
Thanks
Srinivas
I've an issue defining a query to get some data out of Cassandra in WSO2 DSS. The query (and the operation) itself is working but my problem is when I try to get a timestamp as a result.
I only get the date and the timezone (2017-01-11+0100) the time part is missing. I guess that this is somehow related on the mapping to dateTime xsdType that is not working correctly.
Did you already face this issue, and do you have a solution to get the timestamp?
Here is a query sample
<query id="getDataQuery" useConfig="CassandraDB">
<expression>SELECT ts,value FROM keyspace.ts_tp WHERE name = :name</expression>
<result element="result" rowName="data">
<element column="ts" name="ts" xsdType="dateTime"/>
<element column="value" name="value" xsdType="decimal"/>
</result>
<param name="name" paramType="SCALAR" sqlType="STRING"/>
</query>
Thanks
Seems to be an issue in dss dateTime mapping, I opened a Jira ticket #wso2 to be sure. In order to make my call return the right values I made the following (Warning painful solution :))
The query returns now the unix Timestamp in ms
<query id="getDataQuery" useConfig="CassandraDB">
<expression>SELECT unixTimestampOf(minTimeuuid(ts)) as dt,value FROM keyspace.ts_tp WHERE source = :source and name = :name and bucket = :bucket and ts >= :tsFrom and ts <= :tsTo</expression>
<result element="result" rowName="data">
<element column="dt" name="ts" xsdType="int"/>
<element column="value" name="value" xsdType="decimal"/>
</result>
<param name="source" paramType="SCALAR" sqlType="STRING"/>
<param name="name" paramType="SCALAR" sqlType="STRING"/>
<param name="bucket" paramType="SCALAR" sqlType="INTEGER"/>
<param name="tsFrom" paramType="SCALAR" sqlType="TIMESTAMP"/>
<param name="tsTo" paramType="SCALAR" sqlType="TIMESTAMP"/>
</query>
Once I get the result I apply an XSL transformation to compute the dates
<xsl:stylesheet exclude-result-prefixes="xsl soapenv" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="utf-8" indent="yes" method="xml" omit-xml-declaration="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dt">
<xsl:element name="ts">
<xsl:value-of select='xs:dateTime("1970-01-01T00:00:00") + . * xs:dayTimeDuration("PT0.001S")'/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
It needs to be tested with different time zones, and day light savings but it seems to be a working hack, waiting for the official fix.
I want to use Mirth to get data from XML file (CCD) and put its, in my SQL Server database.
So I have install Mirth connect administrator on my pc, then I have just created a new Channel with Source XML file, and to Destination my SQL server database. I have also selected table of my database, and automatically, Mirth have created this query:
INSERT INTO CLINICAL_DOC_Problems (Id, IdRoot, IdExtension, IdObservationRoot, IdObservationExtension, EffectiveTime, EffectiveTimeMin, EffectivTimeMax, CodeSystem, Code, CodeSystemStatus, CodeStatus, IdSection)
VALUES (, , , , , , , , , , , , )
Now the problem is this, the section (that I want insert in my database) of my CCD document (file .xml) have this structures:
<component>
<section>
<templateId root='2.16.840.1.113883.10.20.1.11'/> <!-- Problem section template -->
<code code="11450-4" codeSystem="2.16.840.1.113883.6.1"/>
<entry typeCode="DRIV">
<act classCode="ACT" moodCode="EVN">
<templateId root='2.16.840.1.113883.10.20.1.27'/> <!-- Problem act template -->
<id root="6a2fa88d-4174-4909-aece-db44b60a3abb"/>
<entryRelationship typeCode="SUBJ">
<observation classCode="OBS" moodCode="EVN">
<templateId root='2.16.840.1.113883.10.20.1.28'/> <!-- Problem observation template -->
<id root="d11275e7-67ae-11db-bd13-0800200c9a66"/>
<code code="ASSERTION" codeSystem="2.16.840.1.113883.5.4"/>
<effectiveTime><low value="1950"/></effectiveTime>
<value xsi:type="CD" code="195967001" codeSystem="2.16.840.1.113883.6.96" displayName="Asthma"/>
<entryRelationship typeCode="REFR">
<observation classCode="OBS" moodCode="EVN">
<templateId root='2.16.840.1.113883.10.20.1.50'/> <!-- Problem status observation template -->
<code code="33999-4" codeSystem="2.16.840.1.113883.6.1" displayName="Status"/>
<value xsi:type="CE" code="55561003" codeSystem="2.16.840.1.113883.6.96" displayName="Active"/>
</observation>
</entryRelationship>
</observation>
</entryRelationship>
</act>
</entry>
<entry typeCode="DRIV">
<act classCode="ACT" moodCode="EVN">
<templateId root='2.16.840.1.113883.10.20.1.27'/> <!-- Problem act template -->
<id root="ec8a6ff8-ed4b-4f7e-82c3-e98e58b45de7"/>
<entryRelationship typeCode="SUBJ">
<observation classCode="OBS" moodCode="EVN">
<templateId root='2.16.840.1.113883.10.20.1.28'/> <!-- Problem observation template -->
<id root="ab1791b0-5c71-11db-b0de-0800200c9a66"/>
<code code="ASSERTION" codeSystem="2.16.840.1.113883.5.4"/>
<value xsi:type="CD" code="233604007" codeSystem="2.16.840.1.113883.6.96" displayName="Pneumonia"/>
<entryRelationship typeCode="REFR">
<observation classCode="OBS" moodCode="EVN">
<templateId root='2.16.840.1.113883.10.20.1.50'/> <!-- Problem status observation template -->
<code code="33999-4" codeSystem="2.16.840.1.113883.6.1" displayName="Status"/>
<value xsi:type="CE" code="413322009" codeSystem="2.16.840.1.113883.6.96" displayName="Resolved"/>
</observation>
</entryRelationship>
</observation>
</entryRelationship>
</act>
</entry>
</section>
</component>
As you can see, there are two tag
entry typeCode="DRIV"
I want to insert in my database as many records as entry tag.
In this example, I should to insert in my database 2 records.
You could do something like the following in a JavaScript writer. I prefer the JavaScript writer over the Database Writer because you've got a lot more flexibility and can call all of the same native Mirth Java from the JavaScript.
If you pass your XML (from a File Reader, if I understand correctly...) from your source to your destination, set the destination type as a JavaScript writer, and then iterate through your objects like so:
var dbConn;
try {
dbConn = DatabaseConnectionFactory.createConnection(driver, address, username, password);
var xml = new XML(connectorMessage.getEncodedData());
for(var i = 0; i < xml.section.entry.length(); i++) {
if(xml.section.entry[i].#typeCode == 'DRIV') {
var myData = xml.section.entry[i].act;
var myQuery = '';
//do something with myVar to get a query...
dbConn.executeCachedQuery(myQuery);
}
}
} catch (ex) {
//handle any exceptions...
}
Iteration through XML is done using E4X: https://developer.mozilla.org/en-US/docs/Archive/Web/E4X_tutorial