What I need specifically is to prevent user from entering date/time that is in the future. That's different than disabling a specific date, since I need to disable ALL dates part a certain date.
Ideally, any future dates should be disabled. For now, I'm just going prevent form submit when user enters invalid time, but disabling unwanted dates would be better.
I went through the javadoc and found nothing. Is it possible? How?
Configuring a range just means disabling the dates outside this range. So the process is the same as the one in the linked answer. You can create a utility method to create filters easier. For example, configureShowRangeHandler admits a Predicate<Date> that will disable the date if the predicate returns false. The enableUntilToday is a simple example to limit selectable dates until today.
{
DatePicker dp = new DatePicker();
Predicate<Date> enableUntilTodayDates = d -> !d.after(new Date());
configureShowRangeHandler(dp, enableUntilTodayDates);
}
static HandlerRegistration configureShowRangeHandler(DatePicker dp, Predicate<Date> fn) {
return dp.addShowRangeHandler(ev -> {
for (Date t = copyDate(ev.getStart()); t.before(ev.getEnd()); addDaysToDate(t, 1)) {
dp.setTransientEnabledOnDates(fn.test(t), t);
}
});
}
copyDate and addDaysToDate are static imported from CalendarUtil
Related
I'm new to JavaFX and was wondering if the Bindings API allowed an easier way to achieve the following. Consider a model that contains a database that may be null (because the database loads asynchronously) and a view that displays a label status reflecting the state of the database. If it is null it should say something like "Loading..." and if it isn't it should display how many items are in the database. It also would be great if the status could reflect the size of the database as it grows or shrinks.
So far, I understand that I could bind an integer property (size of the database) to the text property of the label by using a converter. This is fine, but I want the label to display more than the number. A localized string like "Loaded {0} items" precisely. And let's not forget that the database may still be null.
This is the solution I have in place
#Override
public void initialize(URL url, ResourceBundle bundle) {
// Initialize label with default value
status();
model.databaseProperty().addListener((obs, old, neu) -> {
// Update label when database is no longer null
status();
// Update label when size of database changes
neu.sizeProperty().addListener(x -> status());
});
}
public void status() {
if (model.database() == null) {
status.setText(bundle.getString("status.loading"));
} else {
String text = bundle.getString("status.ready");
int size = model.database().size();
text = new MessageFormat(text).format(size);
status.setText(text);
}
}
It works, but is there a way to do it with a chain of bindings, or at least part of it? I've seen how powerful (and lenghty) boolean bindings can be but I'm not sure something as flexible is possible with string bindings.
You can use Bindings.when, which is essentially a dynamic if/then binding:*
status.textProperty().bind(
Bindings.when(model.databaseProperty().isNull())
.then(bundle.getString("status.loading"))
.otherwise(
Bindings.selectInteger(model.databaseProperty(), "size").asString(
bundle.getString("status.ready")))
);
However, the above assumes bundle.getString("status.ready") returns a java.util.Formatter string, not a MessageFormat string. In other words, it would need to be "Loaded %,d items" rather than "Loaded {0,number,integer} items".
Bindings doesn’t have built-in support for MessageFormat, but if you really want to stick with MessageFormat (which is a legitimate requirement, as there are things MessageFormat can do which Formatter cannot), you can create a custom binding with Bindings.createStringBinding:
MessageFormat statusFormat = new MessageFormat(bundle.getString("status.ready"));
status.textProperty().bind(
Bindings.when(model.databaseProperty().isNull())
.then(bundle.getString("status.loading"))
.otherwise(
Bindings.createStringBinding(
() -> statusFormat.format(new Object[] { model.getDatabase().getSize() }),
model.databaseProperty(),
Bindings.selectInteger(model.databaseProperty(), "size")))
);
* Actually, it’s more like the ternary ?…: operator.
Is there a way to build listener that detect if date are still transmitted to variable and if yes do one thing and when not do other?
For example
Until “int counter1” increasing set boolean (true) or print or change another int for 1
int counter (not increasing or decreasing anymore) set Boolean (false) print different thing change another int for 2.
Basically variable changing plus or minus do one thing stop changing do other thing start changing again go back to doing first thing etc etc.
Is there a way to do this?
Without obvious whole if statements compering way.
Handmade
Most simple way is to access that variable through getters and setters. You can put preferred logic into your setter and track all mutations from there.
public class Main {
static int observable = 0;
static void setObservable(int newValue) {
if (observable != newValue) {
System.out.printf("Observable int has been changed from %d to %d.%n", observable, newValue);
observable = newValue;
}
}
public static void main(String[] args) {
observable = 1; // Nothing notified us that value has been changed
setObservable(2); // Console output 'Observable int changed from 1 to 2.'
}
}
Built-in solutions
There are plenty other ways to implement the same functionality: create actual java bean with getters and setters, implement observable and observer interfaces on your own or use ready built-in solutions, for example IntegerProperty:
IntegerProperty intProperty = new SimpleIntegerProperty();
intProperty.addListener((observable, oldValue, newValue) -> {
if (!oldValue.equals(newValue) ) {
System.out.printf("Value has been changed from %d to %d!%n", oldValue.intValue(), newValue.intValue());
}
});
intProperty.setValue(1); // Output: Value has been changed from 0 to 1!
intProperty.setValue(2); // Output: Value has been changed from 1 to 2!
intProperty.setValue(2); // No output
System.out.println(intProperty.intValue()); // Output: 2
stopped changing
As for "stopped changing" listener, it's a little bit more complex issue. Depending on exact situation, there are several possible solutions I can think of:
1) if your loop is predictable and determined by you, just code the logic manually as it's required
/* listening for changes up there */
System.out.println("I'll go get some coffee");
Thread.sleep(60000); // stopped changing, eh?
/* do your stuff */
/* Continue listening for changes below */
2) if your loop is unpredictable but designed by you, you can try make it a little bit more predictable, design set of rules and protocols to follow, for example if new value is exactly zero, system will pause and switch to another task
3) you can also run background task which will periodically check last updated time, to determine if system is idle
There a lot of possible solutions to suggest, but I can't come up with something more specific without knowing more details
In my application the user can set her Locale from a list of available locales. The application needs to determine if a given date is a holiday and I am using jollyday for this task.
Here is my current code:
public boolean isHoliday(Calendar cal) {
HolidayManager m = HolidayManager.getInstance();
return m.isHoliday(cal);
}
I can change this to the following code to set a specific HolidayCalendar:
public boolean isHoliday(Calendar cal) {
HolidayManager m = HolidayManager.getInstance(HolidayCalendar.GERMANY);
return m.isHoliday(cal);
}
But this method is deprecated and I would need to figure out which HolidayCalendar I need based on the user locale. What I want to do is something like this:
public boolean isHoliday(Calendar cal, Locale loc) {
HolidayManager m = HolidayManager.getInstance(loc);
return m.isHoliday(cal);
}
I know that HolidayManager is using Locale.getDefault() and there are public methods in Holiday too (see here) but I can not figure out how to do this and the documentation is very brief.
My question: Can I get the holidays based on a particular locale? Do I have to write a major switch statement for all the locales to match a HolidayCalendar?
Update I created a PR to the project and added the functionality myself. The PR already got merged
In the jollyday/util/ResourceUtil.java I see a hashmap for locale-holiday_description pair, but it's private static and not being populated anywhere.
https://github.com/svendiedrichsen/jollyday/blob/master/src/main/java/de/jollyday/util/ResourceUtil.java#L61
private static final Map<Locale, ResourceBundle> HOLIDAY_DESCRIPTION_CACHE = new HashMap<>();
So, I believe, there isn't any direct method to do what you are looking for. And it would default to default Locale as you figured out. But you can fork and modify that package to your needs and use it in your code.
Also, trying opening a issue-request https://github.com/svendiedrichsen/jollyday/issues
I have created a class called Person which uses Optional<LocalDate> to store a person's birthday as a field. I have a method called timeToNextBirthday which computes the interval between the time of calling and the next birthday. The problem I'm having is that since birthday is optional, the method sometimes has nothing it can return. I don't know if I should throw an exception or just return some default object. I also considered making the return type optional and returning an empty optional if the birthday is unknown. This is a snippet of my code so far, using the exception option.
public class Person {
private Optional<LocalDate> dateOfBirth;
public Period timeToNextBirthday() throws NoSuchElementException {
if(!dateOfBirth.isPresent()) {
throw new NoSuchElementException("Birthday is unknown");
}
LocalDate currentDate = LocalDate.now();
// Assume this year's birthday has not passed and set next birthday to this year
LocalDate nextBirthday = dateOfBirth.get().withYear(currentDate.getYear());
// Add a year to nextBirthday if this year's birthday has already passed or is today
if (currentDate.isAfter(nextBirthday) || currentDate.equals(nextBirthday)) {
nextBirthday = nextBirthday.plusYears(1);
}
return Period.between(currentDate, nextBirthday);
}
}
How should I proceed?
Consider this: Changing the method's return type to Optional<Period> would make it very clear to the user of this method that it may not result in an usable Period due to dateOfBirth being optional and the user space code must be made to accomodate for this fact.
This sort of type carry-over is just fine if you don't want to throw exceptions (like you currently do) as it allows you as an API designer to assist the user of your code to cover all bases in a secure, null safe and self documenting way. Of course writing a bit of javadoc explaining why the return type is wrapped in Optional won't hurt either :)
I am looking for a concurrent Set with expiration functionality for a Java 1.5 application. It would be used as a simple way to store / cache names (i.e. String values) that expire after a certain time.
The problem I'm trying to solve is that two threads should not be able to use the same name value within a certain time (so this is sort of a blacklist ensuring the same "name", which is something like a message reference, can't be reused by another thread until a certain time period has passed). I do not control name generation myself, so there's nothing I can do about the actual names / strings to enforce uniqueness, it should rather be seen as a throttling / limiting mechanism to prevent the same name to be used more than once per second.
Example:
Thread #1 does cache.add("unique_string, 1) which stores the name "unique_string" for 1 second.
If any thread is looking for "unique_string" by doing e.g. cache.get("unique_string") within 1 second it will get a positive response (item exists), but after that the item should be expired and removed from the set.
The container would at times handle 50-100 inserts / reads per second.
I have really been looking around at different solutions but am not finding anything that I feel really suites my needs. It feels like an easy problem, but all solutions I find are way too complex or overkill.
A simple idea would be to have a ConcurrentHashMap object with key set to "name" and value to the expiration time then a thread running every second and removing all elements whose value (expiration time) has passed, but I'm not sure how efficient that would be? Is there not a simpler solution I'm missing?
Google's Guava library contains exactly such cache: CacheBuilder.
How about creating a Map where the item expires using a thread executor
//Declare your Map and executor service
final Map<String, ScheduledFuture<String>> cacheNames = new HashMap<String, ScheduledFuture<String>>();
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
You can then have a method that adds the cache name to your collection which will remove it after it has expired, in this example its one second. I know it seems like quite a bit of code but it can be quite an elegant solution in just a couple of methods.
ScheduledFuture<String> task = executorService.schedule(new Callable<String>() {
#Override
public String call() {
cacheNames.remove("unique_string");
return "unique_string";
}
}, 1, TimeUnit.SECONDS);
cacheNames.put("unique_string", task);
A simple unique string pattern which doesn't repeat
private static final AtomicLong COUNTER = new AtomicLong(System.currentTimeMillis()*1000);
public static String generateId() {
return Long.toString(COUNTER.getAndIncrement(), 36);
}
This won't repeat even if you restart your application.
Note: It will repeat after:
you restart and you have been generating over one million ids per second.
after 293 years. If this is not long enough you can reduce the 1000 to 100 and get 2930 years.
It depends - If you need strict condition of time, or soft (like 1 sec +/- 20ms).
Also if you need discrete cache invalidation or 'by-call'.
For strict conditions I would suggest to add a distinct thread which will invalidate cache each 20milliseconds.
Also you can have inside the stored key timestamp and check if it's expired or not.
Why not store the time for which the key is blacklisted in the map (as Konoplianko hinted)?
Something like this:
private final Map<String, Long> _blacklist = new LinkedHashMap<String, Long>() {
#Override
protected boolean removeEldestEntry(Map.Entry<String, Long> eldest) {
return size() > 1000;
}
};
public boolean isBlacklisted(String key, long timeoutMs) {
synchronized (_blacklist) {
long now = System.currentTimeMillis();
Long blacklistUntil = _blacklist.get(key);
if (blacklistUntil != null && blacklistUntil >= now) {
// still blacklisted
return true;
} else {
// not blacklisted, or blacklisting has expired
_blacklist.put(key, now + timeoutMs);
return false;
}
}
}