Set default value in JAXB - java

I have an xml file as following and when the filePath2 is null or empty I want the value of that to be of filePath1's value. Is there a way in which I can achieve this through JAXB.
<file filePath1="C:/filePath">
<subFile name="Test">
<filePath2></filePath2>
</subFile>
<file/>
I don't want to hardcode the default value. If the value for filePath2 is null or blank("") I want to set the filePath1 attribute as the value of 'String filePath'. Is there a way to do it via a setter in JAXB?

Using plain Oracle JAXB I only see the possibility to implement that using an javax.xml.bind.Unmarshaller.Listener.
Implement that interface in your model class and perform the necessary checks in the afterUnmarshal(..) method.
There you can access the value of filePath1 and set (if necessary) it to filePath2.

Thanks for all your inputs, at the end I opted for a simpler solution; to update the setter where filePath2 is being called.
The JAXB part -
String filePath2;
#XmlElement(required = true)
public void setFilePath2(final String file) {
this.filePath2= file;
}
Where filePath is used -
if (filePath2 == null || filePath2.isEmpty()) {
setFilePath2(getFilePath1());
}
If you come across a bettr yet simple solution let me know.

If you can use annotations, than this should do the trick
...
private String foo;
#XmlElement(defaultValue="bar")
public String getFoo() {
return foo;
}
...

Related

Find all Java methods using only one specific property of a specific type of parameter

We're in the process of trying to identify everywhere that a specific type of object is used only to get a specific property from it, and pass that property into the method instead.
I'm thinking IntelliJ IDEA's "Structural Search" might be a good tool for this, but I'm not sure how to formulate the search template.
A concrete example:
public class MyClass {
public Long getId() {...}
public void setSomethingElse(int se) {...}
}
public class SomeOtherClasses {
public void shouldBeMatched(MyClass mc) {
doSomething();
mc.getId();
doSomethingElse();
}
public void shouldNotBeMatched(MyClass mc) {
doSomething();
mc.getId();
mc.setSomethingElse(14);
doSomethingElse();
}
public void alsoShouldNotBeMatched(MyClass mc) {
shouldBeMatched(mc);
}
}
In the above example, if I'm looking for methods that only use getId, then I should find shouldBeMatched, but not be bothered with shoudNotBeMatched and alsoShouldNotBeMatched, because they do something with the mc object other than call getId().
I'm thinking IntelliJ IDEA's "Structural Search" might be a good tool for this
And it is indeed. The documentation can be tough though.
Let's check Search templates, filters, and script constraints page. It goes as follows.
Let's say, you have a variable that matches a method, a toString()
method. Then this variable is actually a PsiMethod node. Retrieving
variable.parent will produce a PsiClass node, and so forth.
variable.text then will give you the entire text of the method. If you
just need the name of the method, you can use variable.name.
It seems that the task can be done by choosing the right template and writing a corresponding Groovy script.
The template is called methods of the class and can be found under Existing templates. They provide __context__variable to be used with a script.
We have to be sure matched methods have parameters. It is simple enough, just put a count filter on a $Parameter$ variable.
Then we need to extract the name of a parameter of desired type and see if it is called in the body of the method. The following script will do.
def parameters = __context__.getParameterList().getParameters();
def parameter = parameters.find { p -> p.getType().getName().equals('MyClass') };
if (parameter == null) return false;
String parameterName = parameter.getName();
String methodText = __context__.getText();
String occurrence = "${parameterName}.";
String methodCall = "${parameterName}.getId()";
return methodText.count(occurrence) > 0 && methodText.count(occurrence) == methodText.count(methodCall);
Put it in the $Method$ variable filter and verify the results.

Maximo: How to read a field of an application using JAVA?

This question probably is easy. I am trying to read a field of a IBM Maximo application and use this value in the method getList(). The value I want to use was not saved in the database yet.
Here is some pseudocode:
#Override
public MboSetRemote getList() throws MXException, RemoteException {
MboSetRemote result = super.getList();
//Here is where i dont know how to do it
Date field = getFieldValue(FieldName)
//Here is where i want to use the value
String string = "....field..."
result.setWhere(string);
return result;
}
Thanks everyone,
Regards
I think the easiest and safest means to achieve your end of using the field value in your where clause is to use a bind variable, like this:
#Override
public MboSetRemote getList() throws MXException, RemoteException {
MboSetRemote result = super.getList();
//Here is where i want to use the value
String string = "....:fieldName...";
result.setWhere(string);
return result;
}
Notice the colon on the front of :fieldName in string. When Maximo sees this, it will look (not case-sensitive) on the current record / Mbo for an attribute named fieldName and replace :fieldName with the value in the attribute -- wrapped in quotes or whatever, as applicable to the attribute's type (ALN, UPPER, DATE, etc).
This approach is better than the approach you presented because it will employ Maximo's framework to prevent SQL injection attacks and etc.
That said, the way to get the field value would be as follows:
Date fieldValue = getMboValue("FieldName").getDate();
Further, I strongly suggest you get yourself a copy of Maximo's JavaDocs. You can do that here.

