Simplifying loops over hashmap values - java

I have the following code:
public void setSHAShortSha() {
if (parentTracked == null) {
String s = "";
for (Blob b : blobHashMap.values()) {
s += b.toString();
}
sha = Utils.sha1(logMessage + dateFormatted + s);
} else {
String s = "";
for (Blob b : blobHashMap.values()) {
s += b.toString();
}
for (Blob b : parentTracked.values()) {
s += b.toString();
}
sha = Utils.sha1(logMessage + dateFormatted + s);
}
shortSha = MyUtils.getShortSha(sha);
}
This looks a lot complex. Could there be a simpler way to write it in java?
boolean found = false;
for (Commit commit : commits.values()) {
if (commit.getLogMessage().compareTo(commitMessageToSearch) == 0) {
System.out.println(commit.getSha());
found = true;
}
}
if (!found) {
System.out.println("aksdhlkasj");
}
Adding one more code as that is on the same lines. I am little unfamiliar with different forms of for loop and streams need help converting them

You can join all of the values with streams:
s += blobHashMap.values().stream().map(Object::toString).collect(Collectors.joining());

You can at least avoid the repetition.
public void setSHAShortSha() {
String s = "";
for (Blob b : blobHashMap.values()) {
s += b.toString();
}
if (parentTracked != null) {
for (Blob b : parentTracked.values()) {
s += b.toString();
}
}
sha = Utils.sha1(logMessage + dateFormatted + s);
shortSha = MyUtils.getShortSha(sha);
}

you can use the forEach Method of the Map, like this:
StringBuilder stringBuilder = new StringBuilder();
blobHashMap.forEach((key, blob) -> {
stringBuilder.append(blob.toString());
});
if (parentTracked != null) {
parentTracked.forEach((key, blob) -> {
stringBuilder.append(blob.toString());
});
}
sha = Utils.sha1(logMessage + dateFormatted + stringBuilder.toString());
shortSha = MyUtils.getShortSha(sha);
}

Related

Issue in parsing TLV data in java, how to get value,length

I have tried many sample codes to parse APDU response to TLV format.
I am able to parse it properly if the response length is less but facing issue if length is more(how calculate length of a tag without any libraries)
NOTE: I am using predefined tags in Constants
code:
private HashMap<String, String> parseTLV(String apduResponse) {
HashMap<String, String> tagValue = new HashMap<>();
String remainingApdu = apduResponse.replaceAll(" ", "");
if (remainingApdu.endsWith(ResponseTags._SUCCESS_STATUSWORDS)) {
remainingApdu = remainingApdu.substring(0, remainingApdu.length() - 4);
}
while (remainingApdu != null && remainingApdu.length() > 2) {
remainingApdu = addTagValue(tagValue, remainingApdu);
}
return tagValue;
}
addTagValue method
private String addTagValue(HashMap<String, String> tagValue, String apduResponse) {
String tag = "";
String length = "";
String value = "";
int tagLen = 0;
if (tagUtils.isValidTag(apduResponse.substring(0, 2))) {
tagLen = readTagLength(apduResponse.substring(3));
// tagLen = 2;
tag = apduResponse.substring(0, 2);
} else if (tagUtils.isValidTag(apduResponse.substring(0, 4))) {
tagLen = 4;
tag = apduResponse.substring(0, 4);
} else {
return "";
}
Log.e("TAG_LEN","tag: "+tag+"taglen: "+tagLen);
if (tagUtils.shouldCheckValueFor(tag)) {
length = apduResponse.substring(tagLen, tagLen + 2);
int len = tagUtils.hexToDecimal(length);
value = apduResponse.substring(tagLen + 2, (len * 2) + tagLen + 2);
tagValue.put(tag, value);
if (ResponseTags.getRespTagsmap().containsKey(tag)) {
//logData = logData + "\nKEY:" + tag + " TAG:" + ResponseTags.getRespTagsmap().get(tag)/* + " VALUE:" + value + "\n "*/;
}
if (tagUtils.isTemplateTag(tag)) {
// logData = logData + "\n\t-->";
return addTagValue(tagValue, value) + apduResponse.substring(tag.length() + value.length() + length.length());
} else {
return apduResponse.substring(tag.length() + value.length() + length.length());
}
} else {
value = apduResponse.substring(2, 4);
tagValue.put(tag, value);
// logData = logData + "\n\t\tKEY:" + tag + " TAG:" + ResponseTags.getRespTagsmap().get(tag) /*+ " VALUE:" + value + "\n "*/;
return apduResponse.substring(tag.length() + value.length() + length.length());
}
}
readTagLength :
private int readTagLength(String apduResponse) {
int len_bytes = 0;
if (apduResponse.length() > 2) {
len_bytes = (apduResponse.length()) / 2;
}
Log.e("tlv length:", "bytes:" + len_bytes);
if (len_bytes < 128) {
return 2;
} else if (len_bytes > 127 && len_bytes < 255) {
return 4;
} else {
return 6;
}
}
I cannot able to get length properly for few cards(if apdu response is long)
Please help
First be sure the input data is proper before you go into the code. Take the full data and try it on https://www.emvlab.org/tlvutils/ .
Once its confirmed the data is proper, go through in EMV 4.3 Book 3,
Annex B Rules for BER-TLV Data Objects sections B1, B2, B3 - with utmost attention.
If you follow this precisely, then you wouldn't need to store a static list of tags; will save time in future.
Below sample has an assumption that TLV array is ending with special 0x00 tag but for sure you can ignore it.
Pojo class :
public class Tlv {
private short tag;
private byte[] value;
public Tlv(short tag) {
this.tag = tag;
}
public short getTag() {
return tag;
}
public byte[] getValue() {
return value;
}
public void setValue(byte[] valueBytes) {
this.value = valueBytes;
}
}
Utility method :
public static Map<Byte, Tlv> parse(ByteBuffer bb) throws TlvException {
Map<Byte, Tlv> tlvs = null;
tlvs = new HashMap<Byte, Tlv>();
try {
while (bb.remaining() > 0) {
byte tag = bb.get();
if(tag == 0x00)
continue;
int length = bb.get();
byte[] value = new byte[length];
bb.get(value, 0, length);
Tlv tlv = new Tlv(tag);
tlv.setValue(value);
tlvs.put(tag, tlv);
}
} catch (IndexOutOfBoundsException e) {
throw new TlvException("Malformed TLV part: " + bb.toString() + ".", e);
}
return tlvs;
}

