Fo-dicom: How to add "empty, if unknown" integer string type 2 attribute - dicom

There is a tag which is of type 2 ("required, empty if unknown"), with value representation Integer String which I would like to leave empty. I have tried creating the attribute like so:
var attribute = new DicomIntegerString(DicomTag.SeriesNumber, string.Empty);
The storing of the file works. When I read the file again, the result of the following call returns null:
var result = dicomDataset.GetString(DicomTag.SeriesNumber); // <-- this is null
How can I set the element to be correctly "zero-length", or "empty, if unknown"?
Thanks.

As already mentioned in the comments, the code to set an empty string in the dataset is correct:
dataset.AddOrUpdate(new DicomIntegerString(DicomTag.SeriesNumber, string.Empty));
Note that you could also write a null value:
dataset.AddOrUpdate(new DicomIntegerString(DicomTag.SeriesNumber, (string)null));
Writing out the dataset will create an empty tag for SeriesNumber in exactly the same way in both cases, as both cases are equivalent in DICOM.
The code to read the tag back is also correct, and the fact that it returns null is due to this equivalence, which creates an ambiguity in the interpretation of an empty string tag in DICOM. As the number of values in a DICOM string tag is defined only by the string itself (and the number of backslashes it contains), there is no difference between a tag with no values (which usually is represented by a null value), and a tag with an empty string (which would be represented by a "" value). For consistence with other tags it makes sense to return null for a tag with VM 0 - for non-string VRs there is no ambiguity here, as the length of a value is defined. For string values it could also make sense to return an empty string instead - both approaches have pros and cons, so in the end it is a design decision of the library creators.
In fo-dicom, it is probably best to handle both cases (e.g. using something like string.IsNullOrEmpty). If you read the value from a file dataset, you always get null, but if you are writing an empty string to a tag in a dataset (first version shown above) and read it back, you will get the same empty string back.
As an aside: in pydicom (the common Python DICOM library) there was a discussion about this same design decision, and in the end a configuration entry was added that defines the behavior (e.g. return None or an empty string for such values).

Related

BizTalk 2010 parsing data within a string using only functoids

