BIRT: Number type (formats) hell - java

Birt supports 3 number/digits types (e.g. for output columns in dataset):
Integer
Decimal
Float
At the same time, BIRT has the only 1 (yes! ONE!!!) css build-in format for numbers. That means if you have, for instance int (days) and decimal (amounts) you can't use build-in css style for them (you have define own and apply them on each item).
Go further. You call Java class from BIRT and pass to it so called Integer value. What you get at Java? Correct Double. At it's no way to now at that level that originally we have Integer value.
Of course in some cases you could try to guess data type based on a value.
E.g.
public Object formatFromBirt(Object pObject){
if (pObject == null) return null;
...
if (pObject instanceof Double) {
// workaround for int as double (e.g. days in arrear in total)
LWDecimal dec = new LWDecimal((Double)pObject);
if (dec.getScale() == 0){
pObject = dec.getJavaDecimal().toBigInteger();
}
}
return formatObject(pObject);
}
My BIG Question is - guys, how you handle all that hecking mess in BIRT number type system?

In BIRT API, they have this property definitions.
In general, if you are going to check the source code, in every "property" or "column" or "field" or whatever you call that object as long as it has properties that include its data type, you will notice that one of this object field is the string name of the data type. So it seems that the API verifies the selected data type by this string field.
For example, if you create a Output Column in DataSet and selected decimal as its data type,
the Display name in the drop down is actually in CamelCase which is "Decimal", but the XML name is "decimal".Doing this programmatically, you could try
resultSetColumn.setDataType("Decimal");
So in this same way you can verify its exact type programmatically.
Below is the list of common data type for a DataSet column.
http://www.eclipse.org/birt/ref/rom/structs/ResultSetColumn.html#Property-dataType
UPDATE:
You could use DesignChoiceConstant's static constants, it includes the datatype available to BIRT.It also includes property names and values that you could use to other BIRT APIs such as css,labels, list of allowed values, etc.

Related

Parsing a string into different variable types

Relatively new to programming here so I apologize if this is rather basic.
I am trying to convert string lines into actual variables of different types.
My input is a file in the following format:
double d1, d2 = 3.14, d3;
int a, b = 17, c, g;
global int gInt = 1;
final int fInt = 2;
String s1, s2 = "Still with me?", s3;
These lines are all strings at this point. I wish to extract the variables from the strings and receive the actual variables so I can use and manipulate them.
So far I've tried using regex but I'm stumbling here. Would love some direction as to how this is possible.
I thought of making a general type format for example:
public class IntType{
boolean finalFlag;
boolean globalFlag;
String variableName;
IntType(String variableName, boolean finalFlag, boolean globalFlag){
this.finalflag = finalFlag;
this.globalFlag = globalFlag;
this.variableName = variableName;
}
}
Creating a new wrapper for each of the variable types.
By using and manipulating I would like to then compare between the wrappers I've created and check for duplicate declarations etc'.
But I don't know if I'm on the right path.
Note: Disregard bad format (i.e. no ";" at the end and so on)
While others said that this is not possible, it actually is. However it goes somewhat deep into Java. Just search for java dynamic classloading. For example here:
Method to dynamically load java class files
It allows you do dynamically load a java file at runtime. However your current input does not look like a java file but it can easily be converted to one by wrapping it with a small wrapper class like:
public class CodeWrapper() {
// Insert code from file here
}
You can do this with easy file or text manipulations before loading the ressource as class.
After you have loaded the class you can access its variables via reflection, for example by
Field[] fields = myClassObject.getClass().getFields();
This allows you to access the visibility modifier, the type of the variable, the name, the content and more.
Of course this approach presumes that your code actually is valid java code.
If it is not and you are trying to confirm if it is, you can try to load it. If it fails, it was non-valid.
I have no experience with Java, but as far as my knowledge serves me, it is not possible to actually create variables using a file in any language. You'll want to create some sort of list object which can hold a variable amount of items of a certain type. Then you can read the values from a file, parse them to the type you want it to be, and then save it to the list of the corresponding type.
EDIT:
If I were you, I would change my file layout if possible. It would then look something like this:
1 2 3 4 //1 int, 2 floats, 3 booleans and 4 strings
53
3.14
2.8272
true
false
false
#etc.
In pseudo code, you would then read it as follows:
string[] input = file.Readline().split(' '); // Read the first line and split on the space character
int[] integers = new int[int.Parse(input[0])] // initialise an array with specefied elements
// Make an array for floats and booleans and strings the same way
while(not file.eof) // While you have not reached the end of the file
{
integers.insert(int.Parse(file.ReadLine())) // parse your values according to the size which was given on the first line of the file
}
If you can not change the file layout, then you'll have to do some smart string splitting to extract the values from the file and then create some sort of dynamic array which resizes as you add more values to it.
MORE EDITS:
Based on your comment:
You'll want to split on the '=' character first. From the first half of the split, you'll want to search for a type and from the second half, you can split again on the ',' to find all the values.

