Java - Objective C - for each loop issue - java

I'm trying to build an application in Android using some codes from Objective-C (IPhone app).I'm trying to understand what exactly is doing a piece of code and translate it into Java code,but I think I need a little help here.So first, here is the Obj-C code :
(BOOL)processSqlInjectQueries:(NSArray *)injectQueries error:(NSError**)error {
//some code
for(NSDictionary * q in injectQueries)
{
if (![q isKindOfClass:[NSDictionary class]]) continue;
StPacketInjectQueryPackage qType = (StPacketInjectQueryPackage)[[q objectForKey:#"type"] intValue];
NSString * query = [q objectForKey:#"query"];
}
//some code
}
In Java, I'm trying to do something like this :
// in some other method :
JSONObject jsonData= new JSONObject();
String authHash = jsonData.getJSONObject("client_auth_hash").toString();
List<Map<String,String>> injectQueries= new ArrayList<Map<String,String>>();
injectQueries.add(new HashMap<String, String>());
//injectQueries.add(authHash);
public boolean processSqlInjectQueries(List<Map<String,String>> injectQueries, Exception error){
if(injectQueries==null || injectQueries.size()==0){
boolean injectsProcessed = this.processSqlInjectQueries(injectQueries,error);
if(!injectsProcessed){
return false;
}
}
Log.i("Info","Processing INJECT Queries...");
boolean res = true;
/*[_dbAdapter beginTransaction];
[_user.userDbAdapter beginTransaction];*/
for(Map<String,String> b : injectQueries){
if(b.getClass().getName()!=injectQueries.getClass().getName()){
continue;
}
//RPCPacketInjectQueryPackage qType = (RPCPacketInjectQueryPackage)
}
return true;
}
But my problem is that is that I get this error : Type mismatch: cannot convert from element type Object to ArrayList.
Any suggestion how to fix that error?
And second question : Can I use Exception error in declaraion of processSqlInjectQueries instead of NSError *error in Obj-C?

Iterating over the ArrayList
The error is being raised because your code needs to declare that b is an Object (since injectQueries contains objects of type Object, not objects of type ArrayList):
for(Object b : injectQueries){
...
}
Since the NSDictionary class in Objective-C closely resembles the Map class in Java, you can mimic the Objective-C code by casting b as a Map, or even better, you can use generics to specify that injectQueries contains Map objects. For example:
public boolean processSqlInjectQueries(List<Map<String,String> injectQueries, Exception error) {
// some code
for(Map<String,String> b : injectQueries) {
...
}
// some code
return true;
}
Exception Handling
As for your second question, methods in Java normally communicate error conditions by throwing Exception objects, so your method signature would resemble the following:
public boolean processSqlInjectQueries(List<Map<String,String> injectQueries) throws Exception
Note that it's always better to be specific with your exceptions (i.e. to throw objects that are subclasses of Exception) so that your method caller has some idea of what went wrong. See the following link for additional guidelines for handling exceptions in Java:
http://www.javapractices.com/home/HomeAction.do#Exceptions

The objective C code is passing through an NSArray containing NSDictionaries through to the method, so the following is probably closer to what you want to do...
public boolean processSqlInjectQueries(List<Map<String,String> injectQueries) {
for(Map<String,String> q : injectQueries) {
// do stuff with q
}
}
To handle the error code, you probably want to think about throwing an exception rather than trying to pass through an "Error" object, so something like the following:
public boolean processSqlInjectQueries(List<Map<String,String> injectQueries) throws Exception {
for(Map<String,String> q : injectQueries) {
// do stuff with q
}
if(errorConditionOccurs) {
throw new Exception();
}
}
You'll want to tailor the exact Exception that's thrown so it matches whatever your code is trying to do.
In response to comment: perhaps this is closer to what you're trying to do?
public boolean processSqlInjectQueries(JSONObject jsonObject) {
for(String key : jsonObject.keys()) {
Object value = jsonOnject.get(key);
// Do stuff with value
}
// Do more stuff
}
And you could call it with:
processSqlInjectQueries(jsonData.getJSONObject("client_auth_hash"));

Related

How do I iterate over return type of Either<ClientError, List<Employee>>?

Lets say my function A is returning Either<ClientError, List>.
I assign it to a variable lets say:
val employeeList = A().
for (e in employeeList) gives me an error saying "for loop must have iterator". How do I overcome this?
Not sure about using either, but you can try using a when statement to cast the result to you appropriate type.
Something like this
when(val result = myFunction()){
is ClientError -> { //your code}
is List<> -> { //your code}
else -> {//..}
}
The best approach would be to make another sealed class, that contains your two type that you want to return.
sealed class MySealedClass{
data class Success(val data: List<Employee>) : MySealedClass()
data class Failed(val error: ClientError) : MySealedClass()
}
then, return this type from your function
fun myFunction(): MySealedClass{
return if() MySealedClass.Failed(ClientError()) else MySealedClass.Success(resultList)
}
And use the same approach with when, but this time without an else branch
when(val result = myFunction()){
is MySealedClass.Failed -> { //your code}
is MySealedClass.Success -> { //your code}
}

Why doesn't instanceof narrow multicatch union types

The sample function catches checked Exceptions A and B and throws A.
I expected the if statement with instanceof to unwind the union to the expected type, however I still need to cast it.
Is there a reason Java's type system can't/doesn't unwind the union type with instanceof?
public static void throwsA() throws ExceptionA {
try {
funThatThrowsAorB();
} catch (ExceptionA | ExceptionB e) {
// common code
if (e instanceof ExceptionA) {
throw e; // unhandled exception error
throw (ExceptionA)e; // no problem
} else {
throw new ExceptionA(e);
}
}
}
The Java language never narrows a type when entering an if-statement (or any other conditional).
However, Java 14 introduced pattern matching for instanceof expressions as a preview feature:
if (obj instanceof String s) {
// can use s here
} else {
// can't use s here
}
As you can see, this introduces a new variable with the narrowed type, rather than narrowing the type of the existing variable. I am not certain why they chose that route, but I suspect backwards compatibility played a role. Specifically, if you simply narrow the type of an existing variable when entering a conditional, it might break existing code such as the following program:
Number number = 42;
if (number instanceof Integer) {
number = 0.01 * number;
}
To fix that, you'd need to change the type of the variable not just when entering a conditional, but on any assignment. That's more complicated, but TypeScript shows that this is possible:
let x: number | string = "23";
if (typeof x === "string") {
x.charAt(0); // x is a string here
x = 3;
x.toPrecision(2); // but a number here
}
I don't know why the Java design team disliked the TypeScript approach.
Because when you are inside of the catch block, e is an instance of a capture type for both exceptions A and B. By casting, you are specifying that you are throwing ExceptionA specifically:
//e is an "instanceof" either ExceptionA or ExceptionB, but not specified yet!
//For now, e is simply the most specific shared parent type (Exception I assume)
ExceptionA eA; //Cannot be set to e! Cannot coerce Exception into ExceptionA
if (e instanceof ExceptionA) {
eA = (ExceptionA) e; //Have to explicitly cast
throw eA;
}
This works, because your method is specified to be capable of only throwing ExceptionA:
public static void throwsA() throws ExceptionA { ...
As far as why this is required, the error message from attempting an assignment is also pretty clear:
#Andreas offers a much more clear solution, which is just directly handling these errors individually:
try {
//A or B exceptional code
} catch (ExceptionA eA) {
throw eA;
} catch (ExceptionB eB) {
//... B handling
}

How check if an Attribute(object) is null in Java

I need specific data for a report, then I gettin all information from a parent object
Object1
It has many attributes, object attributes
Object11, Object12, Object13, attr1, attr2...
The attributes has many attributes too
Object111, Object131, Object132,..
by now I got 5 level data attributes.
When I send information to my report it says, Error: cause:null
object1.getIdObject11().getIdObject111().getDescription;
It trows error because Object111 is null
I tried using
object1.getIdObject11().getIdObject111().getDescription==null?'':object1.getIdObject11().getIdObject111().getDescription;
but it only verify if description is null, and throws the same error
Then I tried to verify Object
if(object1.getIdObject11().getIdObject111() == null) {
var = object1.getIdObject11().getIdObject111().getDescription;
} else {
var = "";
}
But when Object11 is null, it throws same error.
I don't think its a good way doing this for each attribute (have to get like 30 attributes)
if(object1.getIdObject11()!=null) {
if(object1.getIdObject11().getIdObject111()!=null) {
if(object1.getIdObject11().getIdObject111().getIdObject1111()!=null) {
//...
}
}
}
I want to verify if is there a null object and set '' (blank) if it is, with no such a large code(because the gotten params are set inside a report, mixed with letter).
reportline1 = "Area: "+object1.getIdObject11().getIdObject111().getName;
You code breaks Demeter's law. That's why it's better to refactor the design itself.
As a workaround, you can use Optional
var = Optional.ofNullable(object1)
.map(o -> o.getIdObject11())
.map(o -> o.getIdObject111())
.map(o -> o.getDescription())
.orElse("")
The way I would probably do this to extend the functionality of the code easily in the future might take a bit of writing in the beginning but will be easily usable forever.
I would create a new method in your parent class called hasNull that returns a boolean like so:
public boolean hasNull()
{
boolean hasANull = false;
//Call another hasNull() inside of object11 which in turns calls hasNull() in object111 etc.
//If any of the calls return with a true/null value set hasANull to true
return hasANull;
}
This in turn checks to see if the current objects it contains are null. If one of the class variables is another custom class you created you can then add another hasNull into that one and keep going until you get to the lowest level where you can do a specific operation when the value is null such as set it to "".
After implementing this you will be able to just be able to use it like this any time you need it:
if (!object1.hasNull())
{
//Do whatever you want if there are no null values
}
else
{
//Do whatever you want if there is a null value
}
You can also make this a void method if you only want it to toggle the values on the lowest level, and do not need to do anything in either case.
I prefer the solution that gave dehasi.
But you can also do something like that:
getOrElse(() -> object1.getIdObject11().getIdObject111().getDescription(), "")
Where getOrElse is:
public static <T> T getOrElse(Supplier<T> getter, T elseValue) {
try {
return getter.get();
} catch (Exception e) {
// log or do something with it
}
return elseValue;
}
It may be controversial becaouse you use Exception to do this.
You can use this code to check if your object has a null attribute, the object is myclass;
for (Field f : myclass.getClass().getDeclaredFields()) {
f.setAccessible(true);
try {
if (Objects.isNull(f.get(myclass))) {
isLineContainsNull = true;
}
} catch (Exception e) {
log.error(e.getMessage());
}
}

Continue the flow after throwing exception

In my use case, I am looping across a map and checking whether a particular key is present in a list. If it is present then I have to trow and exception otherwise continue with the execution.
Map<A,B> myMap = new HashMap<A,B>();
//code to populate values in myMap
...
...
List<A> myList = new ArrayList<A>();
//code to populate values in myList
...
...
for(Map.Entry<A,B> eachElementInMap:myMap.entrySet()){
if(myList.contains(eachElementInMap:myMap.getKey())){
//throwing exception
throw new MyCustomizedException("someString");
}
}
//code continues
...
....
In the above example, if there are 3 elements in the map(myMap) in which 1 key is present in the list(myList), I want to throw the exception for one and it should continue executing other lines of code for the rest two. Am I using a wrong design to achieve this? Any help or suggestion is appreciated! Thanks
Typically once you throw an exception, you are saying that the current line of execution should terminate, rather than continue. If you want to keep executing code, then maybe hold off on throwing an exception.
boolean fail = false;
for (Map.Entry<A,B> eachElementInMap:myMap.entrySet()) {
if (myList.contains(eachElementInMap:myMap.getKey())) {
// throw an exception later
fail = true;
}
}
if (fail) {
throw new MyCustomizedException("someString");
}
You can also create an exception object at a different location from where you throw it. This idiom will be useful in cases where the exception message is not just "someString", but needs to be constructed from data obtained from the object being iterated over.
Optional<MyCustomizedException> exception = Optional.empty();
for (Map.Entry<A, B> eachElementInMap:myMap.entrySet()) {
if (myList.contains(eachElementInMap.getKey())) {
// Create an exception object that describes e.g., the missing key(s)
// but do not throw it yet.
if( exception.isPresent() ) {
exception.get().addToDescription( /* Context-sensitive information */ );
}
else {
exception = Optional.of(
new MyCustomizedException( /* Context-sensitive information */));
}
}
}
if( exception.isPresent() ) {
throw exception.get();
}
If the only data stored in the exception is a string, an equivalent effect can be achieved by accumulating problem descriptions in a StringBuilder, but for cases where more interesting data needs to go into the exception object, building as you go might be an option worth considering.
You can split it into two lists,failList and successList. and do it.
This is clearer
failList = myMap.entrySet().stream().filter(p->myList.contains(p.getKey())).collect(Collectors.toList());
successList = myMap.entrySet().stream().filter(p->!myList.contains(p.getKey())).collect(Collectors.toList());
failList.forEach(p -> {
// fail code
});
successList .forEach(p -> {
// success code
});
why not use if...else instead of try catch ? error just means that's a mistake. if you afraid that makes some mistakes what you don't know. you can use throw error.
anyway, it should not be used when the program is running as you wish

Google Collections Suppliers and Find

I'm looking for a Google Collections method that returns the first result of a sequence of Suppliers that doesn't return null.
I was looking at using Iterables.find() but in my Predicate I would have to call my supplier to compare the result against null, and then have to call it again once the find method returned the supplier.
Given your comment to Calm Storm's answer (the desire not to call Supplier.get() twice), then what about:
private static final Function<Supplier<X>, X> SUPPLY = new Function<....>() {
public X apply(Supplier<X> in) {
// If you will never have a null Supplier, you can skip the test;
// otherwise, null Supplier will be treated same as one that returns null
// from get(), i.e. skipped
return (in == null) ? null : in.get();
}
}
then
Iterable<Supplier<X>> suppliers = ... wherever this comes from ...
Iterable<X> supplied = Iterables.transform(suppliers, SUPPLY);
X first = Iterables.find(supplied, Predicates.notNull());
note that the Iterable that comes out of Iterables.transform() is lazily-evaluated, therefore as Iterables.find() loops over it, you only evaluate as far as the first non-null-returning one, and that only once.
You asked for how to do this using Google Collections, but here's how you would do it without using Google Collections. Compare it to Cowan's answer (which is a good answer) -- which is easier to understand?
private static Thing findThing(List<Supplier<Thing>> thingSuppliers) {
for (Supplier<Thing> supplier : thingSuppliers) {
Thing thing = supplier.get();
if (thing != null) {
return thing;
}
}
// throw exception or return null
}
In place of the comment -- if this was the fault of the caller of your class, throw IllegalArgumentException or IllegalStateException as appropriate; if this shouldn't have ever happened, use AssertionError; if it's a normal occurrence your code that invokes this expects to have to check for, you might return null.
What is wrong with this?
List<Supplier> supplierList = //somehow get the list
Supplier s = Iterables.find(supplierList, new Predicate<Supplier>(){
boolean apply(Supplier supplier) {
return supplier.isSomeMethodCall() == null;
}
boolean equals(Object o) {
return false;
}
});
Are you trying to save some lines? The only optimisation I can think is to static import the find so you can get rid of "Iterables". Also the predicate is an anonymous inner class, if you need it in more than one place you can create a class and it would look as,
List<Supplier> supplierList = //somehow get the list
Supplier s = find(supplierList, new SupplierPredicateFinder());
Where SupplierPredicateFinder is another class.
UPDATE : In that case find is the wrong method. You actually need a custom function like this which can return two values. If you are using commons-collections then you can use a DefaultMapEntry or you can simply return an Object[2] or a Map.Entry.
public static DefaultMapEntry getSupplier(List<Supplier> list) {
for(Supplier s : list) {
Object heavyObject = s.invokeCostlyMethod();
if(heavyObject != null) {
return new DefaultMapEntry(s, heavyObject);
}
}
}
Replace the DefaultMapEntry with a List of size 2 or a hashmap of size 1 or an array of length 2 :)

Categories

Resources