ASM to parse .class against the rule defined in xml

I am using ASM bytecode reader to parse .class file present in the code.
But I want to get the particular string defined in the class which inturn will be mentioned inside the xml.
So how to use XML and parse the string present in .class. As I see there is ClassReader only takes .class as a parameter not the XML or any other format.
I am using something like this:
InputStream in=String.class.getResourceAsStream("/java/lang/String.class");
ClassReader classReader=new ClassReader(in);
classReader.accept(v, 0);
please tell me is there any way to parse .class against the rule defined in xml file?
Thanks in advance...
Yashu
As I understand it, you want to do the following: You are receiving a .class file and you then want to extract some sort of information from it which is specified in an XML file. If this is so: ASM does not need to know about what kind of information you are requiring. ASM will plainly read the class file. If you plainly want to know if some specific String is part of the class's constant pool, you could use a short cut for being notified of that: Override the ClassReader's readUTF8(int, char[]) method like this:
public MyClassReader extends ClassReader {
private final Set<String> constantPoolStrings = new HashSet<String>();
// Add constructors here
#Override
public String readUTF8(int index, char[] buf) {
String value = super.readUTF8(index, buf);
constantPoolStrings.add(value);
return value;
}
public boolean hasString(String value) {
// From the details in your comment, we will need to do a fuzzy search.
for(String poolString : constantPoolStrings) {
if(poolString.contains(value)) {
return true;
}
}
return false;
}
}
Of course you have to provide some logic that knows what String you are interested in: If you for example have an XML file that contains specific words you will need to parse this file and extract these words. You can than query the MyClassReader for these Strings.

Hide a specific attribute when logging the values of an Object in Java

I'm logging an object values by printing all of its attribute values
log("logging obj"+my_obj)
I have a "password" attribute in the ojbect which I would like to hide from logging. One strategy I can think of is
temporarily save the password value in another String and set the value of the password to null
perform logging
Set the password value again using the value stored in the temp variable
Is there a better way of excluding a specific attribute from logging?
Edit: Also I cannot modify my_obj itself by design.
You could simply override the toString method of your object and exclude the password attribute.
e.g:
#Override
public String toString()
{
StringBuilder result = new StringBuilder();
... add your attributes that should be printed ...
return result.toString();
}
EDIT: After your comment, I mean something like this:
private String myObjectToString(MyObject myObject)
{
StringBuilder result = new StringBuilder();
...
return result.toString();
}

known API to write Bean/ResultSet into CSV file

I would like to export a Java Bean or ResultSet(JDBC) into a CSV file through Reflection mechanism.
I have seen this api :
http://opencsv.sourceforge.net/apidocs/au/com/bytecode/opencsv/bean/BeanToCsv.html
but it's not released yet.
Also, it will be fine if we can set some filters to avoid to map some precised fields.
Do you know a known API which owns these features ?
Unless there are some ready-made API:s I would use
Apache commons http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/builder/ReflectionToStringBuilder.html to get a String representation of an JavaBean. By setting your own ToStringStyle it would be possible to create a CSV style String. There are many possible settings for styling of the String, including excluding fields and so on.
And then of course writing it to a file.
You can just write out to a csv file as you would to a normal .txt file by using an outputstream or so.
If you need more advanced excel like stuff I recommend using Apache POI. It has always done the job nice & clean for me.
Adding to Kennets answer:
I implemented two classes: One for the header (if needed) and one for the body (actual data)
HEADER
The header style class needs to extend ToStringStyle
Invoke toString with a single element, e.g. ReflectionToStringBuilder.toString(firstElement, headerStyle)
Constructor:
this.setUseClassName(false);
this.setUseIdentityHashCode(false);
this.setContentStart("");
this.setUseFieldNames(true);
this.setFieldNameValueSeparator("");
this.setContentEnd("\n");
Override Method:
#Override
public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) {
super.append(buffer, fieldName, "", fullDetail);
}
BODY
The body class needs to extend RecursiveToStringStyle
Invoke toString with an array, e.g. ReflectionToStringBuilder.toString(array, bodyStyle)
Constructor:
this.setUseClassName(false);
this.setUseIdentityHashCode(false);
this.setContentStart("");
this.setUseFieldNames(false);
this.setContentEnd("");
this.setNullText("n.a.");
this.setArrayStart("");
this.setArrayEnd("");
this.setArraySeparator("\n");
Override Method:
#Override
public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) {
String csvField = Optional.ofNullable(value)
.map(Objects::toString)
.map(this::escapeLineBreak)
.map(this::escapeDoubleQuote)
.map(this::escapeField)
.orElse(null);
super.append(buffer, fieldName, csvField, fullDetail);
}
Formatting Methods:
private String escapeDoubleQuote(final String field) {
return field.replace("\"", "\"\"");
}
private String escapeLineBreak(final String field) {
return field.replaceAll("\\R", " ");
}
private String escapeField(final String field) {
return "\"" + field + "\"";
}

Categories