I have some trouble on Java source code about DefaultPersistenceDelegate - java

I just got some trouble with java source code for DefaultPersistenceDelegate, here is the code:
/**
* This default implementation of the <code>instantiate</code> method returns
* an expression containing the predefined method name "new" which denotes a
* call to a constructor with the arguments as specified in
* the <code>DefaultPersistenceDelegate</code>'s constructor.
*
* #param oldInstance The instance to be instantiated.
* #param out The code output stream.
* #return An expression whose value is <code>oldInstance</code>.
*
* #throws NullPointerException if {#code out} is {#code null}
* and this value is used in the method
*
* #see #DefaultPersistenceDelegate(String[])
*/
protected Expression instantiate(Object oldInstance, Encoder out) {
int nArgs = constructor.length;
Class<?> type = oldInstance.getClass();
Object[] constructorArgs = new Object[nArgs];
for(int i = 0; i < nArgs; i++) {
try {
Method method = findMethod(type, this.constructor[i]);
constructorArgs[i] = MethodUtil.invoke(method, oldInstance, new Object[0]);
}
catch (Exception e) {
out.getExceptionListener().exceptionThrown(e);
}
}
return new Expression(oldInstance, oldInstance.getClass(), "new", constructorArgs);
}
In the return statement , it returns a Expression with method name "new", but in my memory "new" should be a construct name,there is not a method named 'new'.
This question confuse me few days, is anybody can help me?

Related

Java problem - method undefined even though I already defined it in the package

I'm a total beginner in Java and I'm working on an assignment that's largely prefabricated/preformatted code, but I can't get it to work. In Eclipse, I get an error saying "Method cardToString(MyCard) is undefined for the type MyCardTester" before I even run it. I've looked at similar questions on Stackoverflow,
(Eclipse is telling me a method is undefined when it clearly is in fact defined, "The method is not defined for the type" error in simple program in java)
and they have different problems from me. I think that my problem may be with my classpath or run configuration, but those settings seem fine. Here is the code:
Here's the first class:
package EllevensGame;
import EllevensGame.MyCard;
import java.lang.String;
/**
* This is a class that tests the Card class.
*/
public class MyCardTester {
/**
* The main method in this class checks the Card operations for consistency.
* #param args is not used.
*/
public static void main(String[] args) {
MyCard testCard = new MyCard("King", "Hearts", 13);
String printStuff = cardToString(testCard);
System.out.println(printStuff);
}
}
Second class:
package EllevensGame;
/**
* MyCard.java
*
* <code>MyCard</code> represents a playing card.
*/
import java.lang.String;
public class MyCard {
/**
* String value that holds the suit of the card
*/
protected String suit;
/**
* String value that holds the rank of the card
*/
protected String rank;
/**
* int value that holds the point value.
*/
protected int pointValue;
/**
* Creates a new <code>Card</code> instance.
*
* #param cardRank a <code>String</code> value
* containing the rank of the card
* #param cardSuit a <code>String</code> value
* containing the suit of the card
* #param cardPointValue an <code>int</code> value
* containing the point value of the card
*/
public MyCard(String cardRank, String cardSuit, int cardPointValue) {
//MyCard newCard = new MyCard(cardRank, cardSuit, cardPointValue); Not sure if this is right or not
}
/**
* Accesses this <code>Card's</code> suit.
* #return this <code>Card's</code> suit.
*/
public String suit() {
return suit;
}
/**
* Accesses this <code>Card's</code> rank.
* #return this <code>Card's</code> rank.
*/
public String rank() {
return rank;
}
/**
* Accesses this <code>Card's</code> point value.
* #return this <code>Card's</code> point value.
*/
public int pointValue() {
return pointValue;
}
/** Compare this card with the argument.
* #param otherCard the other card to compare to this
* #return true if the rank, suit, and point value of this card
* are equal to those of the argument;
* false otherwise.
*/
public boolean matches(MyCard otherCard) {
if (otherCard.pointValue == (pointValue()) && (otherCard.rank.equals(rank)) && (otherCard.suit.equals(suit))) {
return true;
}
else {return false;}
}
/**
* Converts the rank, suit, and point value into a string in the format
* "[Rank] of [Suit] (point value = [PointValue])".
* This provides a useful way of printing the contents
* of a <code>Deck</code> in an easily readable format or performing
* other similar functions.
*
* #return a <code>String</code> containing the rank, suit,
* and point value of the card.
*/
//#Override
public String cardToString(MyCard newCard) {
String pointstring = String.valueOf(pointValue);
String print = rank + " of " + suit + pointstring;
return print;
}
}
Final note: the code is supposed to create a "card" object for a card game (Ellevens).
Thanks!!
cardToString is a method in MyCard, you must invoke it through the reference. Change
String printStuff = cardToString(testCard);
to
String printStuff = testCard.cardToString(testCard);
Although it might be better to make that method return a String based on the this instance (which would make more sense).
public String cardToString() {
return rank + " of " + suit + pointValue;
}
And then
String printStuff = testCard.cardToString();
I then fixed your constructor
public MyCard(String cardRank, String cardSuit, int cardPointValue) {
this.rank = cardRank;
this.suit = cardSuit;
this.pointValue = cardPointValue;
}
And ran it getting
King of Hearts13

