I need to write a rule using Drool that will validate that the phone number is valid US number (for the sake of this answer we can use this regex "^([0-9]{3})[0-9]{3}-[0-9]{4}$")
The object structure is like this:
{
"name": {"firstName":"John", "lastName":"Smith"},
"phone": [{"phoneType": "mobile", "phoneNumber":"123456789"}],
"dob":"01/01/2000"
}
Because phone is a list, I don't know how to loop and validate this object. For instance the validation for "dob" field looks something like this:
rule "RuleId: Drool01, Validate dob"
when
$user: user(dob != null)
user(dob not matches "(?:0[1-9]|1[012])" from $user
then
modify($user){setDob(null)};
I appreciate any help on this. I apologize if this is very basic but I literally just started to use Drools.
I'm going to assume these models (irrelevant bits omitted; assume getters and setters):
class User {
private Name name; // Name model not shown, not relevant to this question
private Phone phone;
private String dob;
}
class Phone {
private String phoneType;
private String phoneNumber;
}
We can then write a rule like this:
rule "Invalid Phone Number"
when
$user: User( $phoneNumbers: phone )
exists( Phone( phoneNumber not matches "^([0-9]{3})[0-9]{3}-[0-9]{4}$" ) from $phoneNumbers)
then
// $user has at least 1 phone number which doesn't match the pattern
end
This rule is useful when we only need to know that there exists a bad value. It gets a little more interesting if we actually need to get those bad values (eg. if we want to report out a better error message.)
If we want to trigger the consequences for each bad phone number (eg. if there are 3 phone numbers and 2 are bad, we want to trigger the "then" twice) we could do like this:
rule "Invalid Phone Number - trigger for each"
when
$user: User( $phoneNumbers: phone )
$badPhone: Phone( phoneNumber not matches "^([0-9]{3})[0-9]{3}-[0-9]{4}$") from $phoneNumbers
then
// here $badPhone will be a phone number for $user that doesn't match the pattern
end
You might want to write a rule like this if you want to do something for each bad phone number individually. Consider maybe if we were doing "verified" phone numbers -- for example, they text you passcode that you have to use to verify your phone number; in this case you could text each phone number, one-by-one, to go through this verification process.
Alternatively we could just collect up all of the bad phone numbers and trigger the consequences once for all of those numbers, collectively.
rule "Invalid Phone Number - trigger once for all"
when
$user: User( $phoneNumbers: phone )
$badNumbers: List( size > 0 ) from collect (
Phone( phoneNumber not matches "^([0-9]{3})[0-9]{3}-[0-9]{4}$") from $phoneNumbers
)
then
// $badNumbers is a list of all of the Phone objects that don't match
// the pattern and belong to $user
end
Related
I have a requirement where I need to validate a string:
String input1 = example#gmail.com , example1#gmail.com;
String input2 = example#yahoo.com , example1#gmail.com;
String input 1 == valid ::: Valid because all email ids are of same domain
String input 2 == invalid
You can build the logic in the following way.
String input1 = example#gmail.com , example1#gmail.com , example1#gmail.com;
Follow the steps.
Split the entire string using comma (,). You will get an array of email ids.
From the above array of email id, separate out the domain by stripping from # symbol and put in a HashSet. It means the HashSet should contain all the domains.
If the HashSet size is 1 finally or at the end it means that input1 has same doamins, as per your requirement it is valid.
If the HashSet contains more than 1, as per your requirement it is invalid.
This is a simple logic, However there may be better logic to solve it.
I have an existing regex which validates the email input field.
[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!$%&'*+/=?^_`{|}~-]+)*(\\.)?#(?:[a-zA-Z0-9ÄÖÜäöü](?:[a-zA-Z0-9-_ÄÖÜäöü]*[a-zA-Z0-9_ÄÖÜäöü])?\\.)+[a-zA-Z]{2,}
Now, I want this regex to not match for two particular type of email IDs. Which are wt.com and des.net
To do that I made the following changes in the above expression like this.
[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!$%&'*+/=?^_`{|}~-]+)*(\\.)?#(?!wt\\.com)(?!des\\.net)(?:[a-zA-Z0-9ÄÖÜäöü](?:[a-zA-Z0-9-_ÄÖÜäöü]*[a-zA-Z0-9_ÄÖÜäöü])?\\.)+[a-zA-Z]{2,}
After this it does not matches with any email id which ends with the wt.com and des.net which is right.
But the problem is it does not match with wt.comm or any other letter after the restricted string too..
I just want to restrict email which ends with wt.com and des.net
How do I do that?
Below is the sample emails which should match or not.
ajcom#wt.com : no match
ajcom#aa.an : match
ajcom#wt.coms :match
ajcom#des.net : no match
ajcom#des.neta: match
If you want to prevent only wt.com and des.net which have no characters after it you can add $ anchor (which represents end of string) at the end of each negative-look-ahead.
So instead of (?!wt\\.com)(?!des\\.net) use (?!wt\\.com$)(?!des\\.net$)
I am working on google libphonenumber to get the phone number's information. I was able to pull the State & country name. But I am unable to get the CITY name. Does the google API provide CITY name as well ?
Please advice thanks in advance.
Does Google's libphonenumber API provide city names based on the area code?
Yes - but only if its internal geocoding database contains that information. Some US phone numbers are entirely non-geographic (like 1-800 numbers) and for many others the database just doesn't have that information.
Also, libphonenumber's geo lookup only returns single string values: it does not return structured data, like a class with city, state, county, and zip code fields. And the format of the returned string value varies considerably - limiting its uses in any automated system as it necessarily requires a human user to interpret the data.
For example, using the current libphonenumber (as of December 2021, that's version 8.12.38), I get the following results for these fictitious, but valid, numbers:
1-800-333-4567
This is a non-geographic "1-800" (toll-free) number.
libphonenumber's lookup returns the string "United States".
1-201-200-0000
The is is a US phone number in area code 201 for New Jersey.
libphonenumber's lookup returns the string "Jersey City, NJ".
It resolved it to a city and state, giving the state's abbreviation.
1-425-666-9999
This is (almost) my own personal phone number which I got from a T-Mobile store in Redmond, WA.
But libphonenumber's lookup returns only the imprecise string "Washington State" with no city name or similar. It's curious that it returned the full US state name instead of the "WA" abbreviation.
Remember, as with any in-proc "offline" geolocation database, data will inevitably go stale and inaccurate. Also, in the US at least, it's impossible to differentiate between mobile-phone numbers and landline numbers, and the area-code of someone's mobile-phone number is completely detached from the phone subscriber's actual physical location (it's usually the area-code of the AT&T / T-Mobile / Sprint store where they initially signed-up for service, even if they subsequently move across the country).
Anyway, here's how you use the PhoneNumberOfflineGeocoder class:
Java:
static string lookupNumber( string phoneNumber ) {
PhoneNumber parsed = PhoneNumberUtil.getInstance().parse( phoneNumber, /*defaultRegion:*/ "US" );
return PhoneNumberOfflineGeocoder.getInstance().getDescriptionForNumber( parsed, Locale.ENGLISH );
}
lookupNumber( "1-800-333-4567" ) // "United States"
lookupNumber( "+12012000000" ) // "Jersey City, NJ"
lookupNumber( "+14256669999" ) // "Washington State"
C#
static String LookupNumber( string phoneNumber ) {
PhoneNumber parsed = PhoneNumberUtil.GetInstance().Parse( phoneNumber, defaultRegion: "US" );
return PhoneNumberOfflineGeocoder.GetInstance().GetDescriptionForNumber( parsed, Locale.English );
}
LookupNumber( "1-800-333-4567" ) // "United States"
LookupNumber( "+12012000000" ) // "Jersey City, NJ"
LookupNumber( "+14256669999" ) // "Washington State"
I want to generate a uuid for my app i tried many things like wifi mac address , getting android id, serial number , creating pseudo uuid from device
android.os.Build properties .
i also came to know that java itself got Uuid creator class
java.util.UUID
by going through several articles and blogs i am little confused about this . i want to know that if two android device are creating uuid using this java class(java.util.UUID) will that be unique or is there any chance for duplication?
Also in some devices i was not able to find serial number using android.os.Build.SERIAL . is there alternative way to get serial number of device
Assuming you're using the java.util.UUID's randomUUID() function there's a theoretical chance of duplication, but it's incredibly remote. The ids generated are RFC4122 version-4 ids, which have 122 bits randomly set. That means there are 5.32 x 10^^36 possible values. For some perspective on that, if you had a billion devices, each generating a billion IDs per second, it would take roughly 168 billion years for them to finish (~10X the age of the universe).
So, yes, duplication is possible, but (assuming Java is using a high quality random number generator), the odds of it actually happening are so remote as to be meaningless.
to Get Device ID Use Telephoney U can use it here is it is
public static String deviceUDID(Context ctx) {
final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
final String tmDevice, tmSerial, androidId;
tmDevice = "" + tm.getDeviceId();
tmSerial = "" + tm.getSimSerialNumber();
androidId = "" +android.provider.Settings.Secure.getString(ctx.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());
String deviceId = deviceUuid.toString();
Log.d("Device Id", deviceId);
return deviceId;
}
Document structure (just for illustration)
Employee
{
name : "..",
age : ..,
addresses [
{
"street":"...",
"country":{
name:"..",
continent:"..",
Galaxy:".."
}
}
],
company:".."
}
Query -
I have just Addresses -> street (type String) and Addresses -> country -> name (type String). And i want to get all employees that match this criteria.
Address a1 = new Address();
a1.setStreet("bla bla");
Country c = new Country();
c.setName("sth");
a1.setCountry(c);
Query<Employee> q = ds.createQuery(Employee.class).field("addresses").hasThisElement(a1)
DOESN'T fetch results (when actually there is a real match). Looks like its because of partial "Country" document match. If i populate all fields of Country its getting results as expected.
Question #1 : Any workaround for above?
Question #2 : Address is an array and i can get multiple (address#street, country#name) pairs and again i want the list of employees that match given pairs.
Something like:
Query<Employee> q = ds.createQuery(Employee.class).field("addresses").hasThisElement(a1).field("addresses").hasThisElement(a2).field(..) // and so on
Note: i can breakdown address match something like this
Address a = new Address();
a.setStreet("bla bla");
q.createQuery(Employee.class).field("addresses").hasThisElement(a).field("addresses.country.name").equal("hoo");
BUT this will match Employee where street="bla bla" and country.name!="hoo" in address#1 and street!="bla bla" and country.name="hoo" in address #2. You get the point. I don't want such Employees to be returned.
Please let me know if this is possible. Thanks much.
It's possible. MongoDB has a special operator for situations like this called elemMatch. Morphia has support for it.
You are correct that the second approach is the right way (The first approach is trying to match the entire country, not the subkey). The only thing is you want to constrain it to a single element with both street and country.name matching. Not a document with a matching street and a matching country.name.
This doc page and this thread have some more information.
http://code.google.com/p/morphia/wiki/Query
http://groups.google.com/group/morphia/tree/browse_frm/month/2011-02/5bd3f654526fa30b?rnum=41&lnk=ol
Unfortunately I don't know morphia well, but hopefully that will give you enough information to solve it.