Java String Limit - java

I am new to java (previously only worked with sql) and I am attempting to set a length limit for my string variable. Basically I have a username field that can only be 6 characters long.
I am trying the following:
private String username (6);
I am assuming this is not the correct format. Does anyone know how i can do this in java correctly?

Some other answers have claimed that "There is no way to limit Strings in java to a certain finite number through inbuilt features", and suggested rolling ones own. However, Java EE validations API is meant for just this. An example:
import javax.validation.constraints.Size;
public class Person {
#Size(max = 6)
private String username;
}
Further info on how to use Validation API, see this thread for example. Hibernate validator is the reference implementation (usage).
In short, when annotating an object as #Valid, validations done in annotations will be enforced.

There is no way to limit Strings in java to a certain finite number through inbuilt features. Strings are immutable and take the value that you provide in their constructor. You will need to write code manually to do this.
Use the length() function to determine the length of the String and do not allow lengths greater than 6.
if( username.length() > 6 )
{
throw new RuntimeException("User name too long");
}
One of the options you have is to throw an exception and then handle it elsewhere. Or you can display an alert to the user immediately after you encounter the problem.

What you suggested is not the correct way to do what you want. Try using:
private int stringLimit = 6;
// Take input from user
private String username = inputString.substring(0,stringLimit);
For example:
inputString = "joelspolsky";
private String username = inputString.substring(0,stringLimit);
// username is "joelsp"

You can try soemthing like this:Take input from user then validate that string by using following function.
String output ="";
public boolean set(String str, int limit){
if(str.length() <= limit){
output= str;
return true;
}
else
return false;
}

SubString() won't be suitable for this. If the length of input string is less than limit StringIndexOutOfBoundsException will be thrown.
I think you can use StringBuilder for this.
StringBuilder buider = new StringBuilder(username);
builder.setLength(6);
String restName = builder.toString().trim();

In this case annotation mechanism can be useful, if, of course, you know what this is.
You can create your own annotation, something like:
#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
public #interface MaxLength {
int value();
}
And use it like:
#MaxLength(6)
private String username;
Then you have to post-process such objects in a special post-processor, which you have to create manually.

example to cut the length of URL
if (getURLitem.length() >= 15) {
int stringLimit = 15;
final String smallURL = getURLitem.substring(0, stringLimit);
//show short string in textview...
TextView urlLink = (TextView) findViewById(R.id.url_link);
urlLink.setText(smallURL);
// Set On click listener and open URL below
...........
} else {
//show full string in textview...
TextView urlLink = (TextView) findViewById(R.id.url_link);
urlLink.setText(getURLitem);
// Set On click listener and open URL below
...........
}

Related

How to implement this property file?

