Silly Question about a validation case in Java and temporary variables - java

How does one set a temporary variable of date before it is updated? I would like to compare my initial date before it is updated.
Update: More code
* #hibernate.class table="t3sstations"
* #hibernate.join name="rgnjoin" table="stnregions" optional="true"
* #hibernate.join-key column="idstn"
*/
public class Station extends BaseSiteChildCFKObject implements Convertible, Comparable<Station> {
private static final long serialVersionUID = -2056063261398467275L;
protected final Log log = LogFactory.getLog(getClass());
private Project stationProject;
private Date project_startdate;
private Date date_initial;
Table it grabs from SQL using hibernate. It grabs the project's date from the column project_startdate. I want to compare the date that it is initially with the new/updated date. It updates the same value throughout the class.
/**
* #return
* #hibernate.many-to-one column="idproject" not-null="false"
* class="org.unavco.pbo.mdm.model.Project"
*/
#Required
public Project getStationProject() {
return stationProject;
}
public void setStationProject(Project stationProject) {
this.stationProject = stationProject;
}
/**
* #return
* #hibernate.property column="project_startdate"
*/
public Date getProject_startdate() {
return project_startdate;
}
public void setProject_startdate(Date project_startdate) {
this.project_startdate = project_startdate;
}
#AssertTrue
private boolean validateProjectDate() {
project_initialdate = new Date(project_startdate);
if (project_startdate.before(this.project_initialdate)){
return false;
}
if (project_startdate.before(this.stationProject.getStart_date())) {
return false;
}
if (this.stationProject.getEnd_date() != null) {
if (this.project_startdate.after(this.stationProject.getEnd_date())) {
return false;
}
}
return true;
}

So I don't think I found a temporary value holder but I did define the initial date as another variable inside the initializer. By placing it here, I save the date before it is changed and updated via hibernate.
public Station() {
super();
Date date_initial = this.project_startdate;
}
At the top of the class called Station. From there I also defined the getter and setter for date initial.
public Date getDate_initial(){
return date_initial;
}
public void setDate_initial(Date date_initial) {
this.date_initial = date_initial;
}
From there it accurately compares the initial date to the updated date. If it is safe then it continues to save. Otherwise it displays an error message to the user.

Related

Merge multiple RealmList´s and sort resulting List?

I just started using Realm in my current android app and so far it is great.
Unfortunately I´ve encountered a problem:
In my app the user can add different kind of entries (What did he eat this day? What drinks did he have?, etc.) into his diary.
One DiaryEntry object represents the sum off all entries for a given day (e.g. 21.05.2017, etc.).
public class DiaryEntry extends RealmObject {
// ID of the day this diary entry represents
#PrimaryKey private Integer dateId;
private RealmList<MealEntry> mealEntries;
private RealmList<DrinkEntry> drinkEntries;
private RealmList<SymptomEntry> symptomEntries;
private RealmList<MedicineEntry> medicineEntries;
public void addMealEntry(MealEntry mealEntry) {
mealEntries.add(mealEntry);
}
public RealmList<MealEntry> getMealEntries() {
return mealEntries;
}
public void addDrinkEntry(DrinkEntry drinkEntry) {
drinkEntries.add(drinkEntry);
}
public RealmList<DrinkEntry> getDrinkEntries() {
return drinkEntries;
}
public void addSymptomEntry(SymptomEntry symptomEntry) {
symptomEntries.add(symptomEntry);
}
public RealmList<SymptomEntry> getSymptomEntries() {
return symptomEntries;
}
public void addMedicineEntry(MedicineEntry medicineEntry) {
medicineEntries.add(medicineEntry);
}
public RealmList<MedicineEntry> getMedicineEntries() {
return medicineEntries;
}
}
To display this data for a particular day in the diary, all entries should be sorted by the time the user created them.
So every entry object contains a field 'time'.
private int time;
I came up with a temporary solution for my problem, but it´s far from perfect.
The follwing code is executed on the UI Thread, which obviously is bad practice.
List<RealmObject> entryList = new ArrayList<>();
OrderedRealmCollectionSnapshot<MealEntry> mealEntries = diaryEntry.getMealEntries().createSnapshot();
OrderedRealmCollectionSnapshot<DrinkEntry> drinkEntries = diaryEntry.getDrinkEntries().createSnapshot();
OrderedRealmCollectionSnapshot<MedicineEntry> medicineEntries = diaryEntry.getMedicineEntries().createSnapshot();
OrderedRealmCollectionSnapshot<SymptomEntry> symptomEntries = diaryEntry.getSymptomEntries().createSnapshot();
entryList.addAll(mealEntries);
entryList.addAll(drinkEntries);
entryList.addAll(medicineEntries);
entryList.addAll(symptomEntries);
Collections.sort(entryList, entryComparator);
The code to sort the entry list uses reflection by invoking the getter method for the time field:
public int compare(RealmObject entry1, RealmObject entry2) {
try {
Method timeGetter1 = entry1.getClass().getMethod("getTime");
Method timeGetter2 = entry2.getClass().getMethod("getTime");
int time1 = (Integer) timeGetter1.invoke(entry1);
int time2 = (Integer) timeGetter2.invoke(entry2);
return time1 - time2;
} catch (NoSuchMethodException e) {
e.printStackTrace();
Timber.d("No such method 'getTime'.");
}
// Other catch clauses
As I said earlier, all of this happens on the UI thread.
I know that I can´t pass RealmObjects, RealmLists and RealmResults across threads so I really have a hard time coming up with an async solution for that. I thought of starting a background thread and in there create copies of all the RealmList´s inside a DiaryEntry object. Then merge this unmanaged lists and sort it - all of that on the background thread.
So my question: Are there any preferred strategies for merging multiple RealmLists and sorting the merged list - all of that in an async fashion? Would my attempt I described above work?
Thanks #EpicPandaForce
I solved it exactly the way you described it and it works like a charm - now I even have the real-time functionality and no need to refresh the data manually, Nice :)
In case anybody faces the same problem I post some code pieces here that show how I solved it in code.
public class Entry extends RealmObject {
private static final int ENTRY_MEAL = 0;
private static final int ENTRY_DRINK = 1;
private static final int ENTRY_SYMPTOM = 2;
private static final int ENTRY_MEDICINE = 3;
/** The tag describes what kind of entry it represents */
private int tag;
/* Only one of these can be set, according to what this entry represents. */
#Nullable private MealEntry mealEntry;
#Nullable private DrinkEntry drinkEntry;
#Nullable private SymptomEntry symptomEntry;
#Nullable private MedicineEntry medicineEntry;
/** The time value this entry was created at */
/** Format: hours + minutes * 60 */
private int time;
public int getTime() {
return time;
}
/* Can only be accessed from within the 'data' package */
void setTime(int time) {
this.time = time;
}
/**
* Creates a new entry object in the realm database and tags it as 'MEAL'
*
* #param realm not null
* #param mealEntry the {#link MealEntry} object to map this entry to, not null
*
* #return the newly created entry
*/
static Entry createEntryAsMeal(#NonNull final Realm realm, #NonNull final MealEntry mealEntry) {
if(realm == null) {
throw new IllegalArgumentException("'realm' may not be null");
}
if(mealEntry == null) {
throw new IllegalArgumentException("'mealEntry' may not be null");
}
Entry entry = realm.createObject(Entry.class);
entry.tag = ENTRY_MEAL;
entry.mealEntry = mealEntry;
return entry;
}
/* Same methods for other tag types ... */
In MealEntry.class:
public class MealEntry extends RealmObject {
#PrimaryKey #Required private String id;
#Required private String title;
/** The entry objects this meal-entry is added to */
Entry entry;
/** This time value describes when the user consumed this meal **/
private int time;
// other fields
/**
* Creates a new MealEntry object in the realm.
* <p>
* Note: It is important to use this factory method for creating {#link MealEntry} objects in realm.
* Under the hood, a {#link Entry} object is created for every MealEntry and linked to it.
* </p>
*
* #param realm not null
*
* #return new MealEntry object which has been added to the <code>realm</code>
*/
public static MealEntry createInRealm(#NonNull Realm realm) {
if(realm == null) {
throw new IllegalArgumentException("'realm' may not be null");
}
MealEntry mealEntry = realm.createObject(MealEntry.class, UUID.randomUUID().toString());
mealEntry.entry = Entry.createEntryAsMeal(realm, mealEntry);
return mealEntry;
}
The 'time' field exists in the Entry.class and MealEntry.class so if the latter one changes the Entry must be updated accordingly:
/**
* Sets the time value for the <code>mealEntry</code> to the specified value.
* <p>
* Note: This method is necessary in order to sync the new time value with the underlying
* {#link Entry} object that is connected with the <code>mealEntry</code>.
* </p>
*
* #param mealEntry the {#link MealEntry} object to set the time for, not null
*
* #param time the new time value, must be in range of [0, 24*60] because of the format: hours*60 + minutes
*
*/
public static void setTimeForMealEntry(#NonNull MealEntry mealEntry, #IntRange(from=0, to=24*60) int time) {
if(mealEntry == null) {
throw new IllegalArgumentException("'mealEntry' may not be null");
}
mealEntry.setTime(time);
Entry entry = mealEntry.entry;
if(entry == null) {
throw new IllegalStateException("'mealEntry' contains no object of type 'Entry'! Something went wrong on creation of the 'mealEntry'");
}
/* Syncs the entries time value with the time value for this MealEntry. */
/* That´s important for sorting a list of all entries. */
entry.setTime(time);
}
Note: I could have stored only the ID of the corresponding Entry object inside the MealEntry and vice-versa for the Entry object store an ID to the corresponding MealEntry object. However I don´t know what a difference in perfomance this makes so I just went with the above approach.
One reason for the other approach though would be that I wouldn´t have to store the 'time' field twice, once in the Entry.class and once in the MealEntry.class, because in the Entry.class I could just get the time value by finding the corresponding MealEntry object by its ID and then get the time.

How to change values in the SET Method

I am starting to develop my skills in JAVA, however I have a doubt.
I'm creating an object in JAVA, created the constructor and so on, then, it asks "Change the AGE_RECENT value from 1 to 3", I initially declared this as final because I never thought it would change, so no SET or GET were created. I am wondering how can I change the value from 1 to 3 in the SET Method.
I have this variable
private static int AGE_RECENT=1;
I did this.
public void setAgeRecent() {
Vehicle.AGE_RECENT = 3;
}
It works if you run the program, it changes the variable's value, however nothing was declared in that method as every SET method.
Just wondering how can I do this. If this is correct, good, if not, thanks for helping!
As someone asked, the code.
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package tp1;
/**
*
* #author Nelson
*/
public class Vehicle {
/** Variáveis da classe, têm como função **/
private String registration;
private int registrationYear;
private double consumption;
private double autonomy;
private int cilinderCapacity;
/**
* Final variables. They are final because they do not suffer any kind of modification during the project.
* YEAR_OMISSION is 2016 because the currect year is 2016.
* ENVIRONMENTAL_CHARGE_OMISSION is 0.10(10 cents), gave this value because there is nothing to mention the
especific value, hence why I gave 0.10.
* RATING_RECENT = Is a string, just has the text "RECENT" inside.
* RATING_COMTEMPORY - Another string, just with the "Comtempory" text inside.
* RATING_CLASSIC - Yet again another string, with the "Classic" text.
* AGE_RECENT - It is to help to compare if a vehicle is recent or not, it has the value 3.
* AGE_CLASSIC - It is to again help to compare, value is 20.
*/
private static final int YEAR_OMISSION = 2016;
private static final double ENVIRONMENTAL_CHARGE_OMISSION=0.10;
private static final String RATING_RECENT="Recent";
private static final String RATING_CONTEMPORY="Contempory";
private static final String RATING_CLASSIC="Classic";
private static int AGE_RECENT=1;
private static final int AGE_CLASSIC=20;
/**
* Constructor of the object, it has the Registration
* #param registration
* #param registrationYear - The year the vehicle was first registered.
* #param consumption - How many liters the vehicle consumes.
* #param autonomy - How many KMs a vehicle can go without refuelling.
* #param cilinderCapacity - How many Cubic Inches the engine has.
*/
public Vehicle(String registration,int registrationYear, double consumption, double autonomy, int cilinderCapacity) {
this.registration = registration;
this.registrationYear = registrationYear;
this.consumption = consumption;
this.autonomy = autonomy;
this.cilinderCapacity = cilinderCapacity;
}
/**
* Null Constructor, it has no values, they will be attributed in the MAIN Class.
*/
public Vehicle() {
this.registration = "";
this.registrationYear = 0;
this.consumption = 0;
this.autonomy = 0;
this.cilinderCapacity =0;
this.registrationYear = YEAR_OMISSION;
}
/**
* Copy Constructor.
*/
public Vehicle(Vehicle vehicle) {
this.registration = vehicle.getRegistration();
this.registrationYear = vehicle.getRegistrationYear();
this.consumption = vehicle.getConsumption();
this.autonomy = vehicle.getAutonomy();
this.cilinderCapacity = vehicle.getCilinderCapacity();
}
public String getRegistration() {
return registration;
}
public int getRegistrationYear() {
return registrationYear;
}
public double getConsumption() {
return consumption;
}
public double getAutonomy() {
return autonomy;
}
public int getCilinderCapacity() {
return cilinderCapacity;
}
public double getYearRecent() {
return AGE_RECENT;
}
public double getAgeRecent(){
return AGE_RECENT;
}
public void setRegistration(String registration) {
this.registration = registration;
}
public void setRegistrationYear(int registrationYear) {
this.registrationYear = registrationYear;
}
public void setConsumption(double consumption) {
this.consumption = consumption;
}
public void setAutonomy(double autonomy) {
this.autonomy = autonomy;
}
public void setCilinderCapacity(int cilinderCapacity) {
this.cilinderCapacity = cilinderCapacity;
}
public void setAgeRecent() {
Vehicle.AGE_RECENT = 3;
}
/**
* Calculate the age of the vehicle to compare in the vehicleRating method
* #return The year, which is 2016 minus the year the vehicle was first registered.
*/
private int calculateAge(){
return YEAR_OMISSION-this.registrationYear;
}
/**
* Calculate the Circulation Tax.
* #return Returns the value of the Environmental Charge multiplied by the Cilinder Capacity of the vehicle.
*/
public double calculateCirculationTax(){
return ENVIRONMENTAL_CHARGE_OMISSION*cilinderCapacity;
}
/**
* Classify the vehicle based on the age.
* If the result given by the calculateAge method is minor than the AGE_RECENT variable(3), then it will
return "Recent"
* If the result is between Age_RECENT and AGE_CLASSIC(20), then it will say "Contemporary"
* If none of the IFs apply, it will return "Classic".
**/
public static String vehicleRating(Vehicle vehicle) {
if(vehicle.calculateAge() < Vehicle.AGE_RECENT) {
return Vehicle.RATING_RECENT; }
else if ((vehicle.calculateAge()>=Vehicle.AGE_RECENT)&&(vehicle.calculateAge()<=Vehicle.AGE_CLASSIC)){
return Vehicle.RATING_CONTEMPORY;}
else
return Vehicle.RATING_CLASSIC;
}
#Override
public String toString() {
return "Vehicle{" + "registration=" + registration + ", registrationYear=" + registrationYear + ", consumption=" + consumption + ", autonomy=" + autonomy + ", cilinderCapacity=" + cilinderCapacity + '}';
}
}
A setter that takes no arguments is simply a method, not a setter. In order to work as a setter a method must take a parameter that matches the type of the value being set - in your case, that would be int:
public static void setAgeRecent(int age) {
AGE_RECENT = age;
}
Note a few things here:
Since AGE_RECENT is static, setAgeRecent should be static
Since AGE_RECENT and setAgeRecent are static members of the same class Vehicle, you do not need to qualify AGE_RECENT with Vehicle
Now users of your class would be able to call your static setter as follows:
Vehicle.setAgeRecent(3);
A static varible, or class variable, may be used without the need to create an instance of that class. But its value may be changed freely at runtime.
A final variable is not a variable in a true sense, because it's value can't be changed at runtime.
Thus, you may have a set method for a static variable, but never to a final variable.

LocalDateTime not working - without any kind of error

I'm developing a Java project, a log analyzer, that imports any kind of log informations in a universal way.
Actually, I divided any log sheet in a Log class instance, and any sheet line in a Event class instance.
The problem is: Log read all the sheet, and instance an Event with every read line, putting it in a LinkedHashSet.
When Event gets constructed, it takes - depending on which Log type is it in - all the informations (such as the time the event happened).
Everything works flawlessly, except for getting Date/Time from event string.
In fact, without any kind of error, Log's adding Event cycle, stops.
Deleting every Time-related line, I correctly manage to get everything: with them, it stops, without any error, but making me getting only bunch of lines, instead of the thousands I should get.
Here you can find Log and Event classes, and even the method that gets Time from event and the last line of Event the manage to get Time and the first one that doesn't.
Log:
public class Log {
/** LogType assigned to log file */
private LogType type;
/** filename associated to log file*/
private String name;
/** path associated to log file */
private String path;
private LinkedHashSet<Evento> events;
/**
* Log constructor:
* #param path points to file which create log instance from
* #param type is the LogType type associated with the rising Log
* #param bInitialize indicates if Log has to initialize events list
*/
public Log(String path, LogType type, boolean bInitialize) {
String[] pathComponents = path.split("/");
this.path = path;
this.type = type;
this.name = pathComponents[pathComponents.length - 1];
populateEvents();
}
public LinkedHashSet<Evento> getEvents() {
return events;
}
/** type field getter */
public LogType getType() {
return type;
}
/** name field getter */
public String getName() {
return name;
}
/** path field getter */
public String getPath() {
return path;
}
/** #return path field */
public String toString() {
return path;
}
public TreeSet<Utente> getUsers() {
TreeSet<Utente> users = new TreeSet<Utente>();
for (Evento event : events)
users.add(event.getUser());
return users;
}
private void populateEvents() {
events = new LinkedHashSet<Evento>();
try {
File file = new File(path);
FileInputStream fInputStream = new FileInputStream(file);
byte[] data = new byte[(int) file.length()];
fInputStream.read(data);
fInputStream.close();
String[] eventsRead = new String(data, "UTF-8").split("\n");
for (String event : eventsRead)
events.add(new Evento(event, type));
} catch (Exception e) {
// Nothing really needed.
}
}
/** name field setter */
public void setName(String name) {
this.name = name;
}
/**
* Requests that the file or directory denoted by this abstract
* pathname be deleted when the virtual machine terminates.
*/
public void setToDeleted() {
new File(path).deleteOnExit();
}
}
Event:
public class Evento implements Comparable<Evento> {
private LocalDateTime time;
private LogType type;
private String event;
private Utente user;
public Evento(String event, LogType type) {
this.event = event;
this.type = type;
time = type.getAssociatedLoader().getTimeFromLine(event);
user = type.getAssociatedLoader().getUserFromLine(event);
}
public boolean equals(Evento comparedEvent) {
return event.equals(comparedEvent.getEvent());
}
#Override
public int compareTo(Evento comparedEvent) {
return event.compareTo(comparedEvent.getEvent());
}
public LocalDateTime getTime() {
return time;
}
public String getEvent() {
return event;
}
public Utente getUser() {
return user;
}
#Override
public String toString() {
return event;
}
}
getTimeFromLine() method:
#Override
public LocalDateTime getTimeFromLine(String line) {
String clockString = line.split("\t")[2];
return LocalDateTime.of(Integer.parseInt(clockString.substring(0,4)),
Integer.parseInt(clockString.substring(6,7)),
Integer.parseInt(clockString.substring(9,10)),
Integer.parseInt(clockString.substring(11,13)),
Integer.parseInt(clockString.substring(15,16)),
Integer.parseInt(clockString.substring(17,19)));
}
Lines example (first correctly working, not the latter):
142\twestchester.gov\t2006-03-20 03:55:57\t1\thttp://www.westchestergov.com
142\tspace.comhttp\t2006-03-24 20:51:24\t\t
You should not swallow exceptions - if you had let it propagate you would have got a fairly self explanatory exception message that would have helped you find the problem!
java.time.DateTimeException: Invalid value for DayOfMonth (valid values 1 - 28/31): 0
So one of your clockString.substring() does not use the right indices
Your getTimeFromLine method is unnecessary complicated and I would recommend to use a DateTimeFormatter instead of parsing the string manually
Suggested replacement:
private static final DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
public LocalDateTime getTimeFromLine(String line) {
String clockString = line.split("\t")[2];
return LocalDateTime.parse(clockString, fmt);
}

Condition to check if a value exists in list containing objects,

I am trying to write an if condition to check a value exists in a list containing many objects,
Here is my code:
List<TeacherInfo> teacherInfo=ServiceManager.getHelperService(TeacherManagementHelper.class, request, response).getTeacherInfoId();
if(teacherInfo.contains(inputParam))
{
out2.println("<font color=red>");
out2.println("Id Not Available");
out2.println("</font>");
}
else
{
out2.println("<font color=green>");
out2.println("Id Available");
out2.println("</font>");
}
after executing 1st sentence getTeacherInfoId() method successfully returns a list of objects, in those objects I want to check any object has a value same as inputParam. Is my above code right ? if wrong please help me .
contains(Object o) is internally based on equals between objects of your list and your input, as stated by the doc.
Since you said that inputParam is an integer, then the current state of your code can't work because you compare an integer to TeacherInfo objects, so they won't ever be equal. I believe you want to compare inputParam to one particular field of TeacherInfo objects.
If you're using Java 8, you can use the stream API instead of contains():
List<TeacherInfo> teacherInfo=ServiceManager.getHelperService(TeacherManagementHelper.class, request, response).getTeacherInfoId();
if (teacherInfo.stream().anyMatch(ti -> ti.getId() == inputParam)) {
// contains the id
} else {
// does not contain the id
}
For previous java versions, an alternative to contains() would be to iterate over your list and compare manually your integer to the TeacherInfo's field:
private static boolean containsTeacherId(List<TeacherInfo> teacherInfos, int id) {
for (TeacherInfo ti : teacherInfos) {
if (ti.getId() == inputParam) { // I used getId(), replace that by the accessor you actually need
return true;
}
}
return false;
}
Then:
List<TeacherInfo> teacherInfo=ServiceManager.getHelperService(TeacherManagementHelper.class, request, response).getTeacherInfoId();
if (containsTeacherId(teacherInfo, inputParam)) {
// contains the id
} else {
// does not contain the id
}
Note: If you don't need other information than the ID itself, I'd rather suggest to return the list of IDs from a method called getTeacherIds(), especially if this information comes from a DB.
No it won't work at all. you should iterate the 'teacherInfo' list and you need to override the compare()and hashvalue() of object class.
You would need to iterate over the list teacherInfo and compare each element of that list with inputParam.
Below is a small demo code that might help you.
I have created a testerInfo analogous to your teacherInfo and param analogous to your inputParam.
I hope it helps.
Tester.java
/**
*
*/
package com.demo;
/**
* #author Parul
*
*/
public class Tester {
private int id;
private String name;
/**
* #return the id
*/
public int getId() {
return id;
}
/**
* #param id the id to set
*/
public void setId(int id) {
this.id = id;
}
/**
* #return the name
*/
public String getName() {
return name;
}
/**
* #param name the name to set
*/
public void setName(String name) {
this.name = name;
}
public Tester(int id, String name) {
this.id = id;
this.name = name;
}
public Tester() {
}
}
Demo.java
/**
*
*/
package com.demo;
import java.util.ArrayList;
import java.util.List;
/**
* #author Parul
*
*/
public class Demo {
public static void main(String [] args){
List<Tester> testerInfo=new ArrayList<Tester>();
testerInfo.add(new Tester(1,"Java"));
testerInfo.add(new Tester(2,"C++"));
testerInfo.add(new Tester(3,"Python"));
testerInfo.add(new Tester(4,"C"));
Tester tester=null;
int param=2;
for(int i=0;i<testerInfo.size();i++){
tester=testerInfo.get(i);
if(tester.getId()==param){
System.out.println("param found: "+tester.getName());
break;
}
}
}
}
OUTPUT
param found: C++

Annotation for mapping Joda Time "Period" in JPA using Eclipse Link

I am having a field - expiryLimit in my Item entity for which I thought of using joda-time Period which would be an appropriate type to use here.
Just to explain - expiryLimit is the number of year, month, days, or any duration after which a particular item will expire and using which I can calculate the exact expiryDate of an Item given a deliveryDate.
Now the problem I'm facing is finding an appropriate way to map this type into JPA.
Is there any available API or 3rd party library which provides some annotation to do that? Also I've used the Eclipse Link #Converter annotation to map DateTime with MySQL TimeStamp. So, would I need to do the same thing with Period also. And if yes, then to what type should I convert it. To varchar? or to Long? or some other type appropriate to represent a Period.
Ok, finally I've solved the issue by using EclipseLink #Converter only. This is how I've done it. I also welcome any comments on this way: -
ItemMaster entity: -
public class ItemMaster {
#Converter(
name="periodConverter",
converterClass = com.joda.converter.PeriodConverter.class
)
#Convert("periodConverter")
#Column(name = "expiry_limit", length = 2000)
private Period expiryLimit;
/** Constructors **/
public Period getExpiryLimit() {
return expiryLimit;
}
public void setExpiryLimit(Period expiryLimit) {
this.expiryLimit = expiryLimit;
}
}
PeriodConverter.class: -
public class PeriodConverter implements Converter {
private Logger log;
private static final long serialVersionUID = 1L;
#Override
public Object convertDataValueToObjectValue(Object str, Session session) {
if (str == null) {
log.info("convertDataValueToObjectValue returning null");
return null;
}
return new Period(str);
}
#Override
public Object convertObjectValueToDataValue(Object period, Session session) {
/** str format should be: - `PyYmMwWdDThHmMsS` **/
if (period == null) {
log.info("convertObjectValueToDataValue returning null");
return null;
}
return period.toString();
}
#Override
public void initialize(DatabaseMapping mapping, Session session) {
log = Logger.getLogger("com.joda.converter.PeriodConverter");
((AbstractDirectMapping) mapping).setFieldType(java.sql.Types.VARCHAR);
}
#Override
public boolean isMutable() {
return true;
}
}

Categories