I written the code for Post data in webservice and it sends response data and code. Same data I am posting in the sql using select query. My scenario is I need to check responsedata and sql data are same or not.
Mysql.java
public ArrayList<DisputeSummaryarraylistobject> connectSqlconnectiondisputesummary() throws SQLException, ClassNotFoundException{
ArrayList<DisputeSummaryarraylistobject> DisputeSummaryarraylistobjectlist = new ArrayList<DisputeSummaryarraylistobject>();
String connectionUrl = "jdbc:sqlserver://localhost:1433;" +
"databaseName=AdventureWorks;user=UserName;password=*****";
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
sqlConnection = DriverManager.getConnection(connectionUrl);
String sqlStatement = "Enter the sql statement";
stateMent = sqlConnection.createStatement();
resultSet = stateMent.executeQuery(sqlStatement);
DisputeSummaryarraylistobject disputeSummaryarraylistobject = new DisputeSummaryarraylistobject();
while (resultSet.next())
{
disputeSummaryarraylistobject.setchargeback(resultSet.getInt("chargeback"));
disputeSummaryarraylistobject.setactiveDisputes(resultSet.getInt("activeDisputes"));
disputeSummaryarraylistobject.setrecentUpdates(resultSet.getInt("recentUpdates"));
disputeSummaryarraylistobject.setrecentlyClosed(resultSet.getInt("recentlyClosed"));
disputeSummaryarraylistobject.setresponseRequired(resultSet.getInt("responseRequired"));
disputeSummaryarraylistobject.inProgress(resultSet.getInt("inProgress"));
disputeSummaryarraylistobject.setclosedInFavor(resultSet.getInt("closedInFavor"));
disputeSummaryarraylistobject.setclosedChargebacks(resultSet.getInt("closedChargebacks"));
DisputeSummaryarraylistobjectlist.add(disputeSummaryarraylistobject);
}
}
catch (Exception e) {
e.printStackTrace();
}
return DisputeSummaryarraylistobjectlist;
}
}
Myjsonresponse.java
public void convertResponseoutputtojsonobject() throws IOException, ParseException {
logger.info("convertResponseoutputtojsonobject() : BEGINs ");
JSONParser jsonParser = new JSONParser();
Object object = jsonParser.parse(response.toString());
JSONArray jsArray = (JSONArray) object;
Iterator<JSONObject> iterator = jsArray.iterator();
while (iterator.hasNext()) {
JSONObject jsonObj = iterator.next();
list.add(jsonObj);
}
logger.info(list.toString());
logger.info("convertResponseoutputtojsonobject() : ENDS ");
}
output : response data will be stored in the list.tostring() with formart
{
"chargeback": 5,
"activeDisputes": 12,
"recentUpdates": 10,
"recentlyClosed": 12,
"responseRequired": 8,
"inProgress": 4,
"closedInFavor": 4,
"closedChargebacks": 8
}
I need compare the list.tostring values and sql values. Anyone can give a solution how to compare?
If you have a DisputeSummaryarraylistobject with proper equals and hashcode method then you can use Gson to parse the json data directly to the object and do a comparision. Eg.
import java.lang.reflect.Type;
import java.util.List;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class JsonCompare {
public static void main(String[] args) {
String jsonData = "{ \"chargeback\": 5, \"activeDisputes\": 12, \"recentUpdates\": 10, \"recentlyClosed\": 12, \"responseRequired\": 8, \"inProgress\": 4, \"closedInFavor\": 4, \"closedChargebacks\": 8 }";
Gson gson = new Gson();
DisputeSummaryarraylistobject webserviceObject = gson.fromJson(jsonData, DisputeSummaryarraylistobject.class);
//DDObject
DisputeSummaryarraylistobject dbObject = new DisputeSummaryarraylistobject();
dbObject.setChargeback(5);
dbObject.setActiveDisputes(12);
dbObject.setRecentUpdates(10);
dbObject.setRecentlyClosed(12);
dbObject.setResponseRequired(8);
dbObject.setInProgress(4);
dbObject.setClosedInFavor(4);
dbObject.setClosedChargebacks(8);
System.out.println(webserviceObject.equals(dbObject));
// If you have an array of objects
String jsonDataArray = "[ { \"chargeback\": 5, \"activeDisputes\": 12, \"recentUpdates\": 10, \"recentlyClosed\": 12, \"responseRequired\": 8, \"inProgress\": 4, \"closedInFavor\": 4, \"closedChargebacks\": 8 }, "
+ " { \"chargeback\": 6, \"activeDisputes\": 7, \"recentUpdates\": 8, \"recentlyClosed\": 2, \"responseRequired\": 5, \"inProgress\": 14, \"closedInFavor\": 14, \"closedChargebacks\": 5 } ]";
Type listType = new TypeToken<List<DisputeSummaryarraylistobject>>() {}.getType();
List<DisputeSummaryarraylistobject> disputeSummaryArraylistobjectList = gson.fromJson(jsonDataArray, listType);
System.out.println(disputeSummaryArraylistobjectList);
//Now you can iterate through the array and compare the objects with equals.
}
}
A sample Dispute Summary Object
public class DisputeSummaryarraylistobject {
private int chargeback;
private int activeDisputes;
private int recentUpdates;
private int recentlyClosed;
private int responseRequired;
private int inProgress;
private int closedInFavor;
private int closedChargebacks;
public int getChargeback() {
return chargeback;
}
public void setChargeback(int chargeback) {
this.chargeback = chargeback;
}
public int getActiveDisputes() {
return activeDisputes;
}
public void setActiveDisputes(int activeDisputes) {
this.activeDisputes = activeDisputes;
}
public int getRecentUpdates() {
return recentUpdates;
}
public void setRecentUpdates(int recentUpdates) {
this.recentUpdates = recentUpdates;
}
public int getRecentlyClosed() {
return recentlyClosed;
}
public void setRecentlyClosed(int recentlyClosed) {
this.recentlyClosed = recentlyClosed;
}
public int getResponseRequired() {
return responseRequired;
}
public void setResponseRequired(int responseRequired) {
this.responseRequired = responseRequired;
}
public int getInProgress() {
return inProgress;
}
public void setInProgress(int inProgress) {
this.inProgress = inProgress;
}
public int getClosedInFavor() {
return closedInFavor;
}
public void setClosedInFavor(int closedInFavor) {
this.closedInFavor = closedInFavor;
}
public int getClosedChargebacks() {
return closedChargebacks;
}
public void setClosedChargebacks(int closedChargebacks) {
this.closedChargebacks = closedChargebacks;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + activeDisputes;
result = prime * result + chargeback;
result = prime * result + closedChargebacks;
result = prime * result + closedInFavor;
result = prime * result + inProgress;
result = prime * result + recentUpdates;
result = prime * result + recentlyClosed;
result = prime * result + responseRequired;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
DisputeSummaryarraylistobject other = (DisputeSummaryarraylistobject) obj;
if (activeDisputes != other.activeDisputes)
return false;
if (chargeback != other.chargeback)
return false;
if (closedChargebacks != other.closedChargebacks)
return false;
if (closedInFavor != other.closedInFavor)
return false;
if (inProgress != other.inProgress)
return false;
if (recentUpdates != other.recentUpdates)
return false;
if (recentlyClosed != other.recentlyClosed)
return false;
if (responseRequired != other.responseRequired)
return false;
return true;
}
#Override
public String toString() {
return "DisputeSummaryarraylistobject [chargeback=" + chargeback
+ ", activeDisputes=" + activeDisputes + ", recentUpdates="
+ recentUpdates + ", recentlyClosed=" + recentlyClosed
+ ", responseRequired=" + responseRequired + ", inProgress="
+ inProgress + ", closedInFavor=" + closedInFavor
+ ", closedChargebacks=" + closedChargebacks + "]";
}
}
Instead of checking if the JSON documents are the same in your client, you could also do that directly in SQL:
select cast(? as jsonb) = (select jsonb_agg(jsonb_build_object(...)) from ...)
It may not be the right approach for you, but just a thought that is often overlooked.
Related
Can you please read through below code and help to let me know if i need to use synchronized keyword with the concurrent hash map in this example?
The main problem is i dont understand when a synchronized keyword needs to be used in compound operations in a concurrent hash map.can someone please help
import java.util.Map;
import java.util.concurrent.BlockingDeque;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
class Pair {
public final Integer x;
public final Integer y;
public Pair(Integer x, Integer y) {
this.x = x;
this.y = y;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((x == null) ? 0 : x.hashCode());
result = prime * result + ((y == null) ? 0 : y.hashCode());
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Pair other = (Pair) obj;
if (x == null) {
if (other.x != null)
return false;
} else if (!x.equals(other.x))
return false;
if (y == null) {
if (other.y != null)
return false;
} else if (!y.equals(other.y))
return false;
return true;
}
}
class Order{
int clOrdId;
int origClOrdId;
String symbol;
int qty;
double price;
#Override
public String toString() {
return "Order [clOrdId=" + clOrdId + ", origClOrdId=" + origClOrdId + ", symbol=" + symbol + ", qty=" + qty
+ ", price=" + price + ", side=" + side + "]";
}
char side;
Order(int clOrdId,String symbol,int qty,double price,char side){
this.clOrdId=clOrdId;
this.symbol=symbol;
this.qty=qty;
this.price=price;
this.side=side;
}
Order(int clOrdId,int origClOrdId,String symbol,int qty,double price,char side){
this.clOrdId=clOrdId;
this.origClOrdId=origClOrdId;
this.symbol=symbol;
this.qty=qty;
this.price=price;
this.side=side;
}
}
class Message {
int sessionId;
Order order;
Message(int sessionId, Order order) {
this.sessionId = sessionId;
this.order = order;
}
#Override
public String toString() {
return "Message [sessionId=" + sessionId + ", order=" + order + "]";
}
}
/*
* Different clients can submit different messages 1. Each message has a
* sessionId and a string msg 2. Each of the messages on a particular session
* need to be processed sequentially
*/
public class Concurrency {
private Map<Integer, BlockingDeque<Runnable>> pendingTasks = new ConcurrentHashMap<>();
private Map<Pair,Order> orderMap = new ConcurrentHashMap<>();
private ExecutorService executorService = Executors.newFixedThreadPool(13);
public void submitMsg(final Message msg) {
submitTask(msg, () -> {
if(msg.order.origClOrdId==0){
print("Received new order msg " + msg);
sleep(1000);
}else{
Pair key = new Pair(msg.sessionId,msg.order.origClOrdId);
if(orderMap.containsKey(key)){
if(isOnlyAggressivePriceMod(msg, key) ){
print("Aggressive price modification "+ msg);
}else if(isOnlyQtyModUp(msg, key)){
print(" Quantity modification up only for "+ msg);
}else if(isOnlyQtyDown(msg, key)){
print(" Quantity modification down only for "+ msg);
}
}
}
orderMap.put(new Pair(msg.sessionId,msg.order.clOrdId), msg.order);
});
}
private boolean isOnlyQtyDown(final Message msg, Pair key) {
return msg.order.qty<orderMap.get(key).qty && Double.compare(msg.order.price,orderMap.get(key).price)==0;
}
private boolean isOnlyQtyModUp(final Message msg, Pair key) {
return msg.order.qty>orderMap.get(key).qty && Double.compare(msg.order.price,orderMap.get(key).price)==0;
}
private boolean isOnlyAggressivePriceMod(final Message msg, Pair key) {
return ((Double.compare(msg.order.price,orderMap.get(key).price)>0 && msg.order.side=='B') ||
(Double.compare(msg.order.price,orderMap.get(key).price)<0 && msg.order.side=='S')) && Double.compare(msg.order.qty,orderMap.get(key).qty)==0;
}
private void sleep(int time){
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void print(String msg){
System.out.println(msg);
}
private void submitTask(final Message msg, Runnable task) {
synchronized(pendingTasks){
if (pendingTasks.containsKey(msg.sessionId)) {
pendingTasks.get(msg.sessionId).add(task);
return;
}
}
BlockingDeque<Runnable> pendingTasksPerSession = new LinkedBlockingDeque<Runnable>();
pendingTasksPerSession.push(task);
pendingTasks.put(msg.sessionId, pendingTasksPerSession);
executorService.submit(new SynchronizedTask(msg, task));
}
public class SynchronizedTask implements Runnable {
Message msg;
Runnable task;
public SynchronizedTask(Message msg, Runnable task) {
this.msg = msg;
this.task = task;
}
public void run() {
task.run();
BlockingDeque<Runnable> pendingTasksForSession = pendingTasks.get(msg.sessionId);
if (!pendingTasksForSession.remove(task)) {
return;
}
if (!pendingTasksForSession.isEmpty())
executorService.submit(new SynchronizedTask(msg, pendingTasksForSession.getFirst()));
}
}
public static void main(String args[]) {
Concurrency c = new Concurrency();
for(int i =1;i<10;i++){
c.submitMsg(new Message(i, new Order(10,"0001.HK",2000*i,200+i,'B')));
c.submitMsg(new Message(i, new Order(11,10,"0001.HK",1000*i,200+i,'B')));
c.submitMsg(new Message(i, new Order(12,11,"0001.HK",2000*i,201+i,'B')));
}
for(int i =1;i<10;i++){
c.submitMsg(new Message(i, new Order(10,"0001.HK",2000*i,200+i,'S')));
c.submitMsg(new Message(i, new Order(11,10,"0001.HK",1000*i,200+i,'S')));
c.submitMsg(new Message(i, new Order(12,11,"0001.HK",2000*i,201+i,'S')));
}
}
}
I am trying to implement paging in an already running application, it works like mongodb where you get a query with bunch of parameters like
searchConditions ,limit( how many docs you want), skip ( skip these many docs)
and so on
and the response is back in json my task is to generate the previous and next link to the query that means previous page and the next page as per query
I came up with a method below
public Paging generateLink(RequestFilter filter) {
int prev_skip;
int prev_limit;
String pagePrev = "";
String pageNext = "";
int next_skip;
int next_limit;
String searchCondition = JsonUtils.toSimpleJsonString(filter.getSearch());
String url = "http://isgswmdi1n1.nam.nsroot.net:7014/account-search/rest/api/v1/pmm";
//properties.getProperty("paging.link");
System.out.println(url);
Paging pagingOption = new Paging();
Result result = new Result();
int count = luceneSearchService.searchCount(filter);
try {
if (count > 1) {
if (filter.getSkip() > 0) {
prev_skip = Math.max((filter.getSkip() - 1), 0);
prev_limit = filter.getLimit();
pagePrev = url + "?search=" + searchCondition + "&skip=" + prev_skip + "$limit=" + prev_limit;
} else{
result.setPaging(null);
return null;
}
if (count > (filter.getLimit() + filter.getSkip())) {
next_skip = (filter.getSkip() + filter.getLimit());
next_limit = filter.getLimit();
pageNext = url + "?search=" + searchCondition + "&skip=" + next_skip + "$limit=" + next_limit;
} else{
result.setPaging(null);
return null;
}
pagingOption.setPagePrev(pagePrev);
pagingOption.setPageNext(pageNext);
result.setPaging(pagingOption);
}
return pagingOption;
} catch (NullPointerException n)
{
n.printStackTrace();
return pagingOption;
}
}
call to generateLink method
return Result.ok(resultRow, generateLink(filter));
the ok response method in the Result class
public static Result ok(List<ResultRow> resultRows, Paging paging) {
if (paging != null) {
return new Result(resultRows, 200, "Completed", paging);
} else
return new Result(resultRows, 200, "Completed");
}
Underlying paging class
public class Paging implements Serializable {
public String getPagePrev() {
return pagePrev;
}
public void setPagePrev(String pagePrev) {
this.pagePrev = pagePrev;
}
#JsonProperty("pagePrev")
private String pagePrev;
public String getPageNext() {
return pageNext;
}
public void setPageNext(String pageNext) {
this.pageNext = pageNext;
}
#JsonProperty("pageNext")
private String pageNext;
}
but my test method is failing
#Test
public void search_allFilterParamsAreDefined_hp() throws Exception {
// given
Map<String, Serializable> searchConditions = singletonMap("shortName", "GO");
List<String> returnFields = asList("shortname", "gfcid");
String returnFieldsStr = returnFields.stream().collect(joining(","));
RequestFilter filter = RequestFilter.create(searchConditions, returnFieldsStr, 5, 10, true);
int resultSize = 20;
List<ResultRow> searchResult = getSearchResult(resultSize);
when(luceneSearchService.search(filter)).thenReturn(searchResult);
when(luceneSearchService.searchCount(filter)).thenReturn(resultSize);
// do
Result result = searchCoordinator.search(filter);
// verify
assertEquals(searchResult, result.getRows());
assertReturnFields(returnFields, result.getRows());
assertNotNull(result.getPaging());
Map<String, String> nextParams = getQueryParams(result.getPaging().getPageNext());
assertParam(nextParams, "search", toSimpleJsonString(searchConditions));
assertParam(nextParams, "skip", "15");
assertParam(nextParams, "limit", "10");
}
I'm developing a radio app with multiple radios, the stream is playing fine. But I'm struggling to show artist and music playing at the moment.
This is the class I'm using to get metadata from shoutcast stream:
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class IcyStreamMeta<Message> {
protected URL streamUrl;
private Map<String, String> metadata;
private boolean isError;
public IcyStreamMeta(URL streamUrl) {
setStreamUrl(streamUrl);
isError = false;
}
/**
* Get artist using stream's title
*
* #return String
* #throws IOException
*/
public String getArtist() throws IOException {
Map<String, String> data = getMetadata();
if (!data.containsKey("StreamTitle"))
return "";
String streamTitle = data.get("StreamTitle");
String title = streamTitle.substring(0, streamTitle.indexOf("-"));
return title.trim();
}
/**
* Get title using stream's title
*
* #return String
* #throws IOException
*/
public String getTitle() throws IOException {
Map<String, String> data = getMetadata();
if (!data.containsKey("StreamTitle"))
return "";
String streamTitle = data.get("StreamTitle");
String artist = streamTitle.substring(streamTitle.indexOf("-")+1);
return artist.trim();
}
public Map<String, String> getMetadata() throws IOException {
if (metadata == null) {
refreshMeta();
}
return metadata;
}
public void refreshMeta() throws IOException {
retreiveMetadata();
}
private void retreiveMetadata() throws IOException {
URLConnection con = streamUrl.openConnection();
con.setRequestProperty("Icy-MetaData", "1");
con.setRequestProperty("Connection", "close");
con.setRequestProperty("Accept", null);
con.connect();
int metaDataOffset = 0;
Map<String, List<String>> headers = con.getHeaderFields();
InputStream stream = con.getInputStream();
if (headers.containsKey("icy-metaint")) {
// Headers are sent via HTTP
metaDataOffset = Integer.parseInt(headers.get("icy-metaint").get(0));
} else {
// Headers are sent within a stream
StringBuilder strHeaders = new StringBuilder();
char c;
while ((c = (char)stream.read()) != -1) {
strHeaders.append(c);
if (strHeaders.length() > 5 && (strHeaders.substring((strHeaders.length() - 4), strHeaders.length()).equals("\r\n\r\n"))) {
// end of headers
break;
}
}
// Match headers to get metadata offset within a stream
Pattern p = Pattern.compile("\\r\\n(icy-metaint):\\s*(.*)\\r\\n");
Matcher m = p.matcher(strHeaders.toString());
if (m.find()) {
metaDataOffset = Integer.parseInt(m.group(2));
}
}
// In case no data was sent
if (metaDataOffset == 0) {
isError = true;
return;
}
// Read metadata
int b;
int count = 0;
int metaDataLength = 4080; // 4080 is the max length
boolean inData = false;
StringBuilder metaData = new StringBuilder();
// Stream position should be either at the beginning or right after headers
while ((b = stream.read()) != -1) {
count++;
// Length of the metadata
if (count == metaDataOffset + 1) {
metaDataLength = b * 16;
}
if (count > metaDataOffset + 1 && count < (metaDataOffset + metaDataLength)) {
inData = true;
} else {
inData = false;
}
if (inData) {
if (b != 0) {
metaData.append((char)b);
}
}
if (count > (metaDataOffset + metaDataLength)) {
break;
}
}
// Set the data
metadata = IcyStreamMeta.parseMetadata(metaData.toString());
// Close
stream.close();
}
public boolean isError() {
return isError;
}
public URL getStreamUrl() {
return streamUrl;
}
public void setStreamUrl(URL streamUrl) {
this.metadata = null;
this.streamUrl = streamUrl;
this.isError = false;
}
public static Map<String, String> parseMetadata(String metaString) {
Map<String, String> metadata = new HashMap();
String[] metaParts = metaString.split(";");
Pattern p = Pattern.compile("^([a-zA-Z]+)=\\'([^\\']*)\\'$");
Matcher m;
for (int i = 0; i < metaParts.length; i++) {
m = p.matcher(metaParts[i]);
if (m.find()) {
metadata.put(m.group(1), m.group(2));
}
}
return metadata;
}
}
And the method on MainActivity to get the metadata every 10 seconds
private void getMeta()
{
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
try {
IcyStreamMeta icy = new IcyStreamMeta(new URL(RadiophonyService.getRadioURL()));
final String data = icy.getArtist() + " - " + icy.getTitle();
final TextView meta = (TextView) findViewById(R.id.now_playing);
runOnUiThread(new Runnable() {
public void run() {
meta.setText(data);
}
});
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}, 0, 10000);
}
Initially, when I select one station, it plays but does not show metadata and when I select another station the app crashes with this runtime error:
E/AndroidRuntime: FATAL EXCEPTION: Timer-0
Process: com.example.app, PID: 23597
java.lang.StringIndexOutOfBoundsException: length=0; regionStart=0; regionLength=-1
at java.lang.String.startEndAndLength(String.java:504)
at java.lang.String.substring(String.java:1333)
at com.example.app.utilities.IcyStreamMeta.getArtist(IcyStreamMeta.java:41)
at com.example.app.activities.MainActivity$8.run(MainActivity.java:306)
at java.util.Timer$TimerImpl.run(Timer.java:284)
I'm stuck at this for days, and I tried other solutions but nothing works!
Looks like this line
String title = streamTitle.substring(0, streamTitle.indexOf("-"));
is the culprit.
If streamTitle does not have a dash in its title, indexOf() will return a -1, and substring() is choking because you can't have an end index less than the start index.
Maybe you need something like this:
int pos = streamTitle.indexOf("-");
String title = (pos == -1) ? streamTitle : streamTitle.substring(0, pos);
I'm doing a simple MessageRenderer.
It's specification:
Render message based on an Context (it's a map that's contains all key/value pair parameters)
Supports simple render such as: Your username is << username >>. Assume username in the context is barcelona and the result will be Your username is Barcelona.
Supported function-like object. Example: Current time is << now() >>, now(): is an object that will returns a string of current date time. And result will be: Current time is 2011-05-30
Each parameter of function can also be templated: Current time is << now( << date_format >> ) >> . This template returns a string of current date time with format is the value of key 'date_format' retrieved from the Context. Assume date_format in Context is dd/MM/yyyy and the result will be: Current time is 30/05/2011
Each parameter of function can also be templated with a different method call: Time is << now_locale ( << getLocale() >> ). Assume that getLocale() is an function object that will be return a locale is en_US and the result will be: Time is 2011/05/30 11:20:34 PM
Template can be nested. Example: Your user name is << << username >> >>. It means, Key username has value param1, Key param1 has value is barcelona so the final result will be: Your user name is Barcelona.
My classes and interfaces:
RenderContext.java
public interface RenderContext {
public String getParameter(String key);
}
MessageRenderer.java
public interface MessageRenderer {
public String render(String s, RenderContext... context);
}
MethodExpressionEvaluator.java
// Using this class to implements the method evaluation, such as now(), now_locale()
public interface MethodExpressionEvaluator {
public String evaluate(String[] methodParams, RenderContext... context);
}
AbstractMessageRenderer.java
public abstract class AbstractMessageRenderer implements MessageRenderer {
public static final String DEFAULT_NULL = "###";
public static final String PLACEHOLDER_START_TOKEN = "<<";
public static final String PLACEHOLDER_END_TOKEN = ">>";
protected int lenPlaceholderStartToken = 0;
protected int lenPlaceholderEndToken = 0;
protected String nullToken;
protected String placeholderStartToken;
protected String placeholderEndToken;
protected boolean escape = true;
public AbstractMessageRenderer() {
placeholderStartToken = PLACEHOLDER_START_TOKEN;
placeholderEndToken = PLACEHOLDER_END_TOKEN;
lenPlaceholderStartToken = placeholderStartToken.length();
lenPlaceholderEndToken = placeholderEndToken.length();
nullToken = DEFAULT_NULL;
}
public String getNullToken() {
return nullToken;
}
public void setNullToken(String defaultNull) {
this.nullToken = defaultNull;
}
public String getPlaceholderStartToken() {
return placeholderStartToken;
}
public void setPlaceholderStartToken(String placeholderStartToken) {
this.placeholderStartToken = placeholderStartToken;
lenPlaceholderStartToken = placeholderStartToken.length();
}
public String getPlaceholderEndToken() {
return placeholderEndToken;
}
public void setPlaceholderEndToken(String placeholderEndToken) {
this.placeholderEndToken = placeholderEndToken;
lenPlaceholderEndToken = placeholderEndToken.length();
}
public boolean isEscape() {
return escape;
}
public boolean getEscape() {
return escape;
}
public void setEscape(boolean escape) {
this.escape = escape;
}
public String getParam(String key, RenderContext... context) {
if(context != null)
{
for(RenderContext param:context)
{
if(param != null)
{
String value = param.getParameter(key);
if(!StringUtil.isEmpty(value))
{
return value;
}
}
}
}
return nullToken;
}
public String render(String s, RenderContext... context) {
// handle trivial cases of empty template or no placeholders
if (s == null)
{
Log4j.app.debug("Message is null in template. Cannot render null message.");
return nullToken;
}
if (context == null)
{
Log4j.app.debug("RenderContext is null. Cannot render message with null RenderContext.");
return nullToken;
}
if (s.indexOf(placeholderStartToken) < 0)
{
return s;
}
String msg = nullToken;
try
{
// private int renderTemplate(Renderable r, String src, StringBuffer dst, String nil, int i, String[] marks, StringBuffer end,boolean escapes)
msg = doRender(s, context);
}
catch (Exception e)
{
Log4j.app.error("Exception in rendering template: " + e.getMessage(), e);
return nullToken;
}
return msg;
}
protected abstract String doRender(String s, RenderContext... context);
}
MethodExpressionRenderer.java
public class MethodExpressionRenderer extends AbstractMessageRenderer {
private boolean inSingleQuote = false;
private boolean inDoubleQuote=false;
private int placeholders;
private Stack<String> methodStack;
private String[] endTokens;
private String marker;
private List<String> methodParams;
private String prefix = "&";
public MethodExpressionRenderer() {
super();
methodStack = new Stack<String>();
marker = ",";
endTokens = new String[] { placeholderEndToken, marker, "(", ")" };
methodParams = new ArrayList<String>();
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getMarker() {
return marker;
}
public void setMarker(String marker) {
this.marker = marker;
endTokens = new String[] { placeholderEndToken, marker };
}
#Override
public void setPlaceholderEndToken(String placeholderEndToken) {
super.setPlaceholderEndToken(placeholderEndToken);
endTokens = new String[] { placeholderEndToken, marker };
}
protected String doRender(String s, RenderContext... context) {
StringBuffer sb = new StringBuffer();
try
{
renderTemplate(s, sb, nullToken, 0, endTokens, null, context);
}
catch (Exception e)
{
Log4j.app.error("Exception in rendering method expression message emplate: " + e.getMessage(), e);
return nullToken;
}
return sb.toString();
}
private int renderTemplate(String src, StringBuffer dst, String nil, int i, String[] marks, StringBuffer end, RenderContext... context) {
int len = src.length();
while (i < len)
{
char c = src.charAt(i);
if (escape)
{
if (c=='\\')
{
i++;
char ch = src.charAt(i);
if(inSingleQuote)
{
if(ch=='\'')
{
inSingleQuote=false;
}
}
else if(inDoubleQuote)
{
if(ch=='"')
{
inDoubleQuote=false;
}
}
else
{
if(ch=='\'')
{
inSingleQuote=true;
}
else if(ch=='"')
{
inDoubleQuote=true;
}
}
dst.append(ch);
i++;
continue;
}
}
if(inSingleQuote)
{
if(c=='\'')
{
inSingleQuote=false;
}
}
else if(inDoubleQuote)
{
if(c=='"')
{
inDoubleQuote=false;
}
}
else
{
if(c=='\'')
{
inSingleQuote=true;
}
else if(c=='"')
{
inDoubleQuote=true;
}
}
// check for end marker
if (marks != null && !inSingleQuote && !inDoubleQuote)
{
for (int m = 0; m < marks.length; m++)
{
// If one of markers found
if (src.regionMatches(i, marks[m], 0, marks[m].length()))
{
// return marker if required
if (end != null)
{
end.append(marks[m]);
}
return i+marks[m].length();
}
}
}
// check for start of placeholder
if (src.regionMatches(i, placeholderStartToken, i, lenPlaceholderStartToken))
{
synchronized(this)
{
++placeholders;
}
i = renderPlaceholder(src, dst, nil, i, new ArrayList<String>(), context);
continue;
}
// just add plain character
if(c != '\'' && c!= '"')
{
dst.append(c);
}
i++;
}
return i;
}
private int renderPlaceholder(String src, StringBuffer dst, String nil, int i, List<String> params, RenderContext... context){
StringBuffer token = new StringBuffer(); // placeholder token
StringBuffer end = new StringBuffer(); // placeholder end marker
String value;
i = renderTemplate(src, token, nil, i+lenPlaceholderStartToken, endTokens, end);
String sToken = token.toString().trim();
String sEnd = end.toString().trim();
boolean isFunction = sEnd.equals("(");
// This is method name
if(isFunction && placeholders > methodStack.size())
{ // Method
synchronized(this)
{
methodStack.push(sToken); // put method into stack
}
}
else if(!isFunction && (methodStack.size()==0) && sEnd.equals(placeholderEndToken)) // Single template param such as <<param>>
{
value = getParam(sToken, context);
if(value != null)
{
if(value.trim().startsWith(placeholderStartToken))
{
value = render(src, context);
}
dst.append(value);
return i;
}
}
// TODO: Process method parameters to invoke
//.... ?????????
// Found end method token ')'
// Pop method out of stack to invoke
if ( (methodStack.size() >0) && (sEnd.length() == 0 || sEnd.equals(")")))
{
String method = null;
synchronized(this)
{
// Pop method out of stack to invoke
method = methodStack.pop();
--placeholders;
dst.append(invokeMethodEvaluator(method, methodParams.toArray(new String[0]), context));
methodParams.clear();
}
}
return i;
}
// Currently this method just implement to test so it just printout the method name
// and its parameter
// We can register MethodExpressionEvaluator to process
protected String invokeMethodEvaluator(String method, String[] params, RenderContext... context){
StringBuffer result = new StringBuffer();
result.append("[ ")
.append(method)
.append(" ( ");
if(params != null)
{
for(int i=0; i<params.length; i++)
{
result.append(params[i]);
if(i != params.length-1)
{
result.append(" , ");
}
}
}
result.append(" ) ")
.append(" ] ");
return result.toString();
}
}
We can easily register more method to the renderer to invoke. Each method will be an object and can be reused. But I'm in trouble how to resolve the nested method parameter. Can anyone give me an advice how we can process nested template of method parameter to invoke??? The line has TODO. Will my code in on the right way???
When you evaluate something like << count( << getTransId() >> ) >> you can either:
perform direct-evaluation as you parse, and push each function onto a stack, so that once you've evaluated getTransId() you pop the stack and use the return value (from the stack) as an argument for count(), or
you can build a parse tree to represent all the function calls that will be made, and then evaluate your parse tree after building it. (Building a tree probably doesn't buy you anything; since you're writing a template engine there is probably no high-level tree operation 'optimizations' that you could perform.)
An excellent little book I really enjoyed was Language Implementation Patterns by Parr. He walks through building simple to complex languages, and covers decisions like this in some depth. (Yes, he uses the ANTLR parser generator throughout, but your code looks like you're familiar enough with hand-generated parsers that different tools won't be a distraction for you.)
I found the bug and fixed it.
This is my new source:
// AbstractMethodExpressionRenderer.java
public class AbstractMethodExpressionRenderer extends AbstractMessageRenderer {
private boolean inSingleQuote = false;
private boolean inDoubleQuote=false;
private Stack<MethodExpressionDescriptor> functionStack;
private String[] endTokens;
private String marker;
private String prefix = "~";
public AbstractMethodExpressionRenderer() {
super();
functionStack = new Stack<MethodExpressionDescriptor>();
marker = ",";
endTokens = new String[] { placeholderEndToken, "(", ")", };
}
private class MethodExpressionDescriptor {
public List<String> params;
public String function;
public MethodExpressionDescriptor() {
params = new ArrayList<String>();
}
public MethodExpressionDescriptor(String name) {
this();
this.function = name;
}
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getMarker() {
return marker;
}
public void setMarker(String marker) {
this.marker = marker;
endTokens = new String[] { placeholderEndToken, marker };
}
#Override
public void setPlaceholderEndToken(String placeholderEndToken) {
super.setPlaceholderEndToken(placeholderEndToken);
endTokens = new String[] { placeholderEndToken, marker };
}
protected String doRender(String s, RenderContext... context) {
StringBuffer sb = new StringBuffer();
try
{
renderTemplate(s, sb, nullToken, 0, endTokens, null, context);
}
catch (Exception e)
{
Log4j.app.error("Exception in rendering method expression message emplate: " + e.getMessage(), e);
return nullToken;
}
return sb.toString();
}
private int renderTemplate(String src, StringBuffer dst, String nil, int i, String[] marks, StringBuffer end, RenderContext... context) {
int len = src.length();
while (i < len)
{
char c = src.charAt(i);
if (escape)
{
if (c=='\\')
{
i++;
char ch = src.charAt(i);
if(inSingleQuote)
{
if(ch=='\'')
{
inSingleQuote=false;
}
}
else if(inDoubleQuote)
{
if(ch=='"')
{
inDoubleQuote=false;
}
}
else
{
if(ch=='\'')
{
inSingleQuote=true;
}
else if(ch=='"')
{
inDoubleQuote=true;
}
}
dst.append(ch);
i++;
continue;
}
}
if(inSingleQuote)
{
if(c=='\'')
{
inSingleQuote=false;
}
}
else if(inDoubleQuote)
{
if(c=='"')
{
inDoubleQuote=false;
}
}
else
{
if(c=='\'')
{
inSingleQuote=true;
}
else if(c=='"')
{
inDoubleQuote=true;
}
}
// check for end marker
if (marks != null && !inSingleQuote && !inDoubleQuote)
{
for (int m = 0; m < marks.length; m++)
{
// If one of markers found
if (src.regionMatches(i, marks[m], 0, marks[m].length()))
{
// return marker if required
if (end != null)
{
end.append(marks[m]);
}
return i+marks[m].length();
}
}
}
// check for start of placeholder
if (src.regionMatches(i, placeholderStartToken, 0, lenPlaceholderStartToken))
{
i = renderPlaceholder(src, dst, nil, i, new ArrayList<String>(), context);
continue;
}
// just add plain character
if(c != '\'' && c!= '"')
{
dst.append(c);
}
i++;
}
return i;
}
/**
* Render a placeholder as follows:
*
* <<key>>: Simple render, key value map
* <<function(<<param1>>, <<param2>>)>> : Function object render
*
* #param src
* #param dst
* #param nil
* #param i
* #param params
* #param context
* #return
*/
private int renderPlaceholder(String src, StringBuffer dst, String nil, int i, List<String> params, RenderContext... context){
StringBuffer token = new StringBuffer(); // placeholder token
StringBuffer end = new StringBuffer(); // placeholder end marker
String value = null;
// Simple key
i = renderTemplate(src, token, nil, i+lenPlaceholderStartToken, endTokens, end, context);
String sToken = token.toString().trim();
String sEnd = end.toString().trim();
// This is method name
if(sEnd.equals("("))
{ // Method
functionStack.add(new MethodExpressionDescriptor(sToken));
}
else // Try to resolve value
{
if(sToken.startsWith(placeholderStartToken))
{
value = render(sToken, context);
}
else if(sToken.startsWith(prefix))
{
if(functionStack.size() > 0)
{
functionStack.peek().params.add(sToken.substring(1));
}
return i;
}
else
{
value = getParam(sToken, context);
}
}
if (sEnd.length() == 0 || sEnd.equals(placeholderEndToken))
{
// No method found but found the end of placeholder token
if(functionStack.size() == 0)
{
if(value != null)
{
dst.append(value);
}
else
{
dst.append(nil);
}
}
else
{
functionStack.peek().params.add(value);
}
}
else
{
if(value != null)
{
value = value.trim();
}
if(end.substring(0, 1).equals("(") ||
end.substring(0, 1).equals(marker))
{
// right hand side is remainder of placeholder
StringBuffer tmp = new StringBuffer();
end = new StringBuffer();
i = renderTemplate(src, tmp, nil, i, endTokens, end, context);
}
if(end.substring(0, 1).equals(")"))
{
if ( functionStack.size() > 0 )
{
// Pop method out of stack to invoke
MethodExpressionDescriptor descriptor = functionStack.pop();
if(functionStack.size() > 0 )
{
functionStack.peek().params.add(invokeMethodEvaluator(descriptor.function, descriptor.params.toArray(new String[0]), context));
}
else
{
dst.append(invokeMethodEvaluator(descriptor.function, descriptor.params.toArray(new String[0]), context));
}
end = new StringBuffer();
StringBuffer tmp = new StringBuffer();
i = renderTemplate(src, tmp, nil, i, endTokens, end, context);
}
}
}
return i;
}
protected String invokeMethodEvaluator(String method, String[] params, RenderContext... context){
StringBuffer result = new StringBuffer();
result.append("[ ")
.append(method)
.append(" ( ");
if(params != null)
{
for(int i=0; i<params.length; i++)
{
result.append(params[i]);
if(i != params.length-1)
{
result.append(" , ");
}
}
}
result.append(" ) ")
.append(" ] ");
return result.toString();
}
}
hey
i have text file shown as below.
11/2/2010 cat 6
11/2/2010 cat 3
11/2/2010 dog 4
11/2/2010 cat 11
11/3/2010 cat 1
11/3/2010 dog 3
11/3/2010 cat 8
i have in every month this kind of text file. Above figure shows the part of the text file. so then i want to read this text using java to Jtable.
i Have used StringTokanizer And Arreaylist to ceate this. Unfotunately i couldn't done it. SO PLS HELP ME........
So i want below result to jTable using java program.
date animal total count
11/2/2010 cat 20 3
11/3/2010 cat 9 2
You don't need a StringTokenizer (in fact, it's not recommended). Just get the input line by line using BufferedReader, and do a String split:
List<Array> data = new ArrayList<Array>();
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
String line;
// Read input and put into ArrayList of Arrays
while ((line = in.readLine) != null) {
data.add(line.split("\\s+"));
}
// Now create JTable with Array of Arrays
JTable table = new JTable(data.toArray(), new String[] {
"date", "animal", "total", "count"});
test with : http://crysol.org/es/node/819
or
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
public class Reader {
public Reader() {
// TODO Auto-generated constructor stub
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel();
BufferedReader reader;
try {
reader = new BufferedReader(new InputStreamReader(
new FileInputStream("sample.txt")));
Map<String, Object[]> result = new LinkedHashMap<String, Object[]>();
while (reader.ready()) {
String line = reader.readLine();
String[] values = line.split("\\s+");
String key = values[0] + "\t" + values[1];
String label = values[0];
String date = values[1];
Integer sum = 0;
Integer count = 0;
if (result.containsKey(key)) {
sum = (Integer) ((Object[]) result.get(key))[2];
count = (Integer) ((Object[]) result.get(key))[3];
} else {
}
result.put(key, new Object[]{label, date,
sum + Integer.parseInt(values[2]), count + 1});
}
ArrayList arrayList = new ArrayList(result.values());
/* interate and print new output */
/*
* for (String key : result.keySet()) { Integer sum =
* result.get(key); Integer count = result2.get(key);
* System.out.println(key + " " + sum + "\t" + count); }
*/
JTable table = new JTable(new AnimalTableModel(arrayList));
panel.add(new JScrollPane(table));
reader.close();
frame.setContentPane(panel);
frame.setVisible(true);
frame.pack();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Reader();
}
public class AnimalTableModel implements TableModel {
final Class[] columnClass = new Class[]{String.class, String.class,
Integer.class, Integer.class};
final String[] columnName = new String[]{"Date", "Animal", "Sum",
"Count"};
List values = null;
public AnimalTableModel(List values) {
this.values = values;
// initilize values
}
#Override
public void addTableModelListener(TableModelListener l) {
}
#Override
public Class<?> getColumnClass(int columnIndex) {
return columnClass[columnIndex];
}
#Override
public int getColumnCount() {
return columnClass.length;
}
#Override
public String getColumnName(int columnIndex) {
return columnName[columnIndex];
}
#Override
public int getRowCount() {
return values.size();
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return ((Object[]) values.get(rowIndex))[columnIndex];
}
#Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return false;
}
#Override
public void removeTableModelListener(TableModelListener l) {
}
#Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
// TODO FOR EDITABLE DT
}
}
}
You will have to populate the data to a map from the given file.I will give you an example as to how to populate the data.
public class AnimalMapping {
public static void main(String[] args) {
Object[][] data = { { "11/2/2010", "cat", 6 },
{ "11/2/2010", "cat", 3 }, { "11/2/2010", "dog", 4 },
{ "11/2/2010", "cat", 11 }, { "11/3/2010", "cat", 1 },
{ "11/3/2010", "dog", 3 }, { "11/3/2010", "cat", 8 } };
HashMap<String, Map<String, AnimalValCnt>> animalMap = new HashMap<String, Map<String, AnimalValCnt>>();
for (Object[] record : data) {
Map<String, AnimalValCnt> innerMap = null;
if ((innerMap = animalMap.get(record[0])) == null) {
innerMap = new HashMap<String, AnimalValCnt>();
animalMap.put((String) record[0], innerMap);
}
AnimalValCnt obj = null;
if ((obj = innerMap.get(record[1])) == null) {
obj = new AnimalValCnt();
innerMap.put((String) record[1], obj);
}
obj.Sumval += (Integer) record[2];
obj.cnt++;
}
System.out.println(animalMap);
}
}
class AnimalValCnt {
int Sumval;
int cnt;
#Override
public String toString() {
return "(" + Sumval + "," + cnt + ")";
}
}
Once you have got the data in a map then it's easy to populate these data to a table.You can use a tablemodel for this purpose.Have a look at this code to understand how data from a map can be loaded into a table using TableModel.
UPDATE:
public class AnimalMapping {
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader in = new BufferedReader(new FileReader("foo.in"));
String line;
String[] record;
HashMap<String, Map<String, AnimalValCnt>> animalMap = new HashMap<String, Map<String, AnimalValCnt>>();
while(((line = in.readLine()) != null)) {
record=line.split("\\s+");
Map<String, AnimalValCnt> innerMap = null;
if ((innerMap = animalMap.get(record[0])) == null) {
innerMap = new HashMap<String, AnimalValCnt>();
animalMap.put(record[0], innerMap);
}
AnimalValCnt obj = null;
if ((obj = innerMap.get(record[1])) == null) {
obj = new AnimalValCnt();
innerMap.put(record[1], obj);
}
obj.Sumval += Integer.valueOf(record[2]);
obj.cnt++;
}
System.out.println(animalMap);
}
}
class AnimalValCnt {
int Sumval;
int cnt;
#Override
public String toString() {
return "(" + Sumval + "," + cnt + ")";
}
}
#Dilantha Chamal: Reading from file was already given by Box9.I just included it in my code.You should be putting some effort here.Maybe you are a beginner that's why I wrote the code.Now try to implement the TableModel by yourself.Just a friendly advice:unless you do it you are never going to learn.
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import com.google.common.base.CharMatcher;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.google.common.io.LineProcessor;
public class AnimalSummaryBuilder
{
private static final Splitter SPLITTER = Splitter.on(CharMatcher.anyOf(","));
private static final Joiner JOINER = Joiner.on("\t");
#SuppressWarnings("unchecked")
public static void main(final String[] args) throws Exception
{
#SuppressWarnings("rawtypes")
Map<Animal, Summary> result = Files.readLines(new File("c:/1.txt"), Charsets.ISO_8859_1, new LineProcessor() {
private final Map<Animal, Summary> result = Maps.newHashMap();
public Object getResult()
{
return result;
}
public boolean processLine(final String line) throws IOException
{
Iterator<String> columns = SPLITTER.split(line).iterator();
String date = columns.next();
String name = columns.next();
int value = Integer.valueOf(columns.next()).intValue();
Animal currentRow = new Animal(date, name);
if (result.containsKey(currentRow))
{
Summary summary = result.get(currentRow);
summary.increaseCount();
summary.addToTotal(value);
}
else
{
Summary initialSummary = new Summary();
initialSummary.setCount(1);
initialSummary.setTotal(value);
result.put(currentRow, initialSummary);
}
return true;
}
});
for (Map.Entry<Animal, Summary> entry : result.entrySet())
{
Animal animal = entry.getKey();
Summary summary = entry.getValue();
System.out.println(JOINER.join(animal.date, animal.name, summary.total, summary.count));
}
}
final static class Animal
{
String date;
String name;
public Animal(final String date, final String n)
{
this.date = date;
this.name = n;
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((date == null) ? 0 : date.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (!(obj instanceof Animal))
{
return false;
}
Animal other = (Animal) obj;
if (date == null)
{
if (other.date != null)
{
return false;
}
}
else if (!date.equals(other.date))
{
return false;
}
if (name == null)
{
if (other.name != null)
{
return false;
}
}
else if (!name.equals(other.name))
{
return false;
}
return true;
}
}
final static class Summary
{
private int total;
private int count;
void setTotal(int value)
{
total = value;
}
void setCount(int i)
{
count = i;
}
void increaseCount()
{
count++;
}
void addToTotal(int valueToAdd)
{
total += valueToAdd;
}
}
}