Pair swap bug in commons-lang3 EqualsBuilder?

The following is a part source code of org.apache.commons.lang3.builder.EqualsBuilder. What is the difference between pair and swappedPair ? why not swappedPair = Pair.of(pair.getRight(), pair.getLeft());
static Pair<IDKey, IDKey> getRegisterPair(final Object lhs, final Object rhs) {
final IDKey left = new IDKey(lhs);
final IDKey right = new IDKey(rhs);
return Pair.of(left, right);
}
/**
* <p>
* Returns <code>true</code> if the registry contains the given object pair.
* Used by the reflection methods to avoid infinite loops.
* Objects might be swapped therefore a check is needed if the object pair
* is registered in given or swapped order.
* </p>
*
* #param lhs <code>this</code> object to lookup in registry
* #param rhs the other object to lookup on registry
* #return boolean <code>true</code> if the registry contains the given object.
* #since 3.0
*/
static boolean isRegistered(final Object lhs, final Object rhs) {
final Set<Pair<IDKey, IDKey>> registry = getRegistry();
final Pair<IDKey, IDKey> pair = getRegisterPair(lhs, rhs);
final Pair<IDKey, IDKey> swappedPair = Pair.of(pair.getLeft(), pair.getRight());
return registry != null
&& (registry.contains(pair) || registry.contains(swappedPair));
}

Why does Class AtomicBoolean be initialized not true but false by default constractor?

java source code:
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicBoolean.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
default constructor do nothing:
public AtomicBoolean() {
}
The variable 'valueOffset' means the offset location in memory? I don't understand why it initialized to 'false' by default constructor.How can i understand this?
As no value is set in the default constructor, the initial value is the initialized value of the value field - that's an int, with no explicit value, so it has the default value of zero.
Source code:
private volatile int value;
/**
* Creates a new {#code AtomicBoolean} with the given initial value.
*
* #param initialValue the initial value
*/
public AtomicBoolean(boolean initialValue) {
value = initialValue ? 1 : 0;
}
/**
* Creates a new {#code AtomicBoolean} with initial value {#code false}.
*/
public AtomicBoolean() {
}
Setting it to false is consistent with an uninitialized boolean field.

JasperReport: How to use subreport return values as input for Main Report Variable Calculation