How to distinguish long and double-values when deserializing with moshi?

My goal is to synchronize abitrary rows of data by using the JSON-Format.
As I do not know the exact scheme for the rows (it is a general sync method), my datamodel apparently has to rely on "Object". So in Java I will have an array of Map<String,Object> to be synchronized with the server.
Translating such a row into JSON would give something like
{{"string":"stringvalue"},{"double1":1234.567},{"double2":1234.0},{"long":1234}}
so far, so good - no problem with moshi - everything works as expected.
Now the Problem: When I try to deserialize that JSON with moshi, I get back a double-value for the "long" member. Moshi converts all numbers to Doubles. But unfortunately not all numbers can be safely converted to doubles. Very big integers (aka longs) have a problem with the limited precision of doubles. And rounding-effects also might exist.
I opened an issue with moshi, but unfortunately that was closed. Maybe I wasn't clear enough. (Issue 192)
JSON has no concept of integer - only numbers and Strings. But the subtle detail from "double2" from the example above might lead to a solution for my problem:
If a number does not contain a decimal-point, it is an integer and should be converted to a long.
As longs can not be losslessly converted to doubles, I need a method to intercept the parser before the value is converted to double. But how to do that?
Moshi has this handy concept of JsonAdapters - but unfortunately I currently do not see how I can use them in this case:
The input-type of such an JsonAdapter would have to be Object because I can not cast a generated double to long. So I have to intercept the parser before he converts any value.
But how to return more than one type from there? (I would have to return String, Double or Long from there - or if I can limit the inputs to only numbers I would at least have to return Longs or Doubles.)
(My backend is written in PHP and automatically produces the desired output: Integers are written without a decimal-point.)
I am afraid it's not possible without changing Moshi source code. The JSON string source passes through JsonReader which converts all numbers to double. I could not find a way how to alter this behavior since all subclasses are package-protected.

why do i have to use Integer.parseInt?

I am new to Java so forgive me if this is a silly question.
First I did the following (this is a section from my code):
public static void team()
{
int score = JOptionPane.showInputDialog("Enter the team score...");
calculate(score);
}
But I kept getting an error saying: "Incompatible types string cannot be converted to int".
So I thought I may need to use parsing. I did the following and it worked:
public static void team()
{
int myScore;
String score = JOptionPane.showInputDialog("Enter the team score...");
myScore = Integer.parseInt(score);
calculate(myScore);
}
I would like to know why there is a need for me to parse the variable "score"? In the first piece of code, I declared the variable score as an integer, so would it not store the input which I expect to be an Integer in the variable score which is then passed into the method calculate. I understand that parsing is when you convert a String into an Integer. However in this case, I do not expect the user to input a string so why is there a need for parsing?
The simple reason is: because JOptionPane.showInputDialog() returns a String, regardless of what you actually want the user to input.
There's no mechanism in Java to do automatic conversion based on the type of your destination variable myScore (though some other languages can do this, e.g. implicit conversions in Scala).
You could (in principle) create a custom dialog that returns an int , e.g. by getting the user to choose from a pulldown list of numbers, and then no parsing would be needed. But otherwise, you have to do parsing explicitly.
The JOptionPane.showInputDialog("Enter the team score..."); returns a String which you tried to store in a int. That is why you are getting the "incompatible types".
See Javadocs for more information.
Because a string is stored differently than an integer. Integers are stored in binary, while as a String is a collection of characters.
Example:
The number 14 would be stored as 1110 in Binary. However, as a String, it's stored as 00110001 00110100
Take a look at this http://www.roubaixinteractive.com/PlayGround/Binary_Conversion/The_Characters.asp
Integer.parseInt() basically does the dirty work for you, by looking up the characters in a lookup table, and as long as they correlate with proper integer values, it coverts it over to binary form, to be stored in an integer.

Apache Cayenne - I cannot find code defining the constants for Token.kind field