I have this piece of data (this is just one part of one line of the whole file):
000000055555444444******4444 YY
I implemented this CSV config file to be able to read each part of the data and parse it:
128-12,140-22,YY
The first pair (128-12) represent at what position in the line to start reading and then the amount of characters to read, that first pair is for the account number.
The second pair if for the card number.
And the thir parameter is for the registry name.
Anyways, what I do is String.split(","), and then assign the array[0] as the account number and so on.
But I want to change that CSV config file to a Property file, but I'm not sure of how to implement that solution, if I use a Properties file I'd have to add a bunch of if/then in order to properly map my values, here's what I'm thinking of doing:
Property cfg = new Property();
cfg.put("fieldName", "accountNumber");
cfg.put("startPosition", "128");
cfg.put("length", "12");
But I'd have to say if("fieldName".equals("accountNumber")) then assign accountNumber; is there a way to implement this in such a way that I could avoid implementing all this decisions? right now with my solution I don't have to use ifs, I only say accountNumber = array[0]; and that's it, but I don't think that's a good solution and I think that using Property would be more elegant or efficient
EDIT:
This probably needs some more clarification, this data I'm showing is part of a parsing program that I'm currently doing for a client; the data holds information for many many of their customers and I have to parse a huge mess of data that I receive from them, into something more readable in order to convert it to a PDF file, so far the program is under production but I'm trying to refactor it a little bit. All the customer's information is saved into different Registry classes, each class having it's own set of fields with unique information, lets say that this is what RegistryYY would look like:
class RegistryYY extends Registry{
String name;
String lastName;
PhysicalAddress address;
public RegistryYY(String dataFromFile) {
}
}
I want to implement the Property solution, because in that way, I could make the Property for parsing the file, or interpreting the data correctly to be owned by each Registry class, I mean, a Registry should know what data it needs from the data received from the file right?, I think that if I do it that way, I could make each Registry an Observer and they would decide if the current line read from the file belongs to them by checking the registry name stored in the current line and then they'd return an initialized Registry to the calling object which only cares about receiving and storing a Registry class.
EDIT 2:
I created this function to return the value stored in each line's position:
public static String getField(String fieldParams, String rawData){
// splits the field
String[] fields = fieldParams.split("-");
int fieldStart = Integer.parseInt(fields[0]); // get initial position of the field
int fieldLen = Integer.parseInt(fields[1]); // get length of field
// gets field value
String fieldValue = FieldParser.getStringValue(rawData, fieldStart, fieldLen);
return fieldValue;
}
Which works with the CSV file, I'd like to change the implementation to work with the Property file instead.
Is there any reason why you need to have the record layout exposed to the outside world ? does it need to be configurable ?
I think your proposed approached of using the Property file is better than your current approach of using the CSV file since it is more descriptive and meaningful. I would just add a "type" attribute to your Property definition as well to enforce your conversion i.e. for Numeric/String/Date/Boolean.
I wouldnt use an "if" statement to process your property file. You can load all the properties into an Array at the beginning and then iterate around the array for each line of your data file and process that section accordingly something like pseudo code below,
for each loop of data-file{
SomeClass myClass = myClassBuilder(data-file-line)
}
myClassBuilder SomeClass (String data-file-line){
Map<column, value> result = new HashMap<>
for each attribute of property-file-list{
switch attribute_type {
Integer:
result.put(fieldname, makeInteger(data-file-line, property_attribute)
Date:
result.put(fieldname, makeDate(data-file-line, property_attribute)
Boolean :
result.put(fieldname, makeBoolean(data-file-line, property_attribute)
String :
result.put(fieldname, makeBoolean(data-file-line, property_attribute)
------- etc
}
}
return new SomeClass(result)
}
}
If your record layout doesnt need to be configurable then you could do all the conversion inside your Java application only and not even use a Property file.
If you could get your data in XML format then you could use the JAXB framework and simply have your data definition in an XML file.
First of all, thanks to the guys who helped me, #robbie70, #RC. and #VinceEmigh.
I used YAML to parse a file called "test.yml" with the following information in it:
statement:
- fieldName: accountNumber
startPosition: 128
length: 12
- fieldName: cardNumber
startPosition: 140
length: 22
- fieldName: registryName
startPosition: 162
length: 2
This is what I made:
// Start of main
String fileValue = "0222000000002222F 00000000000111110001000000099999444444******4444 YY";
YamlReader reader = new YamlReader(new FileReader("test.yml"));
Object object = reader.read();
System.out.println(object);
Map map = (Map) object;
List list = (List) map.get("statement");
for(int i = 0; i < list.size(); i++) {
Map map2 = (Map) list.get(i);
System.out.println("Value: " + foo(map2, fileValue));
}
}
// End of main
public static String foo(Map map, String source) {
int startPos = Integer.parseInt((String) map.get("startPosition"));
int length = Integer.parseInt((String) map.get("length"));
return getField(startPos, length, source);
}
public static String getField(int start, int length, String source) {
return source.substring(start, start+length);
}
It correctly displays the output:
Value: 000000099999
Value: 444444******4444
Value: YY
I know that maybe the config file has some lists and other unnecessary values and what nots, and that maybe the program needs a little improvement, but I think that I can take it from here and implement what I had in mind.
EDIT:
I made this other one, using Apache Commons, this is what I have in the configuration property file:
#properties defining the statement file
#properties for account number
statement.accountNumber.startPosition = 128
statement.accountNumber.length = 12
statement.account.rules = ${statement.accountNumber.startPosition} ${statement.accountNumber.length}
#properties for card number
statement.cardNumber.startPosition = 140
statement.cardNumber.length = 22
statement.card.rules = ${statement.cardNumber.startPosition} ${statement.cardNumber.length}
#properties for registry name
statement.registryName.startPosition = 162
statement.registryName.length = 2
statement.registry.rules = ${statement.registryName.startPosition} ${statement.registryName.length}
And this is how I read it:
// Inside Main
String valorLeido = "0713000000007451D 00000000000111110001000000099999444444******4444 YY";
Parameters params = new Parameters();
FileBasedConfigurationBuilder<FileBasedConfiguration> builder =
new FileBasedConfigurationBuilder<FileBasedConfiguration>(PropertiesConfiguration.class)
.configure(params.properties()
.setFileName("config.properties"));
try {
Configuration config = builder.getConfiguration();
Iterator<String> keys = config.getKeys();
String account = getValue(getRules(config, "statement.account.rules"), valorLeido);
String cardNumber = getValue(getRules(config, "statement.card.rules"), valorLeido);
String registryName = getValue(getRules(config, "statement.registry.rules"), valorLeido);
} catch (org.apache.commons.configuration2.ex.ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// End of Main
public static String getRules(Configuration config, String rules) {
return config.getString(rules);
}
public static String getValue(String rules, String source) {
String[] tokens = rules.split(" ");
int startPos = Integer.parseInt(tokens[0]);
int length = Integer.parseInt(tokens[1]);
return getField(startPos, length, source);
}
I'm not entirely sure, I think that with the YAML file it looks simpler, but I really like the control I get with the Apache Commons Config, since I can pass around the Configuration object to each registry, and the registry knows what "rules" it wants to get, let's say that the Registry class only cares about "statement.registry.rules" and that's it, with the YAML option I'm not entirely sure of how to do that yet, maybe I'll need to experiment with both options a little bit more, but I like where this is going.
PS:
That weird value I used in fileValue is what I'm dealing with, now add nearly 1,000 characters to the length of the line and you'll understand why I want to have a config file for parsing it (don't ask why....clients be crazy)

How to say String A > String B in Java

I'm working on a small program to compare service levels, the user will input the service level 2 times (current and requested) and then the input will be scanned and compared and show a message.
For example:
current = 9*5 NBD (a)
requested = 24*7 SBD (b)
I want to know how in Java I can tell the compiler that (b) is greater than (a)
Because I want to use if statement like this
if (b > a) then show message.
I tried to use string.equals, but didn't help me too much.
I was not successful to convert string to number to do such comparison.
Try following statement
if(a.compareTo(b) > 0);
First thing: you can't override String.compareTo(), because it's final. you can create class with String field and write compareTo() for this class. This is not best idea.
But you can compare two strings by putting them into array and creating implementation of Comparator interface in sort() method.
String current = "9*5 NBD";
String requested = "24*7 SBD";
String[] test = {current, requested};
Arrays.sort(test, new Comparator<String>() {
#Override
public int compare(String o1, String o2) {
//Your impl goes here
return 0;
}
});
Where do these strings come from? Surely they must be from some kind of table that contains the service level details together with the cost of subscribing to that service level. What you want to check is whether the required service level costs more than the service level the client already has. Suppose the service level details come from a Map<ServiceLevel, BigDecimal> that gives the cost for a certain service level. Then all you need to do is:
BigDecimal costOfCurrentSL = serviceLevelCosts.get(currentSL);
BigDecimal costOfRequiredSL = serviceLevelCosts.get(requiredSL);
if (costOfRequiredSL.compareTo(costOfCurrentSL) > 0) {
// ... tell client he needs to purchase a top-up
}
Thank you all for the willing to help :)
After a lot of thinking I found another way which helped me a lot
I created 2 new integers and called them Values of what I need.
and used if statement, that if the entered is 9*5 NBD so the value will be zero, and if it is SBD, the value will be 1 and so on, then created new if statement to compare the values and show me a message if the A is greater than B, and it really worked.
Here is a part of my code
String WA_SLA = "", REQ_SLA = "";
int Va_WA_SLA = 0, Va_REQ_SLA = 0;
if(WA_SLA.equalsIgnoreCase("9*5 SBD"))
{
Va_WA_SLA = 1;
}
if(REQ_SLA.equalsIgnoreCase("9*5 NBD"))
{
Va_REQ_SLA = 0;
}
if(Va_WA_SLA > Va_REQ_SLA)
{
JOptionPane.showMessageDialog(frame,"Warranty SLA is Higher than Requested SLA " ,null, JOptionPane.INFORMATION_MESSAGE);
}
Thaaaaaaaaaaaaank you a lot

How do I call this object to return all strings it finds?

I have the following code that defines a getParts method to find a given Part Name and Part Number in the system. Note that this code comes from our system's API, so if no one can help I'll just delete this question. I figured someone could potentially see a solution or help me along the way.
<%! private QueryResult getParts( String name, String number )
throws WTException, WTPropertyVetoException {
Class cname = wt.part.WTPart.class;
QuerySpec qs = new QuerySpec(cname);
QueryResult qr = null;
qs.appendWhere
(new SearchCondition(cname,
"master>name",
SearchCondition.EQUAL,
name,
false));
qs.appendAnd();
qs.appendWhere
(new SearchCondition(cname,
"master>number",
SearchCondition.EQUAL,
number,
false));
qr = PersistenceHelper.manager.find(qs);
System.out.println("...found: " + qr.size());
return qr;
}
%>
But I would like to allow the user more flexibility in finding these parts. So I set up conditional statements to check for a radio button. This allows them to search by part name and part number, find all, or search using a wildcard. However, I'm having trouble implementing the two latter options.
To attempt to accomplish the above, I have written the below code:
<%
String partName = request.getParameter("nameInput");
String partNumber = request.getParameter("numberInput");
String searchMethod = request.getParameter("selection");
//out.print(searchMethod);
QueryResult myResult = new QueryResult();
if(searchMethod.equals("search"))
myResult = getParts(partName, partNumber);
else if(searchMethod.equals("all"))
{
//Should I write a new function and do this?
//myResult = getAllParts();
//or is there a way I could use a for each loop to accomplish this?
}
//else if(searchMethod.equals("wildcard"))
//get parts matching %wildcard%
while(myResult.hasMoreElements())
{
out.print(myResult.nextElement().toString());
}
%>
Basically, it accepts user input and checks what type of search they would like to perform. Is there an easy way to pass all the values into the myResult object? And likewise for the wildcard search? Like I said before, it may be futile trying to help without access to the API, but hopefully it isn't.
Thanks!
You can (and should) reuse the function, but in order to do so, you will need a part name and number (as those are its input parameters). So for the multi-result options you will need to get a list/collection of part names+numbers and feed them individually to the function, then collect the result in the format that is most appropriate for your needs

Non-Confusing Simple Validation of email in Java String

I am trying to find a simple method to check to see if a user's input meets a couple criteria for an email address. I've read through many threads on this subject and most seem to want to validate the email address too. I'm not trying to build some super duper email address validator/checker. I'm trying to build a method that checks for these things:
The string entered by the user contains the '#' sign.
There are at least two characters before the '#' sign.
There is a '.' after the at sign followed by only three characters. The domain name can be as long as needed, but the string must end with "._ _ _". As in ".com" or ".net"...
I understand that this is not an all encompassing email address checker. That's not what I want though. I want just something this simple. I know that this is probably a routine question but I can't figure it out even after reading all of the seriously crazy ways of validating an email address.
This is the code I have so far: (Don't worry I already know it's pretty pathetic.... )
public static void checkEmail()
{
validEmail(emailAddresses);
if(validEmail(emailAddresses))
{
}
}
public static boolean validEmail(String email) {
return email.matches("[A-Z0-9._%+-][A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{3}");
}
The javax.mail package provides a class just for this: InternetAddress. Use this constructor which allows you to enforce RFC822 compliance.
Not perfect, but gets the job done.
static boolean validEmail(String email) {
// editing to make requirements listed
// return email.matches("[A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{2,4}");
return email.matches("[A-Z0-9._%+-][A-Z0-9._%+-]+#[A-Z0-9.-]+\\.[A-Z]{3}");
}
void checkEmails() {
for(String email : emailAddresses) {
if(validEmail(email)) {
// it's a good email - do something good with it
}
else {
// it's a bad email - do something... bad to it? sounds dirty...
}
}
}
int indexOfAt = email.indexOf('#');
// first check :
if (indexOfAt < 0) {
// error
}
// second check :
if (indexOfAt < 2) {
// error
}
// third check :
int indexOfLastDot = email.lastIndexOf('.');
if (indexOfLastDot < indexOfAt || indexOfLastDot != (email.length() - 4)) {
// error
}
Read http://download.oracle.com/javase/6/docs/api/java/lang/String.html for the documentation of the String methods.

jline multi-argument parsing

I am trying to get JLine to do tab completion so I can enter something like the following:
commandname --arg1 value1 --arg2 value2
I am using the following code:
final List<Completor> completors = Arrays.asList(
new SimpleCompletor("commandname "),
new SimpleCompletor("--arg1"),
new SimpleCompletor("--arg2"),
new NullCompletor());
consoleReader.addCompletor(new ArgumentCompletor(completors));
But after I type the value2 tab completion stops.
(Suplementary question, can I validate value1 as a date using jline?)
I had the same problem, and I solved it by creating my own classes to complete the commands with jLine. I just needed to implement my own Completor.
I am developing an application that could assist DBAs to type not only the command names, but also the parameters. I am using jLine for just for the Terminal interactions, and I created another Completor.
I have to provide the complete grammar to the Completor, and that is the objective of my application. It is called Zemucan and it is hosted in SourceForge; this application is initially focused to DB2, but any grammar could be incorporated. The example of the Completor I am using is:
public final int complete(final String buffer, final int cursor,
#SuppressWarnings("rawtypes") final List candidateRaw) {
final List<String> candidates = candidateRaw;
final String phrase = buffer.substring(0, cursor);
try {
// Analyzes the typed phrase. This is my program: Zemucan.
// ReturnOptions is an object that contains the possible options of the command.
// It can propose complete the command name, or propose options.
final ReturnOptions answer = InterfaceCore.analyzePhrase(phrase);
// The first candidate is the new phrase.
final String complete = answer.getPhrase().toLowerCase();
// Deletes extra spaces.
final String trim = phrase.trim().toLowerCase();
// Compares if they are equal.
if (complete.startsWith(trim)) {
// Takes the difference.
String diff = complete.substring(trim.length());
if (diff.startsWith(" ") && phrase.endsWith(" ")) {
diff = diff.substring(1, diff.length());
}
candidates.add(diff);
} else {
candidates.add("");
}
// There are options or phrases, then add them as
// candidates. There is not a predefined phrase.
candidates.addAll(this.fromArrayToColletion(answer.getPhrases()));
candidates.addAll(this.fromArrayToColletion(answer.getOptions()));
// Adds a dummy option, in order to prevent that
// jLine adds automatically the option as a phrase.
if ((candidates.size() == 2) && (answer.getOptions().length == 1)
&& (answer.getPhrases().length == 0)) {
candidates.add("");
}
} catch (final AbstractZemucanException e) {
String cause = "";
if (e.getCause() != null) {
cause = e.getCause().toString();
}
if (e.getCause() != null) {
final Throwable ex = e.getCause();
}
System.exit(InputReader.ASSISTING_ERROR);
}
return cursor;
This is an extract of the application. You could do a simple Completor, and you have to provide an array of options. Eventually, you will want to implement your own CompletionHandler to improve the way that the options are presented to the user.
The complete code is available here.
Create 2 completors, then use them to complete arbituary arguments. Note that not all the arguments need to be completed.
List<Completer> completors = new LinkedList<>();
// Completes using the filesystem
completors.add(new FileNameCompleter());
// Completes using random words
completors.add(new StringsCompleter("--arg0", "--arg1", "command"));
// Aggregate the above completors
AggregateCompleter aggComp = new AggregateCompleter(completors);
// Parse the buffer line and complete each token
ArgumentCompleter argComp = new ArgumentCompleter(aggComp);
// Don't require all completors to match
argComp.setStrict(false);
// Add it all together
conReader.addCompleter(argComp);
Remove the NullCompletor and you will have what you want. NullCompletor makes sure your entire command is only 3 words long.

Categories

Resources