currently I have a code like this
public class Department {
public static final String MESSAGE_DEPARTMENT_CONSTRAINTS =
"Department names should only contain alphanumeric characters and spaces, and it should not be blank\n"
+ "Department names should start with a name, followed by 'Management'";
public static final String DEPARTMENT_VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*";
public final String fullDepartment;
public Department(String department) {
requireNonNull(department);
checkArgument(isValidDepartment(department), MESSAGE_DEPARTMENT_CONSTRAINTS);
fullDepartment = department;
}
/**
* Returns true if a given string is a valid department name.
*/
public static boolean isValidDepartment(String test) {
return (test.matches(DEPARTMENT_VALIDATION_REGEX) && (test.indexOf("Management") >= 0));
}
#Override
public String toString() {
return fullDepartment;
}
#Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof Department // instanceof handles nulls
&& fullDepartment.equals(((Department) other).fullDepartment)); // state check
}
#Override
public int hashCode() {
return fullDepartment.hashCode();
}
}
I would like the code to only allow only valid departments name to be created
Example:
Junior Management
Senior Management
However, now I'm facing a problem where the word Management can be placed at anywhere and it's still considered valid
Example:
Management
Management Junior
How can I ensure that the word Management is a requirement at the back of a department name when I'm creating a department? Thanks.
Just change this function to this:
public static boolean isValidDepartment(String test) {
return test.matches(DEPARTMENT_VALIDATION_REGEX)
&& test.endsWith("Management")
&& !test.equals("Management");
}
If you think you will need more sophisticated checks you can also change your department validation regex to:
public static final String DEPARTMENT_VALIDATION_REGEX = "(\\p{Alnum}+ )+Management";
public static boolean isValidDepartment(String test) {
return test.matches(DEPARTMENT_VALIDATION_REGEX);
}
Note that this will still allow "Management Management" and also "M8n8g3m3nt Management" since you used \\p{Alnum}. If you only need alphabet characters
use \\p{Alpha}. If you want to catch the exception of "Management Management" you might want to do:
public static boolean isValidDepartment(String test) {
return test.matches(DEPARTMENT_VALIDATION_REGEX)
&& !test.equals("Management Management");
}
You should be able to do it all through the regex, but might get too complicated and unreadable for just one exception you can easily check with .equals().
Two ways to do it
a. Using startsWith() and endsWith() in StringUtils ,or just startsWith() and endsWith() that String provides
boolean endsWith = StringUtils.endsWith("Managemet") && !StringUtils.startsWith("Managemet");
b. Using regex .*?Management$,in this expression using .*? to include space and other special characters
String str ="Test Management";
String regex = ".*?Management$";
System.out.println(str.matches(regex));
Related
I have the following java code:
...
public final class Constants {
...
public static class Languages {
...
public static class en_US {
public static final String VALIDATION_REGEX = "[a-zA-Z-' ]+";
...
}
public static class en_GB {
public static final String VALIDATION_REGEX = "[a-zA-Z-' ]+";
...
}
}
...
}
My problem is as follows:
I receive a text and a language, and I have to check, whether that text is written only with valid alphabetic characters of that given language.
My code so far is as follows:
...
public boolean isContentValid(String content, String language) {
Boolean isCorrect = false;
switch (language) {
...
case "en_US":
isCorrect = content.matches(Constants.Phrases.en_US.VALIDATION_REGEX);
break;
case "en_GB":
isCorrect = content.matches(Constants.Phrases.en_GB.VALIDATION_REGEX);
break;
...
default:
isCorrect = false;
}
return isCorrect;
}
...
This is fine and works, but as I add languages to my application, I will have to add more and more cases to my switch.
And I was wondering if in Java there is a way to dynamically name a static nested class, something like:
Constants.Phrases[language].VALIDATION_REGEX
So my above code could be something like:
...
public boolean isContentValid(String content, String language) {
return content.matches(Constants.Phrases[language].VALIDATION_REGEX);
}
...
Thank you, and sorry if this is something super easy.
I am a JavaScript developer, and just learning Java.
Looking at you use case maybe this is a better approach:
public enum Language {
en_US("engUS_reg"),
en_GB("engGB_reg");
private final String regex;
Language(String regex) {
this.regex = regex;
}
public String getRegex() {
return regex;
}
}
And using this enum class write your method as follows:
public boolean isContentValid(String content, String language) {
return content.matches(Language.valueOf(language).getRegex());
}
You could use an enum for something like this.
"An enum can, just like a class, have attributes and methods. The only difference is that enum constants are public, static and final (unchangeable - cannot be overridden)." - [w3][1]
public enum Languages {
EN_US {
#Override
public String toString() {
return "[a-zA-Z-' ]+";
}
},
EN_GB {
#Override
public String toString() {
return "[a-zA-Z-' ]+";
}
},
}
And then you can access these values like this
Languages.valueOf("EN_US");
As mentioned by #Pshemo you could avoid a class based approach entirely and use an implementation of Map if you want something a little more lightweight
[1]: https://www.w3schools.com/java/java_enums.asp#:~:text=An%20enum%20can%2C%20just%20like,but%20it%20can%20implement%20interfaces).
I have created a custom FEST Condition to verify that my actual string either matches or is equal to an expected String
public class StringMatchesOrIsEqualTo extends Condition<String>{
private String expectedStringOrExpression;
public StringMatchesOrIsEqualTo(final String expectedStringorExpression){
this.expectedStringOrExpression = expectedStringorExpression;
}
#Override
public boolean matches(String value) {
return value.matches(expectedStringOrExpression) || value.equals(expectedStringOrExpression);
}
}
Whenever the conditon fails i want it to display a message that shows me what the original and expected String was
currently the display string is
actual value:<'Some String'> should satisfy condition:<StringMatchesOrIsEqualTo>
is there a way that this message also displays what the match is made against ?
I tried overriding the toString method in the class
#Override
public String toString() {
return "string matches or is equal to : " + expectedStringOrExpression;
}
but that does not seem to work.
You want to set the description, which can be done by calling the Condition(String) constructor:
public StringMatchesOrIsEqualTo(final String expectedStringorExpression){
super("A String that matches, or is equal to, '" + expectedStringorExpression "'");
this.expectedStringOrExpression = expectedStringorExpression;
}
Alternatively, you could override description():
#Override
public String description()
{
return "A String that matches, or is equal to, '" + expectedStringorExpression "'");
}
I am looking for a better way of comparing two "lists". The idea is : I have 2 lists which are composed of Strings. My method returns true if all Strings from both lists matches. I.E
List(1) = "foo, foo1, foo2, foo3"
List(2) = "foo, foo1, foo2, foo3"
When comparing these two lists if ALL strings match then the method returns true. If any of the elements do not match then returns false.
Code which i have ( and works ) is this: however i was just wondering if any one could think of a better solution to this problem ?
private boolean match(Context messageContext, ContextRule contextRule) {
if(contextRule.getMessageContext().getUser().equals(ContextRuleEvaluator.WILDCARD)
|| (contextRule.getMessageContext().getUser().equals(messageContext.getUser()))) {
if(contextRule.getMessageContext().getApplication().equals(ContextRuleEvaluator.WILDCARD)
|| (contextRule.getMessageContext().getApplication().equals(messageContext.getApplication()))) {
if(contextRule.getMessageContext().getService().equals(ContextRuleEvaluator.WILDCARD)
|| (contextRule.getMessageContext().getService().equals(messageContext.getService()))) {
if(contextRule.getMessageContext().getOperation().equals(ContextRuleEvaluator.WILDCARD)
|| (contextRule.getMessageContext().getOperation().equals(messageContext.getOperation()))) {
return true;
}
}
}
}
return false;
}
Context
public interface Context {
public String getUser();
public void setUser(String user);
public String getApplication();
public void setApplication(String application);
public String getService();
public void setService(String service);
public String getOperation();
public void setOperation(String operation);
}
ContextRule
public interface ContextRule {
public Context getMessageContext();
public int getAllowedConcurrentRequests();
}
I think with a bit of refactoring and applying DRY, your approach would work as well as any other:
Move the matching logic inside the Context class:
#Override
public boolean match(Context anotherContext) {
return match(this.getUser(), anotherContext.getUser()) &&
match(this.getApplication(), anotherContext.getApplication()) &&
match(this.getService(), anotherContext.getService()) &&
match(this.getOperation(), anotherContext.getOperation());
}
private boolean match(String thisString, String thatString) {
return thisString.equals(WILDCARD) || thisString.equals(thatString);
}
Then use it:
private boolean match(Context messageContext, ContextRule contextRule) {
Context ruleContext = contextRule.getContext();
return ruleContext.match(messageContext);
}
the list implementation overrides the equals method.
Is there a requirement not to use this?
list1.equals(list2);
javadoc:
Compares the specified object with this list for equality. Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal. (Two elements e1 and e2 are equal if (e1==null ? e2==null : e1.equals(e2)).) In other words, two lists are defined to be equal if they contain the same elements in the same order. This definition ensures that the equals method works properly across different implementations of the List interface
This does the first two operations above, and calls each elements .equals(...) method to the others. So make sure you have properly overridden the equals method in your elements.
What you could do (but it would add unnecessary object creation):
private static boolean match(Context messageContext, ContextRule contextRule) {
Context ruleContext = contextRule.getMessageContext();
String[] interleaved = {
ruleContext.getUser(), messageContext.getUser(),
ruleContext.getApplication(), messageContext.getApplication(),
ruleContext.getService(), messageContext.getApplication(),
ruleContext.getOperation(), messageContext.getOperation()};
for (int i = 0; i < interleaved.length; i += 2) {
if (!interleaved[i].equals(ContextRuleEvaluator.WILDCARD) &&
!interleaved[i].equals(interleaved[i + 1]) {
return false;
}
}
return true;
}
It is possible to come up with many variants of this, but I think it would be hard to utilize list.equals() because you need to take the WILDCARD into account...
I would just rewrite the original check in a more concise form, utilizing a helper to reduce redundancy, e.g.
private static boolean matchValue(String ruleValue, String messageValue) {
return ruleValue.equals(ContextRuleEvaluator.WILDCARD)
|| ruleValue.equals(messageValue);
}
private static boolean match(Context messageContext, ContextRule contextRule) {
Context ruleContext = contextRule.getMessageContext();
return matchValue(ruleContext.getUser(), messageContext.getUser())
&& matchValue(ruleContext.getApplication(), messageContext.getApplication())
&& matchValue(ruleContext.getService(), messageContext.getService())
&& matchValue(ruleContext.getOperation(), messageContext.getOperation());
}
}
I have a Model class DOModel :
package amarsoft.dbmp.credit.web.model;
import ejp.annotations.ConcreteTableInheritance;
import amarsoft.rcp.base.databinding.BindableModel;
#ConcreteTableInheritance
public class DOModel extends BindableModel {
/**
* 编号
*/
private String id;
/**
* 名称
*/
private String name;
/**
* 模板类型,没有太大意义
*/
private String type;
/**
* 模板参数
*/
private String args;
private String updateTable;
private String updateWhere;
private String fromClause;
private String whereClause;
private String groupClause;
private String orderClause;
public String getId() {
return id;
}
public void setId(String id) {
this.firePropertyChange("id", this.id, this.id = id);
}
public String getName() {
return name;
}
public void setName(String name) {
this.firePropertyChange("name", this.name, this.name = name);
}
public String getType() {
return type;
}
public void setType(String type) {
this.firePropertyChange("type", this.type, this.type = type);
}
public String getArgs() {
return args;
}
public void setArgs(String args) {
this.firePropertyChange("args", this.args, this.args = args);
}
public String getUpdateTable() {
return updateTable;
}
public void setUpdateTable(String updateTable) {
this.firePropertyChange("updateTable", this.updateTable, this.updateTable = updateTable);
}
public String getDoUpdateWhere() {
return updateWhere;
}
public void setDoUpdateWhere(String doUpdateWhere) {
this.firePropertyChange("updateWhere", this.updateWhere, this.updateWhere = doUpdateWhere);
}
public String getFromClause() {
return fromClause;
}
public void setFromClause(String fromClause) {
this.firePropertyChange("fromClause", this.fromClause, this.fromClause = fromClause);
}
public String getWhereClause() {
return whereClause;
}
public void setWhereClause(String whereClause) {
this.firePropertyChange("whereClause", this.whereClause, this.whereClause = whereClause);
}
public String getGroupClause() {
return groupClause;
}
public void setGroupClause(String groupClause) {
this.firePropertyChange("groupClause", this.groupClause, this.groupClause = groupClause);
}
public String getOrderClause() {
return orderClause;
}
public void setOrderClause(String orderClause) {
this.firePropertyChange("orderClause", this.orderClause, this.orderClause = orderClause);
}
#Override
public String toString() {
return "DOModel [id=" + id + ", name=" + name + "]";
}
#Override
public int dataValueHashCode() {
int code = 0;
if (id != null) {
code += id.hashCode();
}
if(name != null){
code += name.hashCode();
}
if(type != null){
code += type.hashCode();
}
if(args != null){
code += args.hashCode();
}
if(updateTable != null){
code += updateTable.hashCode();
}
if(updateWhere != null){
code += updateWhere.hashCode();
}
if(fromClause != null){
code += fromClause.hashCode();
}
if(whereClause != null){
code += whereClause.hashCode();
}
if(groupClause != null){
code += groupClause.hashCode();
}
if(orderClause != null){
code += orderClause.hashCode();
}
return code;
}
}
this class is used in ORM, when one or more property of DOModel's instance is changed, I need to persist the DOModel's instance back to database.
so there is a problem for me: how can I know a DOModel instance object is modified compared to a specific time ?
please notice the method dataValueHashCode, I use a combination of the hash code of all the properties to measure if a model is changed.the basic flow is:
1.load the a DOModel object from database
2.call dataValueHashCode method and cache it
3.(optional)modify property values
4.when need to save the object back to database, call dataValueHashCode method again
and compare it to the cached one
5.if match, no change. if not match, save it back to database.
It seems that works right now, but as a java newbie, I am worrying there is potential problems. so before I go further, I want to prove my way will not lead me to a wrong place.
As a Chinese, my English is not good enough. if you have problem to understand what I am talking about, please post comment, I will try my best to edit this question.
thanks a lot!
There is something potentially wrong with that approach: two different objects may have the same hashCode value (the contract for hashcode is only that if a.equals(b) is true, then a.hashCode == b.hashCode, theoretically, all hashCodes could return 1 they would still be valid albeit inefficient)
So you need to come up with a cryptographic hash of yours that doesn't use hashcode, if you want to be absolutely certain it reflects your object change. I suggest using MD5 encryption, which (almost) uniquely identifies a string. It's not completely collision-resistant (means theoretically, there are multiple strings with the same output), but in practice, it's good enough.
http://en.wikipedia.org/wiki/MD5
It's quite easy to do in Java:
final MessageDigest messageDigest = MessageDigest.getInstance("MD5");
final byte[] data = stringToConvert.getBytes();
messageDigest.update(data,0,data.length);
final BigInteger hash = new BigInteger(1,messageDigest.digest());
return String.format("%1$032X", hash);
That sounds like you're relying on "equal hash codes imply equal objects" which is not safe to rely on.
Assuming a proper implementation of hashCode, you should be able to rely on "different hash codes mean unequal objects" - but the reverse is not true.
In particular, an implementation of:
#Override public int hashCode() {
return 0;
}
is always valid. Sucky, but valid.
If you want to be sure that there is no change you have to compare the contents of the attributes rather than the hash code. For that you should implement the equals method. The problem with the hash code is that though unlikely it can be the same value for different property values.
This is not the way to override hashCode(). Joshua Bloch tells you the correct way to do it in chapter 3 of his "Effective Java".
It seems that works right now, but as a Java newbie, I am worrying there is potential problems.
It's not a safe approach: A change in an object, does not guarantee that the objects hash code changes.
Keep in mind that a hash code is simply an int. If your object have more than 232 states (as in your case) you are bound to have hash collisions.
A few more pointers regarding your code:
When overriding hashCode, you need to also override equals.
Your hashCode implementation is not very good (it doesn't provide a very good distribution)
So I have this method that get executed repeatedly
public static boolean isReady(String dirPath, int numPdfInPrintJob){
File dir = new File(dirPath);
String[] fileList = dir.list(new FilenameFilter(){
public boolean accept(File file, String filename) {
return (filename.toLowerCase().endsWith(".pdf"));
}
});
if(fileList.length >= numPdfInPrintJob) return true;
else return false;
}
This method using anonymous class that will create a new instance of FilenameFilter every time invoked and I invoke this method a lot. So I want to make this anonymous class into a singleton. So my initial thought is to create a new singleton class that look like this
public class PdfFileNameFilter implements FilenameFilter{
private PdfFileNameFilter(){} //non-instantible
//guarantee to only have one instance at all time
public static final PdfFileNameFilter INSTANCE = new PdfFileNameFilter();
public boolean accept(File dir, String name) {
return (name.toLowerCase().endsWith(".pdf"));
}
}
Can I refactor this a bit more. I need to do ZipFileNameFilter as well, and maybe many different file extension filter. Dont want to create a class for each filter. I need to refactor this design a bit more. Maybe interface come into place somewhere here.
If all you wanted to do was reduce memory usage you could have done
private static final FilenameFilter PDF_FILES = new FilenameFilter(){
public boolean accept(File file, String filename) {
return (filename.toLowerCase().endsWith(".pdf"));
}
}
If you want to create a singleton, the simplest way is
public enum PdfFileNameFilter implements FilenameFilter {
INSTANCE;
public boolean accept(File dir, String name) {
return (name.toLowerCase().endsWith(".pdf"));
}
}
It seems simpler to me to just use your existing anonymous class and make one instance that all your method invocations use.
private static final FilenameFilter PDF_FILTER = new FilenameFilter() {
public boolean accept(File file, String filename) {
return (filename.toLowerCase().endsWith(".pdf"));
}
}
public static boolean isReady(String dirPath, int numPdfInPrintJob){
File dir = new File(dirPath);
String[] fileList = dir.list(pdfFilter);
if(fileList.length >= numPdfInPrintJob) return true;
else return false;
}
This is a case where subclassing and making a singleton seems to be a tad overkill: you simply want only one instance to use right here, whereas a singleton is used when there is only one instance you will ever want to use.
You could use an enum for this:
public enum ExtensionFilter implements FilenameFilter {
PDF(".pdf"),
ZIP(".zip");
private final String extension;
private ExtensionFilter(String extension) {
this.extension = extension;
}
#Override
public boolean accept(File dir, String name) {
return (name.toLowerCase().endsWith(extension));
}
}
Now you'll be able to use it like:
dir.list(ExtensionFilter.PDF)
You can also iterate through them if you need:
for ( FilenameFilter fileNameFilter : ExtensionFilter.values() ) {
....
}
You could also use a vararg as constructor argument to allow multiple extensions for the same filter and use the constant name as the default to make it simpler to use:
public enum ExtensionFilter implements FilenameFilter {
PDF,
ZIP(".zip", ".jar", ".war", ".ear");
private final String[] extensions;
private ExtensionFilter(String... extensions) {
if (extensions.length == 0) {
extensions = new String[] {"." + name().toLowerCase()};
}
this.extensions = extensions;
}
#Override
public boolean accept(File dir, String name) {
for (String extension : extensions) {
if (name.toLowerCase().endsWith(extension)) {
return true;
}
}
return false;
}
}
you can step away from the full singleton and use a private field to set up the extension
public class ExtensionFileNameFilter implements FilenameFilter{
private String extension;
private ExtensionFileNameFilter (String extension){this.extension=extension;}
public static final ExtensionFileNameFilter PDFINSTANCE = new ExtensionFileNameFilter (".pdf");
public static final ExtensionFileNameFilter ZIPINSTANCE = new ExtensionFileNameFilter (".zip");
//add instances as you need
public boolean accept(File dir, String name) {
return (name.toLowerCase().endsWith(extension));
}
}
Can I refactor this a bit more.
Yes, yes you can.
Assuming that wasn't the answer you were looking for (you should update yoru question to ask a more specific question), I wouldn't refactor it until you need it; YAGNI.
Once you have more code, like more FilenameFilters, is when you will see the possible refactorings. You will see common code, maybe an interface, stuff like that. Don't try to pre-maturely over-engineeer.
TDD is also the best way to do refactoring safely. If you have tests showing what code you actually need, lots of the extra stuff goes away, if any. And with a comprehensive test suite, you can refactor without hesitation because you know if your changes work or not based on whether your tests continue to pass.
For interest, this alternative accept implementation would run much faster in a benchmark test. It does not create new stateful Objects or carry the other overhead of String.toLowerCase, which is not required for your case.
public boolean accept(File file, String filename) {
int offset = s.length() - 4;
if (offset >= 0) {
if (s.charAt(offset) == '.') {
offset += 1;
if (s.regionMatches(offset, "pdf", 0, 3)) {
return true;
} else if (s.regionMatches(offset, "PDF", 0, 3)) {
return true;
}
}
}
return false;
}
If this was an execution hotspot and you were looking for optimization, something like that would help.