I'm using Cayenne to parse SQL conditions, through org.apache.cayenne.exp.parser.ExpressionParser, which produces a series of org.apache.cayenne.exp.parser.Tokens, and I want to determine the type of each Token (like identifier, equal sign, number, string etc.).
The token type is definitely identified by the ExpressionParser, and it seems to me that it is stored in the int field Token.kind. The values that this field shows in my parsing tests are definitely consistent (for ex. = is always 5, literal strings are always 42, and operators are always 2 etc.).
My problem is just that I cannot find the Java class containing the constants to compare Token.kind values with.
The Javadoc for field Token.kind says:
An integer that describes the kind of this token. This numbering
system is determined by JavaCCParser, and a table of these numbers is
stored in the file ...Constants.java.
It does not specify the full name of the file, so I downloaded JavaCCParser and I checked several *Constants.* files found in javacc-5.0src.zip, javacc-6.0.zip, the two javacc.jar contained in those two zip, and cayenne-3.0.2-src.tar.gz.
None of the classes I found there seems to me to have constants that consistently match the values I see in my tests.
The closest I was able to get to that was with class org.apache.cayenne.exp.parser.ExpressionParserConstants which for ex. contains int PROPERTY_PATH = 34 and int SINGLE_QUOTED_STRING = 42 which definitely match the actual tokens of my test expressions, but other tokens have no corresponding constant in that class, for ex. the = sign (kind = 5) and the and operator (kind = 2).
So my question is if anyone knows in which Java class are those constants defined.
First I should mention that ExpressionParser is designed to parse very specific format of Cayenne expressions. It certainly can not be used to parse SQL. So you might be looking in the wrong direction.
Parser itself is generated by JavaCC based on this grammar file. Tokens for the parser are formally defined in the bottom of this file, and are very specific to the task at hand.

What is the best approach to parse a String type to other numeric types available in Java?

Let's consider the following code snippet in Java. There are some of possible approaches (that I know) to parse a String value to other numeric types (Let's say for the sake of simplicity, it is an Integer, a wrapper type in Java).
package parsing;
final public class Parsing
{
public static void main(String[] args)
{
String s="100";
Integer temp=new Integer(s);
System.out.print("\ntemp = "+temp);
temp=Integer.parseInt(s);
System.out.print("\ntemp = "+temp);
temp=Integer.valueOf(s).intValue();
System.out.print("\ntemp = "+temp);
temp=Integer.getInteger(s);
System.out.print("\ntemp = "+temp);
}
}
In all the cases except the last one, returns the value 100 after converting it into an Integer. Which one is the best approach to parse a String value to other numeric types available in Java? The last case returns NULL even if the String object s already contains a parsable value. Why?
Calling Integer.getInteger("42") attempts to fetch the value of the system property whose name is "42". Unless you really do have a system property with that name, it will return null.
Here is the Java 7 javadoc if you want more details.
Yes, the name of the method is misleading, and its utility is questionable.
FWIW, I'd use Integer.parseInt(String) if I required an int result and Integer.valueOf(String) if I required an Integer. I'd only use new Integer(String) if I required the object to be a new Integer and not one that might be shared.
(The reasoning is the same as for new Integer(int) versus Integer.valueOf(int). Again, read the javadocs for a more complete explanation.)
temp=Integer.parseInt(s);
unlike the other it just calculate a int, not a Integer. (this is not a big advantage though)
The last case returns NULL even if the String object s already contains a parsable value. Why?
It's not doing what you think it's doing:
public static Integer getInteger(String nm)
Determines the integer value of the system property with the specified name.
See API Doc.
Also see the doc for other related methods, they do different things.
new Integer(s); //you are creating new object
parseInt(s); // parses and returns int (primitive)
valueOf(s); //returns cached Integer object with the int value in s
So, it depends: if you need int then parseInt(s) and if you need Integer then valueOf(s).
Integer.parseInt(s) is the best approach.
Interger#valueOf() method will return an Integer object equal to the value of new Integer(Integer.parseInt(s)).
Integer.getInteger() is not even a candidate.
Integer.getInteger(String) says that
Determines the integer value of the system property with the specified name.
If there is no property with the specified name, if the specified name is empty or null, or if the property does not have the correct numeric format, then null is returned.
In other words, this method returns an Integer object equal to the value of:
getInteger(nm, null)
And here is best explanation of your confusion.
Edited :
AFAIK:
Integer.valueOf(String) converts a String to a number by assuming the String is a numeric representation. In other words. Integer.valueOf("100") yields the number 100.
Integer.getInteger(String) converts a String to a number by assuming the String is the name of a system property numeric representation. In other words. Integer.getInteger("100") is likely to yield null.
getInteger(String s) returns the integer value of the system property with the specified name.If there is no property with the specified name, if the specified name is empty or null, or if the property does not have the correct numeric format, then null is returned. Note that this is equivalent to getInteger(s, null) evidently its not doing what you expect it to do!
Now analyzing the remaining approaches, valueOf() result is an Integer object that represents the integer value specified by the string,an Integer object equal to the value of: new Integer(Integer.parseInt(s)), so lets rule out this first.
Now the new Integer(s) approach, now if you want to work with the int value, you again need to get the intValue(), So finally it turns out that Integer.parseInt(s) approach is better (depends).
Javadoc can provide you with more details in case you need.
I prefer parseInt(...).
The reason that your last output is null is because getInteger(...) get the integer value from a property. To set the value of a property, use an option -D. Therefore, if you use the command line
java -D100=5 Test
You will not get the null but you'll get 5. Here, the option -D sets the property named "100" to value "5".
See getInteger(), which "determines the integer value of the system property with the specified name."

Categories

Resources