Scenario:
I've two reports: Main Report (let's call it, A) and sub-report (let's call it, B).
Report A contains sub-report B at the detail band, so sub-report B is displayed for each element at the Report A datasource. Sub-report B also returns a variable to the Main report A.
What I want is to sum those return values from sub-report B and totalize them at the Main report summary.
To do that, I have tried to create a new report variable that sum those returns values... Something like this:
However, I've found that such variables expression are always evaluated before the band detail is rendered, so I always miss the first sub-report return value...
Sadly, the evaluation time (as this link says) cannot be changed on those kind of variables, so I'm stuck...
After been struggling with this for some hours... and searching the internet for a solution... I came with a Workaround (the enlightening forums were these ones: one and two).
First, you need to define a java Class Helper that allows you calculate some arithmetic operation, in my case a Sum operation. I defined these classes:
package reports.utils;
import java.util.Map;
/**
* Utility that allows you to sum Integer values.
*/
public class SumCalculator {
/**
* Stores a map of {#code SumCalculator} instances (A Map instance per thread).
*/
private static final ThreadLocalMap<String, SumCalculator> calculatorsIndex = new ThreadLocalMap<>();
/**
* The sum total.
*/
private int total = 0;
/**
* No arguments class constructor.
*/
private SumCalculator() {
super();
}
/**
* Instance a new {#code SumCalculator} with the given ID.
*
* #param id {#code SumCalculator}'s ID
* #return the new {#code SumCalculator} instance
*/
public static SumCalculator get(String id) {
Map<String, SumCalculator> map = calculatorsIndex.get();
SumCalculator calculator = map.get(id);
if (calculator == null) {
calculator = new SumCalculator();
map.put(id, calculator);
}
return calculator;
}
/**
* Destroy the {#code SumCalculator} associated to the given ID.
*
* #param id {#code SumCalculator}'s ID
* #return {#code null}
*/
public static String destroy(String id) {
Map<String, SumCalculator> map;
map = calculatorsIndex.get();
map.remove(id);
if (map.isEmpty()) {
calculatorsIndex.remove();
}
return null;
}
/**
* Resets the {#code SumCalculator} total.
*
* #return {#code null}
*/
public String reset() {
total = 0;
return null;
}
/**
* Adds the given integer value to the accumulated total.
*
* #param i an integer value (can be null)
* #return {#code null}
*/
public String add(Integer i) {
this.total += (i != null) ? i.intValue() : 0;
return null;
}
/**
* Return the accumulated total.
*
* #return an Integer value (won't be null, never!)
*/
public Integer getTotal() {
return this.total;
}
}
package reports.utils;
import java.util.HashMap;
import java.util.Map;
/**
* Thread Local variable that holds a {#code java.util.Map}.
*/
class ThreadLocalMap<K, V> extends ThreadLocal<Map<K, V>> {
/**
* Class Constructor.
*/
public ThreadLocalMap() {
super();
}
/* (non-Javadoc)
* #see java.lang.ThreadLocal#initialValue()
*/
#Override
protected Map<K, V> initialValue() {
return new HashMap<>();
}
}
Second, at your jasper report, you need to define four text fields:
1) A text field that iniatializes your calculator; it should be (ideally) at the title section of the report and should have an expression like this: SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").reset(). This text field should have the evaluation time: NOW.
2) A text field that calls the increment function (i.e. SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").add($V{SUB_REPORT_RETURN_VALUE}). This text field will reside at your detail band, after the subreport element; and it should have the evaluation time: BAND (this is very important!!)
3) A text field that prints the calculator total. This text field will reside at your summary band, it will evaluate to NOW. Its expression will be: SumCalculator.get("$V{SUB_REPORT_RETURN_VALUE}").getTotal()
4) A text field that destroy the calculator. This text field will also reside at your summary band and must appear after the text field 3. The text field should have an expression like: SumCalculator.destroy("$V{SUB_REPORT_RETURN_VALUE}"). This text field should have the evaluation time: NOW.
Also, the text fields: 1, 2, and 4, should have the attribute "Blank when Null", so they will never be printed (that's why those java operations always return null).
And That's it. Then, your report can look something like this:
if i understand the problem, you can not summarize the amount returned by the sub report in the main report, i had the same problem and i solved in this way.
1.- Create a class which extends from net.sf.jasperreports.engine.JRDefaultScriptlet. and override the method beforeReportInit()
this is the code from this class.
package com.mem.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import net.sf.jasperreports.engine.JRDefaultScriptlet;
public class SumarizacionSubtotales extends JRDefaultScriptlet {
private final Log log = LogFactory.getLog(getClass());
private Double total;
public Double getTotal() {
return total;
}
public Double add(Double cantidad) {
if(log.isDebugEnabled())log.debug("AGREGANDO LA CANTIDAD : " + cantidad);
this.total += cantidad;
return cantidad;
}
#Override
public void beforeReportInit() throws JRScriptletException {
if(log.isDebugEnabled())log.debug("beforeReportInit");
total = 0.0D;
}
}
2.- add your project's jar in your ireport's classpath.
3.- Replace the class of the REPORT scriptlet.
in the properties with your class.
3.- add in the group footer where you want to print the value returned by the sub-report a textfield with the following expression.
$P{REPORT_SCRIPTLET}.add( $V{sum_detalles} )
In this case $V{sum_detalles} is a variable in the main report which contains the value returned by the sub-report.
4.- Add in the Last page footer another textfield with the following expression.
$P{REPORT_SCRIPTLET}.getTotal()

Finding a class reflectively by its simple-name alone

I was wondering if there is any given function that allows me to introspect a class without having to write the packages where the class is contained.
For example, I want to take a look at the methods and superclasses of the class Integer in order to do that I have to specify the packages where the class is located. This will be "java.lang.Integer"
Instead of doing that I want to just type the class name in order to have the information of the class displayed. Just like this "Integer"
How can I make that my program just check the class name, no matter where is it located?
Java will not stop you from creating your own my.company.Integer class and my.other.company.Integer class, so how it cannot know which Integer class is the right one.
The closes thing to an answer I can suggest is to create a pre-defined list of packages where you want to search the class for, and keep trying each until you find your class.
So something like:
class ClassFinder{
public static final String[] searchPackages = {
"java.lang",
"java.util",
"my.company",
"my.company.other" };
public Class<?> findClassByName(String name) {
for(int i=0; i<searchPackages.length; i++){
try{
return Class.forName(searchPackages[i] + "." + name);
} catch (ClassNotFoundException e){
//not in this package, try another
} catch (...){
//deal with other problems...
}
}
//nothing found: return null or throw ClassNotFoundException
return null;
}
}
If you want to get a list of all available packages instead of hard-coding them, see here.
Be warned that this method is unlikely to perform very well, so use it sparingly.
Borrowed code, slightly modified (...from #rodion's answer)
/**
* Returns first loaded Class found in the searchPackages
* #param classname the simple class name (e.g. "String")
* #param searchPackages String[] of packages to search.
* <li>Place the more important packages at the top since the first Class
* found is returned</li>
* <code>//Example
* public static final String[] searchPackages = {
* "java.lang",
* "java.util",
* "my.company",
* "my.company.other" };
* </code>
* #return the loaded Class or null if not found
*/
public static final Class<?> findClassByName(String classname, String[] searchPackages) {
for(int i=0; i<searchPackages.length; i++){
try{
return Class.forName(searchPackages[i] + "." + classname);
} catch (ClassNotFoundException e){
//not in this package, try another
}
}
//nothing found: return null or throw ClassNotFoundException
return null;
}
same code modified to throw an exception if duplicate Class names found
/**
* Returns the loaded Class found in the searchPackages
* #param classname the simple class name (e.g. "String")
* #param searchPackages String[] of packages to search.
* <li>Place the more important packages at the top since the first Class
* found is returned</li>
* <code>//Example
* public static final String[] searchPackages = {
* "java.lang",
* "java.util",
* "my.company",
* "my.company.other" };
* </code>
* #throws RuntimeException if more than one class of the same classname found in multiple packages
* #return the loaded Class (guaranteed to be unique among the searchPackages) or null if not found
*/
public static final Class<?> findClassByNameNoDupes(String classname, String[] searchPackages) {
Class<?> foundClass = null;
for(int i=0; i<searchPackages.length; i++){
try{
boolean wasNull = foundClass == null;
foundClass = Class.forName(searchPackages[i] + "." + classname);
if (!wasNull) throw new RuntimeException(classname + " exists in multiple packages!");
} catch (ClassNotFoundException e){
//not in this package, try another
}
}
return foundClass;
}
That's not possible, classes are loaded dynamically once referenced. So, there is no way to drill down the list of available packages as there is no such thing.
However, there are ways to inspect jars as these are zip files (including the standard JVM jars).

Categories