How to remove logical error

I want to print the all values in the array but it just prints the last value int the array, how can I get my desired result by improving this code:
public void applyAttendence(ArrayList<String> presents, ArrayList<String> absents) {
ArrayList<String> present = new ArrayList<String>();
HashMap params = new HashMap();
// [232, 232, 12, 223]
String[] stringArray = presents.toArray(new String[0]);
if (presents.size() == 0) {
params.put("present", "");
} else {
// for(String pre:presents) {
params.put("present", stringArray);
System.out.println(" present[]" + presents);
System.out.println("hellow present man: " + params.get("present"));
// }
System.out.println("hellow present man: " + params.get("present"));
}
if (absents.size() == 0) {
params.put("absent", "");
} else {
for (String abs : absents) {
params.put("absent[]", abs);
}
// params.put("present[]", presents + "");
//
params.put("absent[]", absents + "");
}
}
That is because you are overwriting same key with different value every time
for (String abs : absents) {
params.put("absent[]", abs);
}
So your hashmap will only have last value written against the key absent[]
This is may be you have defined array as:
String[] stringArray = presents.toArray(new String[0]);
try initializing as:
String[] stringArray = new String[presents.size()];
stringArray = presents.toArray(stringArray );
Try this simplified solution to show all of the attendance
public void applyAttendence(ArrayList<String> presents, ArrayList<String> absents) {
String sPresent = "";
for (String present : presents) {
sPresent += present + ", ";
}
if (!sPresent.equals(""))
sPresent = sPresent.substring(0, sPresent.length() - 2);
String sAbsent = "";
for (String absent : absents) {
sAbsent += absent + ", ";
}
if (!sAbsent.equals(""))
sAbsent = sAbsent.substring(0, sAbsent.length() - 2);
if (presents.size() > 0) {
System.out.println("present = " + sPresent);
} else {
System.out.println("present = no one");
}
if (absents.size() > 0) {
System.out.println("absent = " + sAbsent);
} else {
System.out.println("absent = no one");
}
}

Android insert data in Db from file which have multiple lines for each Insert query

