What is the correct representation of a multi-level FHIR extension?
<extension url="http://example.com/DataElement/researchAuth">
<extension url="http://example.com/DataElement/researchAuth.type">
<valueCode value="local" />
</extension>
<extension url="http://example.com/DataElement/researchAuth.flag>
<valueBoolean value="true" />
</extension>
</extension>
-- OR --
<extension url="http://example.com/DataElement/researchAuth">
<extension url="http://example.com/DataElement/researchAuth#type">
<valueCode value="local" />
</extension>
<extension url="http://example.com/DataElement/researchAuth#flag>
<valueBoolean value="true" />
</extension>
</extension>
In the StructureDefinition, should the URL for the sub-extensions be fully qualified (url: "http://example.com/DataElement/researchAuth#type") or just the name ("type") as here: http://hl7-fhir.github.io/extension-goal-relationship.html
Finally, is there an standard linkage between StructureDefinition.name and the sub-extension URL? I.e. the part after the # (type in http://example.com/DataElement/researchAuth#type) should match the name in the structure defition of the extension:
<StructureDefinition>
...
<element>
<path value="Extension" />
<name value="researchAuth" />
</element>
<element>
<path value="Extension.extension" />
<name value="researchAuth.type" />
</element>
...
</StructureDefinition>
Otherwise, how does one determine what the post # element is??
James's example adds to my confusion:
http://jamesagnew.github.io/hapi-fhir/doc_extensions.html
In the sub-extensions section, the "parent" is "http://example.com#parent" and the children are "http://example.com#ChildOne" and "http://example.com#ChildTwo" respectively.
I would expect only "http://example.com" for the parent extension (no # as it's the base extension defined at the URL). OR http://example.com#parent.ChildOne for the sub-extensions.
In DSTU 1, it would be the first approach. In DSTU 2, it would be this:
<extension url="http://example.com/DataElement/researchAuth">
<extension url="type">
<valueCode value="local" />
</extension>
<extension url="flag>
<valueBoolean value="true" />
</extension>
</extension>
That only holds for children of complex extensions. If you want to include an extension defined elsewhere inside another extension, you need to use the full URL.
Related
As I mentioned in the title I need to do reverse engineering with a .msm file, this MSM file contains a class table and a progId table and I can't find any simple code example of how to do it.
If I put class and progId in "File", I only get a new entry in the registry table. That someone could give me a simple example but with all the Wix?
Use Class and ProgId elements with their Advertise attributes set to yes.
The WiX Class doc says:
Set this value to "yes" in order to create a normal Class table row.
I used IsWiX and heat to generate this short POC. Heat originally authored the Class element as a child of the File element but that isn't allowed when setting Advertise to yes like Bob said to do. I used some random Windows OCX file because I don't author COM components these days.
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define ComponentRules="OneToOne"?>
<!-- SourceDir instructs IsWiX the location of the directory that contains files for this merge module -->
<?define SourceDir="..\Deploy"?>
<Module Id="MergeModule1" Language="1033" Version="1.0.0.0">
<Package Id="ae2940bf-2a96-409f-8828-43732e8eec3d" Manufacturer="MergeModule1" InstallerVersion="200" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="MergeRedirectFolder">
<Component Id="owc1342753EC14FB934098148748894FC8C" Guid="cb00efc4-e09b-8162-9ee7-2f0d2982bab0" >
<Class Id="{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}" Context="InprocServer32" Description="ScriptControl Object" ThreadingModel="apartment" Version="1.0" Programmable="yes" Control="yes" Advertise="yes">
<ProgId Id="MSScriptControl.ScriptControl.1" Description="ScriptControl Object">
<ProgId Id="MSScriptControl.ScriptControl" Description="ScriptControl Object" />
<ProgId Id="ScriptControl" Description="ScriptControl Object" />
</ProgId>
</Class>
<File Id="owf1342753EC14FB934098148748894FC8C" Source="$(var.SourceDir)\msscript.ocx" KeyPath="yes">
<TypeLib Id="{0E59F1D2-1FBE-11D0-8FF2-00A0D10038BC}" Description="Microsoft Script Control 1.0" HelpDirectory="MergeRedirectFolder" Language="0" MajorVersion="1" MinorVersion="0" Advertise="yes">
<Interface Id="{0E59F1D3-1FBE-11D0-8FF2-00A0D10038BC}" Name="IScriptControl" ProxyStubClassId32="{00020424-0000-0000-C000-000000000046}" />
<Interface Id="{70841C6F-067D-11D0-95D8-00A02463AB28}" Name="IScriptModuleCollection" ProxyStubClassId32="{00020424-0000-0000-C000-000000000046}" />
<Interface Id="{70841C70-067D-11D0-95D8-00A02463AB28}" Name="IScriptModule" ProxyStubClassId32="{00020424-0000-0000-C000-000000000046}" />
<Interface Id="{70841C71-067D-11D0-95D8-00A02463AB28}" Name="IScriptProcedureCollection" ProxyStubClassId32="{00020424-0000-0000-C000-000000000046}" />
<Interface Id="{70841C73-067D-11D0-95D8-00A02463AB28}" Name="IScriptProcedure" ProxyStubClassId32="{00020424-0000-0000-C000-000000000046}" />
<Interface Id="{70841C78-067D-11D0-95D8-00A02463AB28}" Name="IScriptError" ProxyStubClassId32="{00020424-0000-0000-C000-000000000046}" />
<Interface Id="{8B167D60-8605-11D0-ABCB-00A0C90FFFC0}" Name="DScriptControlSource" ProxyStubClassId32="{00020420-0000-0000-C000-000000000046}" />
</TypeLib>
</File>
<RegistryValue Root="HKCR" Key="CLSID\{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}\Implemented Categories\{0DE86A52-2BAA-11CF-A229-00AA003D7352}" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}\Implemented Categories\{0DE86A53-2BAA-11CF-A229-00AA003D7352}" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}\Implemented Categories\{0DE86A57-2BAA-11CF-A229-00AA003D7352}" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}\Implemented Categories\{40FC6ED4-2438-11CF-A3DB-080036F12502}" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}\Implemented Categories\{40FC6ED5-2438-11CF-A3DB-080036F12502}" Value="" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}\MiscStatus\1" Value="132499" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}\MiscStatus" Value="0" Type="string" Action="write" />
<RegistryValue Root="HKCR" Key="CLSID\{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}\ToolboxBitmap32" Value="[#owf1342753EC14FB934098148748894FC8C],102" Type="string" Action="write" />
</Component>
</Directory>
</Directory>
<ComponentGroupRef Id="Custom" />
</Module>
</Wix>
I am currently switching from static configs to using mod_xml_curl and have encountered a problem with setting up call groups.
Inside my dialplan (served dynamically, working as expected) I am bridging to a group:
<action application="bridge" data="${group_call(call-group#domain-a.com)}"/>
Freeswitch is making a request with section=directory&action=group_call to the web server, to which I respond with a chunk of the directory containing the group and all relevant users:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="freeswitch/xml">
<section name="directory">
<domain name="domain-a.com">
<params>
<param name="dial-string" value="{presence_id=${dialed_user}#${dialed_domain}}${sofia_contact(${dialed_user}#${dialed_domain})}" />
</params>
<variables>
<variable name="user_context" value="domain-a.com" />
</variables>
<group name="call-group">
<users>
<user id="john" number-alias="1000">
<params>
<param name="password" value="1234" />
<param name="vm-password" value="1000" />
</params>
<variables>
<variable name="toll_allow" value="domestic,international,local" />
<variable name="accountcode" value="1000" />
<variable name="outbound_caller_id_name" value="John at domain-a.com" />
<variable name="outbound_caller_id_number" value="1234567" />
</variables>
</user>
<user id="lucy" number-alias="1001">
<params>
<param name="password" value="1234" />
<param name="vm-password" value="1000" />
</params>
<variables>
<variable name="toll_allow" value="domestic,international,local" />
<variable name="accountcode" value="1001" />
<variable name="outbound_caller_id_name" value="Lucy" />
<variable name="outbound_caller_id_number" value="12345678" />
</variables>
</user>
</users>
</group>
</domain>
</section>
</document>
However, group_call() seems to fail and in the logs I get ``:
2016-02-24 10:42:14.249534 [DEBUG] mod_dptools.c:1498 SET sofia/internal/michael#domain-a.com [call_timeout]=[15]
2016-02-24 10:42:14.529107 [CONSOLE] mod_xml_curl.c:323 XML response is in /tmp/2f772a8a-4c3a-46f2-834f-b9ba2c735feb.tmp.xml
EXECUTE sofia/internal/michael#domain-a.com bridge(error/NO_ROUTE_DESTINATION)
Perhaps anyone has experience setting up group calls with mod_xml_curl and could explain what exactly Freeswitch is expecting in the response?
After a little gnashing of teeth, I got this working. The clue was here underneath the group_call description:
Please note: If you need to have outgoing user variables set in leg B,
make sure you don't have dial-string and group-dial-string in your
domain or dialed group variables list; instead set dial-string or
group-dial-string in the default group of the user. This way
group_call will return user/101 and user/ would set all your user
variables to the leg B channel.
So, when you receive an action of type group_call, move the dial-string param to the group level, so instead of
<domain name="domain-a.com">
<params>
<param name="dial-string" value="{presence_id=${dialed_user}#${dialed_domain}}${sofia_contact(${dialed_user}#${dialed_domain})}" />
</params>
<variables>
<variable name="user_context" value="domain-a.com" />
</variables>
<group name="call-group">
<users>
<user id="john" number-alias="1000">
...
send this
<domain name="domain-a.com">
<variables>
<variable name="user_context" value="domain-a.com" />
</variables>
<group name="call-group">
<params>
<param name="dial-string" value="{presence_id=${dialed_user}#${dialed_domain}}${sofia_contact(${dialed_user}#${dialed_domain})}" />
</params>
<users>
<user id="john" number-alias="1000">
...
After I made that change, everything was hunky dory. Cheers!
It's related to your dialplan.It's not generated perfectly. just check the domain-a.com context in the dialplan.
Does a FHIR extension always have to be defined in its own StructureDefinition before it can be used in a resource profile?
Or can its definition exist solely within the StructureDefinition of a profiled resource?
E.g.
<StructureDefinition xmlns="http://hl7.org/fhir">
<base value="http://hl7.org/fhir/StructureDefinition/Order" />
<name value="Order" />
...
<differential>
<element>
<path value="Order.extension" />
<name value="type" />
<label value="Type" />
<short value="BookAppointment | TelephonePatient | PatientNote | Note | Other" />
<definition value="Order type" />
<min value="1" />
<max value="1" />
<type>
<code value="code" />
</type>
<binding>
<strength value="required" />
<valueSetReference>
<reference value="http://test.org/fhir/ValueSet/task-type" />
</valueSetReference>
</binding>
</element>
...
Is the above valid?
No, that's not valid - because Order.extension can't have a type of "code". You could, in theory, slice extension and constrain the value[x] type to be valueCode with the specified properties. You'd also have to constrain the URL to a specified fixed value. The tricky part is that the URL you indicate as the fixed value is supposed to resolve to a StructureDefinition that defines the extension. So you really won't have saved yourself any work. Sending an instance where any immediate receiver can't discover the extension definition would make you automatically non-conformant.
So I have a valid xml file looking something like this:
<session xmlns="http://winscp.net/schema/session/1.0" name="mysession#10.0.0.22" start="2015-09-28T05:00:01.974Z">
<ls>
<destination value="/" />
<files>
<file>
<filename value="." />
<type value="d" />
<modification value="2015-09-28T05:44:14.000Z" />
<permissions value="rw-rw----" />
</file>
<file>
<filename value=".." />
<type value="d" />
<modification value="2015-09-28T05:44:14.000Z" />
<permissions value="rw-rw----" />
</file>
<file>
<filename value="55800379_150928_071525.zip" />
<type value="-" />
<size value="999124" />
<modification value="2015-09-28T05:36:08.000Z" />
<permissions value="rw-rw----" />
</file>
</files>
<result success="true" />
</ls>
<download>
<filename value="/55800379_150928_071525.zip" />
<destination value="C:\somefolder\55800478_150928_071525.zip" />
<result success="true" />
</download>
<rm>
<filename value="/55800379_150928_071525.zip" />
<result success="true" />
</rm>
</session>
I have added it as data in splunk and am trying to search using a query as below:
source="sample5.xml" host="dummy1" sourcetype="WinSCP XML" | xpath outfield=afield "//ls/files/file/filename/#value"
However, in this case the afield field is not getting populated (I was expecting the three values '.', '..' and '55800379_150928_071525.zip'). So I've got the error down to the xmlns in the session tag, when the first line looks like this (note: no xmlns attribute), the search does what I expect:
<session name="mysession#10.0.0.22" start="2015-09-28T05:00:01.974Z">
What do I have to put in my xpath to get the result I am looking for (I would very much prefer not to have to preprocess my logs to remove the XML namespace prior to import)?
Hmm, that looks like an unnamed namespace, which I can get at by registering a custom namespace prefix using my libxml2 wrapper program:
$ xpquery -n 'x:http://winscp.net/schema/session/1.0' '//x:ls/x:files/x:file/x:filename/#value' blah.xml
value="."
value=".."
value="55800379_150928_071525.zip"
$
Check whether your xpath program has support for the equivalent of libxml2 registerNs functionality?
Slicing of DataElements is defined once per path (only one set of discriminators per unique path). This works for built-in elements, but extension is (and must be) sliced only by url. As a result, it appears that further (more detailed) slicing of an extension isn't possible.
For example, consider an extension to Patient for research authorizations, ext url "http://example.com/DataElement/researchAuth".
It has an extension sub-element "authorizationType" (http://example.com/DataElement/researchAuth.type) of type Code. Here are two instances of this extension (one type "local", one "national").
<extension url="http://example.com/DataElement/researchAuth">
<extension url="http://example.com/DataElement/researchAuth.type">
<valueCode value="local" />
</extension>
<extension url="http://example.com/DataElement/researchAuth.flag>
<valueBoolean value="true" />
</extension>
</extension>
<extension url="http://example.com/DataElement/researchAuth">
<extension url="http://example.com/DataElement/researchAuth.type">
<valueCode value="national" />
</extension>
<extension url="http://example.com/DataElement/researchAuth.flag>
<valueBoolean value="false" />
</extension>
</extension>
The StructureDefinition for this would include (from Patient):
...snip...
<element>
<path value="Patient.extension" />
<slicing>
<discriminator value="url" />
</slicing>
</element>
I could add an element for researchAuthorization by using type.Profile to define the extension URL, but can I add a slicing as shown?
<element>
<path value="Patient.extension" />
<slicing>
<discriminator value="url" />
</slicing>
</element>
<element>
<path value="Patient.extension" />
<name value="researchAuthorization" />
<slicing>
<discriminator value="url" />
<discriminator value="extension["http://example.com/DataElement/researchAuth.type"].code" />
</slicing>
<type>
<profile value="http://example.com/DataElement/researchAuth" />
</type>
</element>
The second is now legal since it "satisfies" the first slicing via type.profile.#value being fixed?
It's possible for a set of sliced data to have multiple discriminators. Whether the existing tooling will support this for extensions is a different question. You may need to manually author your profile.