I am getting data in an inbound EDI file and one of the fields has measurements which I need to parse out of a single string. An example of this field is:
11.75x21.25x41.37x
I need to take all the values in front of the first X and push them to a destination field (say length), all the values between the 1st and 2nd X and push those to the destination field "width", and all the data between the 2nd and 3rd x and send that to the destination field "height".
Here's the challenge: can this be done using only functoids, no C# code? It is preferred because managing C# code should the client modify the format of the data between the X's (as they may well do) is easier to maintain if no code needs to be modified, vetted, stored and pushed to the server.
I tried using the string trimming and string exact functoids but it didn't work; there is no fixed number of digits between the X's and I cannot even be guaranteed there will always be decimals--another feature I originally wanted to key on. The only constant will be the X's.
Yes, you can do this using only functoids - but if you artificially stipulate that you not use C# (in a scripting functoid), then you make life much harder and don't solve the problem you think you're solving.
You'd have to use multiple String Find functoids to pick out the various pieces of the field - and this will work only assuming you know the number of xes that can occur ahead of time. Have the first input be the node, and the second input be x for string find, then connect that to a String Extract functoid. To get the second one you'll have to stack the String Find functoids, and life gets ugly. You're effectively trying to build out recursion manually using BizTalk functoids.
The bottom line is: no matter how you achieve this, if the client changes the format of the string you'll have to change the parsing logic to get it out. That logic will be vastly easier to manage by writing a custom functoid (or just an external Assembly method) which, at its core, does this:
public string StringPartAt(string s, string sep, int idx)
{
string[] splits = s.Split(sep[0]);
if (splits.Length > idx)
return splits[idx];
return "";
}
This will be much easier to maintain and understand. You could set that in a Scripting functoid and pass in your node, x, and a zero-based index to get your string out, and just use that for as many times as you need to split things up. You could even add error handling/logging ("Warning: Tried to extract value that was out of range of input" in the EventLog might be appreciated). If you're worried about the Client's facility with C#, you could also write this in VB or JavaScript. Even in custom XSLT it would be easier (use substring-before() a few times over, or build a recursive template), it'll be better than trying to hack together a bunch of stock functoids to complete this task.
Pictures of how this works (using inline C# to demo - you'd probably want this in an external assembly or a custom functoid for reusability; note that char can't actually be used, you have to use string as shown above):
It turns out we had to use a different script for each value (height, width and length) to extract those values from the string. Putting each in the scripting functiod using the following C# scripts worked for my map:
Length:
public decimal getLength(string weights)
{
string[] wgt;
wgt = weights.Split('x');
decimal len = Convert.ToDecimal(wgt[0]);
decimal wid = Convert.ToDecimal(wgt[1]);
decimal hgt = Convert.ToDecimal(wgt[2]);
return len;
}
Width:
public decimal getWidth(string weights)
{
string[] wgt;
wgt = weights.Split('x');
decimal len = Convert.ToDecimal(wgt[0]);
decimal wid = Convert.ToDecimal(wgt[1]);
decimal hgt = Convert.ToDecimal(wgt[2]);
return wid;
}
Height:
public decimal getHeight(string weights)
{
string[] wgt;
wgt = weights.Split('x');
decimal len = Convert.ToDecimal(wgt[0]);
decimal wid = Convert.ToDecimal(wgt[1]);
decimal hgt = Convert.ToDecimal(wgt[2]);
return hgt;
}

What does an empty input's value when using POST in asp?

I am using asp (JScript as my language) and working with getting data from a form that is sent using POST.
Specifically, I have a text input and I want to check if it was left empty. When leaving it empty, and including Response.Write(Request.form('opt2Dur')) in the called page, nothing prints (doesn't print null or undefined).
My thought was that it was just an empty string so I included this: Response.Write(Request.form('opt2Dur') === ''), however this printed false.
It will print true if I use Response.Write(Request.form('opt2Dur') == '') (== not ===). What is the true value that I can check against using ===? Or, in this case will it be sufficient to check with just ==?
Thanks for any help.
In scripting languages with "flexible" types and default values it's very easy to get confused with actual data types.
The actual type of each Request item (both QueryString and Form, it doesn't matter) is some sort of Array as it also supports more than one form element with the same name submitted to the ASP handler. It's mentioned in the documentation as well:
The Form collection is indexed by the names of the parameters in the request body. The value of Request.Form(element) is an array of all the values of element that occur in the request body.
Since the === also take into account type, it will return false in your case as array is not a string.
I wasn't able to find the exact actual type and reproduce it with local variable (it's not any plain array) so if you are keen on using the strict comparison operator, check the Count:
Response.Write(Request.Form('opt2Dur').Count === 0);

Switch of string in Workflow Foundation issue

I've encountered a very weird problem with WF4: when I use Switch activity and make the decision on the value of a string variable somehow WF treats argument to the Switch as a string, not the name of the variable. And consequently I get incorrect results. Steps to repro:
- create new WF
- add Sequence
- add Switch of String to the Sequence
- add a new string variable named, for instance, [testText] and set its default value to "test"
- set argument of the switch to testText
- create a case in the switch for "test" string and show msgbox on it
- create another case, let it be default case which shows another msgbox with "default" text
- run
And suddenly here we get a message box with "default" text, not the one for the testText case
You need to use the value of test without the quotes. The cases contain a literal value, not an expression. And yes I find this confusing as well.

How to pass "Null" (a real surname!) to a SOAP web service in ActionScript 3

We have an employee whose surname is Null. Our employee lookup application is killed when that last name is used as the search term (which happens to be quite often now). The error received (thanks Fiddler!) is:
<soapenv:Fault>
<faultcode>soapenv:Server.userException</faultcode>
<faultstring>coldfusion.xml.rpc.CFCInvocationException: [coldfusion.runtime.MissingArgumentException : The SEARCHSTRING parameter to the getFacultyNames function is required but was not passed in.]</faultstring>
Cute, huh?
The parameter type is string.
I am using:
WSDL (SOAP)
Flex 3.5
ActionScript 3
ColdFusion 8
Note that the error does not occur when calling the webservice as an object from a ColdFusion page.
Tracking it down
At first I thought this was a coercion bug where null was getting coerced to "null" and a test of "null" == null was passing. It's not. I was close, but so very, very wrong. Sorry about that!
I've since done lots of fiddling on wonderfl.net and tracing through the code in mx.rpc.xml.*. At line 1795 of XMLEncoder (in the 3.5 source), in setValue, all of the XMLEncoding boils down to
currentChild.appendChild(xmlSpecialCharsFilter(Object(value)));
which is essentially the same as:
currentChild.appendChild("null");
This code, according to my original fiddle, returns an empty XML element. But why?
Cause
According to commenter Justin Mclean on bug report FLEX-33664, the following is the culprit (see last two tests in my fiddle which verify this):
var thisIsNotNull:XML = <root>null</root>;
if(thisIsNotNull == null){
// always branches here, as (thisIsNotNull == null) strangely returns true
// despite the fact that thisIsNotNull is a valid instance of type XML
}
When currentChild.appendChild is passed the string "null", it first converts it to a root XML element with text null, and then tests that element against the null literal. This is a weak equality test, so either the XML containing null is coerced to the null type, or the null type is coerced to a root xml element containing the string "null", and the test passes where it arguably should fail. One fix might be to always use strict equality tests when checking XML (or anything, really) for "nullness."
Solution
The only reasonable workaround I can think of, short of fixing this bug in every damn version of ActionScript, is to test fields for "null" and escape them as CDATA values.
CDATA values are the most appropriate way to mutate an entire text value that would otherwise cause encoding/decoding problems. Hex encoding, for instance, is meant for individual characters. CDATA values are preferred when you're escaping the entire text of an element. The biggest reason for this is that it maintains human readability.
On the xkcd note, the Bobby Tables website has good advice for avoiding the improper interpretation of user data (in this case, the string "Null") in SQL queries in various languages, including ColdFusion.
It is not clear from the question that this is the source of the problem, and given the solution noted in a comment to the first answer (embedding the parameters in a structure) it seems likely that it was something else.
The problem could be in Flex's SOAP encoder. Try extending the SOAP encoder in your Flex application and debug the program to see how the null value is handled.
My guess is, it's passed as NaN (Not a Number). This will mess up the SOAP message unmarshalling process sometime (most notably in the JBoss 5 server...). I remember extending the SOAP encoder and performing an explicit check on how NaN is handled.
#doc_180 had the right concept, except he is focused on numbers, whereas the original poster had issues with strings.
The solution is to change the mx.rpc.xml.XMLEncoder file. This is line 121:
if (content != null)
result += content;
(I looked at Flex 4.5.1 SDK; line numbers may differ in other versions.)
Basically, the validation fails because 'content is null' and therefore your argument is not added to the outgoing SOAP Packet; thus causing the missing parameter error.
You have to extend this class to remove the validation. Then there is a big snowball up the chain, modifying SOAPEncoder to use your modified XMLEncoder, and then modifying Operation to use your modified SOAPEncoder, and then moidfying WebService to use your alternate Operation class.
I spent a few hours on it, but I need to move on. It'll probably take a day or two.
You may be able to just fix the XMLEncoder line and do some monkey patching to use your own class.
I'll also add that if you switch to using RemoteObject/AMF with ColdFusion, the null is passed without problems.
11/16/2013 update:
I have one more recent addition to my last comment about RemoteObject/AMF. If you are using ColdFusion 10; then properties with a null value on an object are removed from the server-side object. So, you have to check for the properties existence before accessing it or you will get a runtime error.
Check like this:
<cfif (structKeyExists(arguments.myObject,'propertyName')>
<!--- no property code --->
<cfelse>
<!--- handle property normally --->
</cfif>
This is a change in behavior from ColdFusion 9; where the null properties would turn into empty strings.
Edit 12/6/2013
Since there was a question about how nulls are treated, here is a quick sample application to demonstrate how a string "null" will relate to the reserved word null.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" initialize="application1_initializeHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function application1_initializeHandler(event:FlexEvent):void
{
var s :String = "null";
if(s != null){
trace('null string is not equal to null reserved word using the != condition');
} else {
trace('null string is equal to null reserved word using the != condition');
}
if(s == null){
trace('null string is equal to null reserved word using the == condition');
} else {
trace('null string is not equal to null reserved word using the == condition');
}
if(s === null){
trace('null string is equal to null reserved word using the === condition');
} else {
trace('null string is not equal to null reserved word using the === condition');
}
}
]]>
</fx:Script>
<fx:Declarations>
<!-- Place non-visual elements (e.g., services, value objects) here -->
</fx:Declarations>
</s:Application>
The trace output is:
null string is not equal to null reserved word using the != condition
null string is not equal to null reserved word using the == condition
null string is not equal to null reserved word using the === condition
Translate all characters into their hex-entity equivalents. In this case, Null would be converted into &#4E;K&#6C;&#6C;
Stringifying a null value in ActionScript will give the string "NULL". My suspicion is that someone has decided that it is, therefore, a good idea to decode the string "NULL" as null, causing the breakage you see here -- probably because they were passing in null objects and getting strings in the database, when they didn't want that (so be sure to check for that kind of bug, too).
As a hack, you could consider having a special handling on the client side, converting 'Null' string to something that will never occur, for example, XXNULLXX and converting back on the server.
It is not pretty, but it may solve the issue for such a boundary case.
Well, I guess that Flex' implementation of the SOAP Encoder seems to serialize null values incorrectly. Serializing them as a String Null doesn't seem to be a good solution. The formally correct version seems to be to pass a null value as:
<childtag2 xsi:nil="true" />
So the value of "Null" would be nothing else than a valid string, which is exactly what you are looking for.
I guess getting this fixed in Apache Flex shouldn't be that hard to get done. I would recommend opening a Jira issue or to contact the guys of the apache-flex mailinglist. However this would only fix the client side. I can't say if ColdFusion will be able to work with null values encoded this way.
See also Radu Cotescu's blog post How to send null values in soapUI requests.
It's a kludge, but assuming there's a minimum length for SEARCHSTRING, for example 2 characters, substring the SEARCHSTRING parameter at the second character and pass it as two parameters instead: SEARCHSTRING1 ("Nu") and SEARCHSTRING2 ("ll"). Concatenate them back together when executing the query to the database.

Test if the user typed email format ASP.NET (VB)

I have a TextBox, and I want to force the user to type an email format in this field like (example#mail.com) ?
I don't want to use FilteredTextBoxExtender or the RegularExpressionValidator.
I want to do it manualy.
Use the MailAddress class of System.Net.Mail. If what you pass into it is not a valid email address it will fail.
Example:
How do I validate email address formatting with the .NET Framework?
You are really going to reinvent the wheel.
But if it is your wish, you have to use string manipulation functions built in to the String object.
First do a check whether there is a in # symbol in the text.
Use String.Contains to check that.
Or you can use String.IndexOf to check whether the # symbol is present, and if present which index is it present. (considering the string as an array of characters)
And then check whether there are any (and how many) characters present before the # symbol.
If the symbol # symbol was in the 4th index, then you know there are 3 characters before etc.
There's plethora of functions for the String object. You may have to use Length function and String.SubString to retrieve parts of the string.
Get the indexes of the # symbol and the . symbol and check whether there are at least 3 characters in between.
I really cant seem to think of all the possibilities but first list down all the possibilities and check them one by one.
You can also use the Contains method to check whether illegal characters are present :)
EDIT: String.LastIndexOf will return the last index where a specified character was found ;)
And you count and check whether the # symbol was found more than once etc
String.IndexOfAny(Char[])
String.IndexOfAny Method (Char[], Int32)
String.IndexOfAny Method (Char[], Int32, Int32)
This is the best way I found on internet.
Regex.IsMatch(YourStringEmail, "^(?("")("".+?""#)|(([0-9a-zA-Z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-zA-Z])#))" + _
"(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6}))$")
Thank you.

Resources