I want to pre-populate my database. So I generate SQL queries from browser and write code to insert them in db. It is working fine for the single line query but most insert queries have multiple line for example `
INSERT INTO `poem` VALUES (780,'سلام القلب واشواقه
من قلب يحب مجنونه
ياليت هالقلب يحن
ويقول هالدنيا
ماتسوى دون *_*','0',NULL);`
My requirement is to insert them as they are. That is the method i wrote for multiple line (works perfect for single line query)
public static int countLines(InputStream is) throws IOException {
try {
byte[] c = new byte[1024];
int count = 0;
int readChars = 0;
boolean empty = true;
int index = 0;
while ((readChars = is.read(c)) != -1) {
empty = false;
String temp = new String(c);
for (int i = 0; i < readChars; i++) {
if (c[i] == ';' && index == 0) {
index++;
} else if (c[i] == '\n' && index == 1) {
index++;
} else if (c[i] == '\t' && index == 2) {
index++;
} else if (c[i] == 'I' && index == 3) {
count++;
index = 0;
} else {
i -= index;
index = 0;
}
}
}
return (count == 0 && !empty) ? 1 : count + 1;
} finally {
is.close();
}
}
Anyone have idea how to insert such queries from file to DB.?
Any help would be great. Thanks
What you are asking is an ugly way of doing things. Use sqliteassethelper to create prepopulated databases and tables. It works extremely similar to SQLiteOpenHelper so it is very easy to use.
Sorry for late response in case of anyone having same issue
Here is the solution step by step
I create a .sql file which contain insert queries (some Include multiline queries) ends with :.
In my onCreate() method of SQLiteOpenHelper I m counting lines of my file using getFileLineCount(). This method return me the count of line. This line count is never used , but I had it because if all your queries are single line, it might comes into play. You can skip this method.
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE \"" + TABLE_POEM + "\" (\"" + POEM_LOCAL_ID + "\" INTEGER PRIMARY KEY AUTOINCREMENT , \"" + POEM_TEXT + "\" TEXT,\"" + POEM_ID + "\" INTEGER , \"" + POEM_IS_FAV + "\" TEXT);");
int totalLineCount = getFileLineCount("poem.sql");
int insertCount = insertFromFile(db, "poem.sql", totalLineCount);
Log.d("DatabaseHelper", "------------onCreate(SQLiteDatabase db) >>>>>>> completed--------");
}
private int getFileLineCount(String assetFilePath) {
InputStream insertStream = null;
int totalCount = 0;
try {
insertStream = context.getAssets().open(assetFilePath);
totalCount = FileUtil.countLines(new BufferedInputStream(insertStream));
} catch (Exception e) {
e.printStackTrace();
} finally {
if (insertStream != null) {
try {
insertStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return totalCount;
}
By using this method I insert queries from file. It handles both single line queries and multi line queries. First I check if line contain ";" it means the line is ended else not ended. Pretty simple it was at the end.
while ((currentLine = insertReader.readLine()) != null) {
if (currentLine.length() != 0) {
if (currentLine.charAt(currentLine.length() - 1) == ';') {
insertInDb(db, insertStr + "\n" + currentLine);
insertStr = "";
} else {
insertStr += currentLine;
}
}
}
private int insertFromFile(SQLiteDatabase db, String assetFilePath, int totalCount) {
int result = 0;
BufferedReader insertReader = null;
try {
InputStream insertStream = context.getAssets().open(assetFilePath);
insertReader = new BufferedReader(new InputStreamReader(insertStream));
db.beginTransaction();
while (insertReader.ready()) {
// String insertStr = insertReader.toString();
String insertStr = "";
String currentLine;
while ((currentLine = insertReader.readLine()) != null) {
if (currentLine.length() != 0) {
if (currentLine.charAt(currentLine.length() - 1) == ';') {
insertInDb(db, insertStr + "\n" + currentLine);
insertStr = "";
} else {
insertStr += currentLine;
}
}
}
}
db.setTransactionSuccessful();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (insertReader != null) {
try {
insertReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
db.endTransaction();
}
return result;
}
private void insertInDb(SQLiteDatabase db, String assetFilePath) throws IOException {
if (assetFilePath != null && assetFilePath.length() > 0) {
SQLiteStatement statement = db.compileStatement(assetFilePath);
statement.execute();
}
}
I used this technique to insert 4000 records in db. And it was working fine without much of the lag. If anyone have any batter solution for it. Kindly post it.

Reflection recursive display of object with attributes types, names and values

I have some complex objects that I would like to print out including the attributes names, types and values. As long as I don't know in advance the amount and depth of all attributes/sub-attributes, I need a recursive call including a loop. I have done it for 2 levels
StringBuilder descr = new StringBuilder();
foreach (PropertyInfo propertyInfo in req.GetType().GetProperties())
{
if (propertyInfo.CanRead)
{
string attributValue = "";
string attributName = propertyInfo.Name;
Type attributType = propertyInfo.PropertyType;
var propertyInfoValue = propertyInfo.GetValue(req, null);
//if (attributType == typeof(XFkType))
if (attributType != typeof(System.String) &&
attributType != typeof(System.Boolean))
{
PropertyInfo[] nestedpropertyInfoArray = propertyInfo.PropertyType.GetProperties();
attributValue += "{";
foreach (PropertyInfo subProperty in nestedpropertyInfoArray)
{
// var instance = (EntityBase)Activator.CreateInstance(subClass);
attributValue += subProperty.Name + "=";
try
{
attributValue += propertyInfoValue == null ? "" : subProperty.GetValue(propertyInfoValue, null).ToString();
}
catch (Exception e)
{
attributValue += "null";
}
attributValue += ",";
}
attributValue = attributValue.Length > 1 ? attributValue.Substring(0, attributValue.Length - 1) : attributValue;
attributValue += "}";
}
else
attributValue = propertyInfo.GetValue(req, null) == null ? "" : propertyInfo.GetValue(req, null).ToString();
descr.Append("[" + propertyInfo.PropertyType + "]" + attributName + "=" + attributValue + " | ");
}
}
The result is something like:
[XPhone]class{Phone,protocol=SIP,protocolSide=User,callingSearchSpaceName=XFkType,devicePoolName=XFkType,commonDeviceConfigName=XFkType,commonPhoneConfigName=XFkType,networkLocation=Use System Default,locationName=XFkType,mediaResourceListName=null,wirelessLanProfileGroup=null,ctiid=null} | [System.UInt64]sequence={} | [System.Boolean]sequenceSpecified=False |
It's a bit difficult to understand your structures but I would expect the solution to be in the following form:
public String propertyDescription(PropertyInfo[] properties) {
StringBuilder description;
for (PropertyInfo property: properties) {
if (property.containsNestedProperties()) {
description.append(propertyDescription(property.getNestedProperties()));
} else {
description.append( ... );
}
}
return description.toString();
}

JAVA String concatenanting with comma

Hey guys can somebody show me a way good way of concatenating these strings with commas
Basically Im building a header criteria string showing which forms variables have been selected. I need to put commas in between the values and keep the break tags in place...can somebody see a better way to do it. I didnt want commas if there were just on value
This is what it looks like currently formatted:
protected final String getCriteriaHeader(MetricFilterCriteriaForm form)
{
String filterCriteria = "<br/>";
}
if (form.isSacNone() || form.isSac1() || form.isSac2() || form.isSac3())
{
filterCriteria = filterCriteria + "SAC:";
}
if (form.isSacNone())
{
filterCriteria = filterCriteria + " NONE";
}
if (form.isSac1())
{
filterCriteria = filterCriteria + " 1";
}
if (form.isSac2())
{
filterCriteria = filterCriteria + " 2";
}
if (form.isSac3())
{
filterCriteria = filterCriteria + " 3";
}
if (form.isSac1() || form.isSac2() || form.isSac3())
{
filterCriteria = filterCriteria + "<br/>";
}
if (form.isRegularScheduleType() || form.isLotScheduleType() || form.isBatchScheduleType())
{
filterCriteria = filterCriteria + "Schedule Type:";
}
if (form.isRegularScheduleType())
{
filterCriteria = filterCriteria + " Regular";
}
if (form.isLotScheduleType())
{
filterCriteria = filterCriteria + " Lot";
}
if (form.isBatchScheduleType())
{
filterCriteria = filterCriteria + " Batch";
}
return filterCriteria;
}
There are different ways to concatenate a set of values in a string with a separator.
With StringBuilder
Add the values with the comma, then remove the last comma manually.
StringBuilder sb = new StringBuilder();
if (/*condition1*/) {
sb.add("A,"); // value with comma
}
if (/*condition2*/) {
sb.add("B,");
}
sb.delete(sb.length()-1, sb.length()); // remove last character, which is the comma.
String result = sb.toString(); // get the result string.
With Guava's Joiner
Put it all in a List and use Joiner.
List<String> list = Lists.newArrayList();
if (/*condition1*/) {
list.add("A"); // no comma here
}
if (/*condition2*/) {
list.add("B");
}
String result = Joiner.on(",").join(list); // use Joiner to join elements of the list.
Alternatively to Guava, there is StringUtils.Join from Apache Common Lang. See #Iswanto San's answer.
You can use StringUtils.Join from Apache Common Lang
Example :
protected final String getCriteriaHeader(MetricFilterCriteriaForm form)
{
String filterCriteria = "<br/>";
List<String> sacs = new ArrayList<String>();
List<String> schedules = new ArrayList<String>();
if (form.isSacNone() || form.isSac1() || form.isSac2() || form.isSac3())
{
filterCriteria = filterCriteria + "SAC:";
}
if (form.isSacNone())
{
filterCriteria = filterCriteria + " NONE";
}
if (form.isSac1())
{
sacs.add(" 1");
}
if (form.isSac2())
{
sacs.add(" 2");
}
if (form.isSac3())
{
sacs.add(" 3");
}
filterCriteria += StringUtils.join(saces, ",");
if (form.isSac1() || form.isSac2() || form.isSac3())
{
filterCriteria = filterCriteria + "<br/>";
}
if (form.isRegularScheduleType() || form.isLotScheduleType() || form.isBatchScheduleType())
{
filterCriteria = filterCriteria + "Schedule Type:";
}
if (form.isRegularScheduleType())
{
schedules.add(" Regular");
}
if (form.isLotScheduleType())
{
schedules.add(" Lot");
}
if (form.isBatchScheduleType())
{
schedules.add(" Batch");
}
filterCriteria+=StringUtils.join(schedules, ",");
return filterCriteria;
}
At first avoid creating so much String instances by using StringBuilder. Then nest the conditions to speed things up a bit and to get more structure.
protected final String getCriteriaHeader(MetricFilterCriteriaForm form)
{
StringBuilder filterCriteria = new StringBuilder("<br/>");
if (form.isSacNone() || form.isSac1() || form.isSac2() || form.isSac3())
{
filterCriteria.append("SAC:");
if (form.isSacNone())
filterCriteria.append(" NONE");
if (form.isSac1() || form.isSac2() || form.isSac3())
{
if (form.isSac1())
filterCriteria.append(" 1,");
if (form.isSac2())
filterCriteria.append(" 2,");
if (form.isSac3())
filterCriteria.append(" 3,");
if(','==filterCriteria.charAt(filterCriteria.length-1) )
filterCriteria.deleteCharAt(filterCriteria.length-1)
filterCriteria.append("<br/>");
}
}
if (form.isRegularScheduleType() || form.isLotScheduleType() || form.isBatchScheduleType())
{
filterCriteria.append("Schedule Type:");
if (form.isRegularScheduleType())
filterCriteria.append(" Regular,");
if (form.isLotScheduleType())
filterCriteria.append(" Lot,");
if (form.isBatchScheduleType())
filterCriteria.append(" Batch,");
if(','==filterCriteria.charAt(filterCriteria.length-1) )
filterCriteria.deleteCharAt(filterCriteria.length-1)
}
return filterCriteria.toString();
}
If only one condition can be true,you can also use else if instead of cascades of if.
You could use a StringBuilder to build the string, it's better than simple string concatenation :
StringBuilder sb = new StringBuilder();
if(XX) {
sb.append("XX");
}
return sb.toString();
Hope this helps :)
PS: Note that StringBuilder is faster than StringBuffer, but the latter is Thread-safe.
EDIT
I re-read your question, and it seems I don't answer it well, although I provided useful advice (IMHO). I don't understand exactly what you need.
I would suggest whacking the thing into a List then using a StringBuilder:
protected final String getCriteriaHeader(MetricFilterCriteriaForm form) {
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("<br/>");
final List<String> sacList = new LinkedList<String>();
if (form.isSacNone() || form.isSac1() || form.isSac2() || form.isSac3()) {
stringBuilder.append("SAC: ");
}
if (form.isSacNone()) {
sacList.add("NONE");
}
if (form.isSac1()) {
sacList.add("1");
}
if (form.isSac2()) {
sacList.add("2");
}
if (form.isSac3()) {
sacList.add("3");
}
final Iterator<String> sacIter = sacList.iterator();
while (sacIter.hasNext()) {
stringBuilder.append(sacIter.next());
if (sacIter.hasNext()) {
stringBuilder.append(", ");
}
}
if (form.isSac1() || form.isSac2() || form.isSac3()) {
stringBuilder.append("<br/>");
}
final List<String> scheduleTypeList = new LinkedList<String>();
if (form.isRegularScheduleType() || form.isLotScheduleType() || form.isBatchScheduleType()) {
scheduleTypeList.add("Schedule Type: ");
}
if (form.isRegularScheduleType()) {
scheduleTypeList.add("Regular");
}
if (form.isLotScheduleType()) {
scheduleTypeList.add("Lot");
}
if (form.isBatchScheduleType()) {
scheduleTypeList.add("Batch");
}
final Iterator<String> scheduleTypeIter = scheduleTypeList.iterator();
while (scheduleTypeIter.hasNext()) {
stringBuilder.append(scheduleTypeIter.next());
if (scheduleTypeIter.hasNext()) {
stringBuilder.append(", ");
}
}
return stringBuilder.toString();
}

Categories