Selecting Substring from last - substring

i have this path
C:\Users\sspl\Desktop\worldtaxi_14_march_2014_new\worldtaxi_12_march_2014_new\o_logo\img1.png
i want to select o_logo\img1.png from last of that string
how to do that
any help that will be appreciated.

in c# you can do this as
string str = #"folder2\folder2\o_logo\img1.png";
string sub = str.Substring(str.Substring(0,str.LastIndexOf(#"\")).LastIndexOf(#"\") + 1);
Hope it will help you.

We may use Java String class's split method to get the required output
public class GetFilename {
/**
* #param args
*/
private String instr = "C:\\Users\\sspl\\Desktop\\worldtaxi_14_march_2014_new\\worldtaxi_12_march_2014_new\\o_logo\\img1.png";
//private String instr = "C:/Users/sspl/Desktop/worldtaxi_14_march_2014_new/worldtaxi_12_march_2014_new/o_logo/img1.png";
private String getFileName(){
String filename="";
String[] splitarr = instr.split("\\\\");
//String[] splitarr = instr.split("/");
int splitarrlen = splitarr.length;
filename = splitarr[splitarrlen-2]+"\\"+splitarr[splitarrlen-1];
return filename;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
GetFilename gfn = new GetFilename();
System.out.println(gfn.getFileName());
}
}
Care must be taken while using regular expressions. String's split method takes a regular expression as input. Special characters need to be escaped with a backward slash. Also it is better to use forword slash(/) as path seperator. To understand the simplicity of using "/" instead of "\" uncomment the lines which are commented, and also comment the previous line.

Related

What is the purpose of the line "public Word(#NonNull String word) {this.mWord = word;}" in this example?

I'm trying to figure out how to use Android's Room library for implementing a prepopulated sqlite database in my app and I came across this Android tutorial. One of the lines (the one in the title) confuses me though, because in another tutorial (also by Android), this line isn't present. Why is this line of code present in the first tutorial but not the second? What is its purpose?
I ask this because my code (which I'm basing off the second tutorial) doesn't include this line and yet this post by a different user attempting to do something similar with a prepopulated database does include it.
Here is some of the code I have (each of the fields has a getter method which just returns this.thatfield'sname):
#Entity (tableName = "words")
public class Words {
#PrimaryKey
#NonNull
#ColumnInfo (name = "word_id")
private int wordId;
#ColumnInfo(name = "a_words")
private String aWords;
#ColumnInfo(name = "b_words")
private String bWords;
#ColumnInfo(name = "c_words")
private String cWords;
This code gives me a "Cannot find setter for field" but just changing the fields from public to private seems to solve that (not sure if this is the best way to solve this error, though).
Why is this line of code present in the first tutorial but not the second?
That line is an additional class constructor that takes 1 non-null String and sets the mWord member/variable to the provided String.
Without then you can only use myWord = new Word(); to instantiate a Word object and the value would be either the default value if provided or null.
With the additional constructor then you could use both
myWord = new Word();
or
myOtherWord = new Word("A Word");
So, in short it's provided an alternative way of constructing/instantiating a new Object of that Class.
Using your code then you could have, for example :-
#Entity(tableName = "words")
class Words {
#ColumnInfo(name = "word_id")
#PrimaryKey
private int wordId;
#ColumnInfo(name = "a_words")
String aWords;
#ColumnInfo(name = "b_words")
String bWords;
#ColumnInfo(name = "c_words")
String cWords;
public void setWordId(int wordId, String aWord, String bWords, String c) {
this.wordId = wordId;
this.aWords = aWord;
this.bWords = bWords;
this.cWords = c;
}
}
Note for demonstration the parameter names use 3 different standards, ideally you would stick to a single standard/convention for naming the parameters.
So now you could use the one constructor that expects 4 parameters e.g.
myWord = new Words(1,"Apple","Banana","Cherry");
which equates to
myWord = new Words();
myWord.wordId = 1;
myWord.aWords = "Apple;
myWord.bWords = "Banana";
myWord.cWords = "Cherry";
As you have specified a constructor, the default constructor is no longer usable.
What is its purpose?
As can be seen, additional constructors, can reduce the amount of coding, there use will also prompt for the values (hence the use of useful parameter names improves i.e. c as above is not very meaningful at all (although in conjunction with the other parameters if would be better than x))

Constructor not defined error after setting date fields as null during object creation

I have created a wrapper class to create an Object and send it as a request to a third party system. It was working well. But after I added a two new arguments of the Datatype Date, I am getting the below error.
Constructor not defined: [SFDC_DataObject.CustomerAccountObject].<Constructor>(Id, String, Id, String, Id, String, Integer, NULL, String, String, Id, String, NULL, String, String, String, String)
The request that I am creating and sending is as below.
SFDC_DataObject.CustomerAccountObject cusAccObj = new SFDC_DataObject.CustomerAccountObject(o.AccountId, o.Customer_Name__c, o.Agency_Name__r.Id,o.Agency_Name_OB__c, o.Opportunity.OwnerId, o.Opportunity.Owner.FederationIdentifier, PrimarySalesSplitPercent, null, secSOSalesforceId.get(o.OpportunityId), secSOSalesforceEmail.get(o.OpportunityId), o.Opportunity.Customer_Success_Manage__r.Id, o.Opportunity.Customer_Success_Manage__r.FederationIdentifier, null, o.Billing_Email__c, o.Billing_Phone__c, o.Bill_To_Name__c, o.Billing_Notes__c);
My wrapper class for the same object is as below.
public class CustomerAccountObject {
public String sfCustomerId;
public String customerName;
public String sfAgencyId;
public String agencyName;
public String sfPrimarySalesOwnerId;
public String primarySalesOwnerEmail;
public Integer primarySalesOwnerPercentage;
public Date primarySalesOwnerEffectiveFrom;
public String sfSecondarySalesOwnerId;
public String secondarySalesOwnerEmail;
public Date secondarySalesOwnerEffectiveFrom;
public String sfAccountManagerId;
public String accountManagerEmail;
public String billingEmail;
public String billingPhone;
public String billingName;
public String billingNotes;
public CustomerAccountObject() {}
public CustomerAccountObject(String sfCustomerId, String customerName, String sfAgencyId, String agencyName, String sfPrimarySalesOwnerId, String primarySalesOwnerEmail, Integer primarySalesOwnerPercentage, Date primarySalesOwnerEffectiveFrom, String sfSecondarySalesOwnerId, String secondarySalesOwnerEmail, Date secondarySalesOwnerEffectiveFrom, String sfAccountManagerId, String accountManagerEmail, String billingEmail, String billingPhone, String billingName, String billingNotes) {
this.sfCustomerId = sfCustomerId;
this.customerName = customerName;
this.sfAgencyId = sfAgencyId;
this.agencyName = agencyName;
this.sfPrimarySalesOwnerId = sfPrimarySalesOwnerId;
this.primarySalesOwnerEmail = primarySalesOwnerEmail;
this.primarySalesOwnerPercentage = primarySalesOwnerPercentage;
this.primarySalesOwnerEffectiveFrom = primarySalesOwnerEffectiveFrom;
this.sfSecondarySalesOwnerId = sfSecondarySalesOwnerId;
this.secondarySalesOwnerEmail = secondarySalesOwnerEmail;
this.secondarySalesOwnerEffectiveFrom = secondarySalesOwnerEffectiveFrom;
this.sfAccountManagerId = sfAccountManagerId;
this.accountManagerEmail = accountManagerEmail;
this.billingEmail = billingEmail;
this.billingPhone = billingPhone;
this.billingName = billingName;
this.billingNotes = billingNotes;
}
}
I began getting the error after I added the null for the Date arguments I.e primarySalesOwnerEffectiveFrom and secondarySalesOwnerEffectiveFrom during the Object creation.
Can anyone please let me know what am I doing wrong here.
The order is wrong.
In c-tor definition you have
String sfCustomerId, String customerName, String sfAgencyId, String
agencyName, String sfPrimarySalesOwnerId, String
primarySalesOwnerEmail, Integer primarySalesOwnerPercentage, Date
primarySalesOwnerEffectiveFrom, String sfSecondarySalesOwnerId, String
secondarySalesOwnerEmail, Date secondarySalesOwnerEffectiveFrom + 6 more Strings
So
... Integer, Date, String, String, Date, ...
But the code that calls it goes
o.AccountId, o.Customer_Name__c,
o.Agency_Name__r.Id,o.Agency_Name_OB__c, o.Opportunity.OwnerId,
o.Opportunity.Owner.FederationIdentifier, PrimarySalesSplitPercent,
null, secSOSalesforceId.get(o.OpportunityId),
secSOSalesforceEmail.get(o.OpportunityId),
o.Opportunity.Customer_Success_Manage__r.Id,
o.Opportunity.Customer_Success_Manage__r.FederationIdentifier, null, +
4 strings
There are extra 2 strings before 2nd null. And only 4 strings after it. You need to inject that null just after secSOSalesforceEmail?
This will get only worse to maintain as time goes on. Consider making a simple constructor and making the properties public. You could then set them after constructor in normal call. And if you don't need dates you just don't write line that sets date fields instead of injecting null at right position.
Follow-up edit
Not sure if there's an official guide to that technique or a blog post. Tools like Apex-PMD complain when you make methods with too many arguments, rules like "Avoid long parameter lists".
One way would be to do something like this:
SFDC_DataObject.CustomerAccountObject cusAccObj = new SFDC_DataObject.CustomerAccountObject();
cusAccObj.sfCustomerId = o.AccountId;
cusAccObj.customerName = o.Customer_Name__c;
cusAccObj.sfAgencyId = o.Agency_Name__c;
cusAccObj.agencyName = o.Agency_Name_OB__c;
cusAccObj.sfPrimarySalesOwnerId = o.Opportunity.OwnerId;
cusAccObj.primarySalesOwnerEmail = o.Opportunity.Owner?.FederationIdentifier;
cusAccObj.primarySalesOwnerPercentage = PrimarySalesSplitPercent;
// cusAccObj.primarySalesOwnerEffectiveFrom = null; // just don't bother with the line?
cusAccObj.sfSecondarySalesOwnerId = secSOSalesforceId.get(o.OpportunityId);
// ..
That's not very object oriented, not very elegant but caller has full control on the mapping. Problem will be if you need to map new field and this has been copy-pasted into 10 places. You'll have to update them all (which will be easier than adding N-th parameter to long call but still)
Another way would be to create a baseline constructor that takes whole Order object (it's an Order, right?), it'd map the fields internally. Then if needed - you specify some extra fields after constructor. Or maybe make few constructors?
public CustomerAccountObject(){
// I'm parameterless, I'm doing nothing! I'm just here if somebody needs a really custom field mapping or JSON deserialisations need a parameterless one
}
public CustomerAccountObject(Order o){
// I can map all fields from Order! Want to map new field? Just chuck it in here!
sfCustomerId = o.AccountId;
// ...
}
public CustomerAccountObject(Order o, Map<Id, String> secSOSalesforceId, Map<Id, String> secSOSalesforceEmail){
// I can do everything above and few more fields too!
this(o);
sfSecondarySalesOwnerId = secSOSalesforceId.get(o.OpportunityId);
secondarySalesOwnerEmail = secSOSalesforceEmail.get(o.OpportunityId);
}
You have bit of code reuse, the Order fields mapping is defined in just 1 place, just 1 line to change in future. You don't have an orgy of this everywhere anymore. And then your call if you really need the last constructor or you'll call the one that just takes Order o and then set the 2 extra fields after it finishes.

Java convert list of string with comma separated values to list of objects

I'd like to convert a json array of person
persons: [
{"1, Franck, 1980-01-01T00:00:00"},
{"2, Marc, 1981-01-01T00:00:00"}
]
To a list of Person object using this class:
class Person {
private Integer id;
private String name;
private Date dateOfBirth;
// getter and setter
}
Would it be possible to use a converter and Java 8 to do it?
public Person convert(String from) {
String[] data = from.split(",");
return new Person(Integer.parseInt(data[0]), data[1], new Date(data[2]));
}
You can do it like so,
Pattern idNumber = Pattern.compile("\\d+");
List<Person> persons = Arrays.stream(from.split("}")).filter(s -> idNumber.matcher(s).find())
.map(s -> s.substring(s.indexOf("{") + 1)).map(s -> s.split(","))
.map(a -> new Person(Integer.parseInt(a[0].replaceAll("\"", "")), a[1],
LocalDateTime.parse(a[2].trim().replaceAll("\"", ""))))
.collect(Collectors.toList());
First split each string using "}" character, and then filter out invalid tokens, which does not contain a digit. Notice that each valid payload should contain Id number which is a digit. Finally remove any spurious trailing characters occur before the Id digit and map each resulting String to a Person object. At last collect the Person instances into a List.
Notice that I have used LocalDateTime for the dateOfBirth field in the Person class. So the Person class looks like this.
public class Person {
private final Integer id;
private final String name;
private final LocalDateTime dateOfBirth;
// remainder omitted for the sake of brevity.
}
However as you can see it is always intuitive to use some framework such as Jackson ObjectMapper to get the work done than writing all this. But in this case your Json is malformed so you won't be able to use such a framework unless you fix the json payload structure.
Update
Here's much more elegant Java9 solution.
String regexString = Pattern.quote("{\"") + "(.*?)" + Pattern.quote("\"}");
Pattern pattern = Pattern.compile(regexString);
List<Person> persons = pattern.matcher(from)
.results()
.map(mr -> mr.group(1)).map(s -> s.split(", "))
.map(a -> new Person(Integer.parseInt(a[0]), a[1], LocalDateTime.parse(a[2])))
.collect(Collectors.toList());
In Java 9, you can now use Matcher#results() to get a Stream<MatchResult>. Here's an excerpt from the documentation.
Returns a stream of match results for each subsequence of the input
sequence that matches the pattern. The match results occur in the same
order as the matching subsequences in the input sequence.
I would rather recommend you to use Java9 to solve this.
If you need to do it just for a List of String representation of a Person, you may do it like so.
List<String> personStr = Arrays.asList("1, Franck, 1980-01-01T00:00:00", "2, Marc, 1981-01-01T00:00:00");
List<Person> persons = personStr.stream()
.map(s -> s.replaceAll(" ", "").split(","))
.map(a -> new Person(Integer.parseInt(a[0]), a[1], LocalDateTime.parse(a[2])))
.collect(Collectors.toList());
Notice the latter is far more easier than the prior and contains just a subset of the original solution.
An Extention of your solution itself & with a bit of abstraction:
List<String> personStr = Arrays.asList("1, Franck, 1980-01-01T00:00:00", "2, Marc, 1981-01-01T00:00:00");
List<Person> persons = personStr.stream()
.map(Person::new)
.collect(Collectors.toList());
Where, Person class has a constructor which accepts a string arg to convert it to a Person object, as follows:
public Person(String from) {
String[] data = from.split(",");
Arrays.parallelSetAll(data, i -> data[i].trim());
this.id = Integer.parseInt(data[0]);
this.name = data[1];
this.dateOfBirth = new Date(data[2]);
}

QueryBuider get parameters for Dao.queryRaw

I'm using QueryBuider to create raw query, but I need to fill parameters to raw query manually.
Properties 'from' and 'to' are filled two times. One in 'where' section of QueryBuider, and one in queryRaw method as parameters.
Method StatementBuilder.prepareStatementString() returns query string with "?" for substitution.
Is there any way to get these parameters directly from QueryBuider instance?
For example, imagine a new method in ormlite - StatementBuilder.getPreparedStatementParameters();
QueryBuilder<AccountableItemEntity, Long> accountableItemQb = accountableItemDao.queryBuilder();
QueryBuilder<AccountingEntryEntity, Long> accountingEntryQb = accountingEntryDao.queryBuilder();
accountingEntryQb.where().eq(
AccountingEntryEntity.ACCOUNTING_ENTRY_STATE_FIELD_NAME,
AccountingEntryStateEnum.CREATED);
accountingEntryQb.join(accountableItemQb);
QueryBuilder<AccountingTransactionEntity, Long> accountingTransactionQb =
accountingTransactionDao.queryBuilder();
accountingTransactionQb.selectRaw("ACCOUNTINGENTRYENTITY.TITLE, " +
"ACCOUNTINGENTRYENTITY.ACCOUNTABLE_ITEM_ID, " +
"SUM(ACCOUNTINGENTRYENTITY.COUNT), " +
"SUM(ACCOUNTINGENTRYENTITY.COUNT * CONVERT(ACCOUNTINGENTRYENTITY.PRICEAMOUNT,DECIMAL(20, 2)))");
accountingTransactionQb.join(accountingEntryQb);
accountingTransactionQb.where().eq(
AccountingTransactionEntity.ACCOUNTING_TRANSACTION_STATE_FIELD_NAME,
AccountingTransactionStateEnum.PRINTED)
.and().between(AccountingTransactionEntity.CREATE_TIME_FIELD_NAME, from, to);
accountingTransactionQb.groupByRaw(
"ACCOUNTINGENTRYENTITY.ACCOUNTABLE_ITEM_ID, ACCOUNTINGENTRYENTITY.TITLE");
String query = accountingTransactionQb.prepareStatementString();
accountingTransactionQb.prepare().getStatement();
Timestamp fromTimestamp = new Timestamp(from.getTime());
Timestamp toTimestamp = new Timestamp(to.getTime());
//TODO: get parameters from accountingTransactionQb
GenericRawResults<Object[]> genericRawResults =
accountingEntryDao.queryRaw(query, new DataType[] { DataType.STRING,
DataType.LONG, DataType.LONG, DataType.BIG_DECIMAL },
fromTimestamp.toString(), toTimestamp.toString());
Is there any way to get these parameters directly from QueryBuider instance?
Yes, there is a way. You need to subclass QueryBuilder and then you can use the appendStatementString(...) method. You provide the argList which then can be used to get the list of arguments.
protected void appendStatementString(StringBuilder sb,
List<ArgumentHolder> argList) throws SQLException {
appendStatementStart(sb, argList);
appendWhereStatement(sb, argList, true);
appendStatementEnd(sb, argList);
}
For example, imagine a new method in ormlite - StatementBuilder.getPreparedStatementParameters();
Good idea. I've made the following changes to the Github repo.
public StatementInfo prepareStatementInfo() throws SQLException {
List<ArgumentHolder> argList = new ArrayList<ArgumentHolder>();
String statement = buildStatementString(argList);
return new StatementInfo(statement, argList);
}
...
public static class StatementInfo {
private final String statement;
private final List<ArgumentHolder> argList;
...
The feature will be in version 4.46. You can build a release from current trunk if you don't want to wait for that release.

How to handle optional query parameters in Play framework

Lets say I have an already functioning Play 2.0 framework based application in Scala that serves a URL such as:
http://localhost:9000/birthdays
which responds with a listing of all known birthdays
I now want to enhance this by adding the ability to restrict results with optional "from" (date) and "to" request params such as
http://localhost:9000/birthdays?from=20120131&to=20120229
(dates here interpreted as yyyyMMdd)
My question is how to handle the request param binding and interpretation in Play 2.0 with Scala, especially given that both of these params should be optional.
Should these parameters be somehow expressed in the "routes" specification? Alternatively, should the responding Controller method pick apart the params from the request object somehow? Is there another way to do this?
Encode your optional parameters as Option[String] (or Option[java.util.Date], but you’ll have to implement your own QueryStringBindable[Date]):
def birthdays(from: Option[String], to: Option[String]) = Action {
// …
}
And declare the following route:
GET /birthday controllers.Application.birthday(from: Option[String], to: Option[String])
A maybe less clean way of doing this for java users is setting defaults:
GET /users controllers.Application.users(max:java.lang.Integer ?= 50, page:java.lang.Integer ?= 0)
And in the controller
public static Result users(Integer max, Integer page) {...}
One more problem, you'll have to repeat the defaults whenever you link to your page in the template
#routes.Application.users(max = 50, page = 0)
In Addition to Julien's answer. If you don't want to include it in the routes file.
You can get this attribute in the controller method using RequestHeader
String from = request().getQueryString("from");
String to = request().getQueryString("to");
This will give you the desired request parameters, plus keep your routes file clean.
Here's Julien's example rewritten in java, using F.Option: (works as of play 2.1)
import play.libs.F.Option;
public static Result birthdays(Option<String> from, Option<String> to) {
// …
}
Route:
GET /birthday controllers.Application.birthday(from: play.libs.F.Option[String], to: play.libs.F.Option[String])
You can also just pick arbitrary query parameters out as strings (you have to do the type conversion yourself):
public static Result birthdays(Option<String> from, Option<String> to) {
String blarg = request().getQueryString("blarg"); // null if not in URL
// …
}
For optional Query parameters, you can do it this way
In routes file, declare API
GET /birthdays controllers.Application.method(from: Long, to: Long)
You can also give some default value, in case API doesn't contain these query params it will automatically assign the default values to these params
GET /birthdays controllers.Application.method(from: Long ?= 0, to: Long ?= 10)
In method written inside controller Application these params will have value null if no default values assigned else default values.
My way of doing this involves using a custom QueryStringBindable. This way I express parameters in routes as:
GET /birthdays/ controllers.Birthdays.getBirthdays(period: util.Period)
The code for Period looks like this.
public class Period implements QueryStringBindable<Period> {
public static final String PATTERN = "dd.MM.yyyy";
public Date start;
public Date end;
#Override
public F.Option<Period> bind(String key, Map<String, String[]> data) {
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
try {
start = data.containsKey("startDate")?sdf.parse(data.get("startDate") [0]):null;
end = data.containsKey("endDate")?sdf.parse(data.get("endDate")[0]):null;
} catch (ParseException ignored) {
return F.Option.None();
}
return F.Option.Some(this);
}
#Override
public String unbind(String key) {
SimpleDateFormat sdf = new SimpleDateFormat(PATTERN);
return "startDate=" + sdf.format(start) + "&" + "endDate=" + sdf.format(end);
}
#Override
public String javascriptUnbind() {
return null;
}
public void applyDateFilter(ExpressionList el) {
if (this.start != null)
el.ge("eventDate", this.start);
if (this.end != null)
el.le("eventDate", new DateTime(this.end.getTime()).plusDays(1).toDate());
}
}
applyDateFilter is just a convienence method i use in my controllers if I want to apply date filtering to the query. Obviously you could use other date defaults here, or use some other default than null for start and end date in the bind method.