How to avoid cumbersome holder in kotlin - kotlin

I have to deal with the following java code
abstract class ScriptResult {
void ifSuccess(Consumer<Object> block) {
}
void ifError(Consumer<Throwable> block) {
}
static class Success extends ScriptResult {
private final Object returnValue;
Success(Object returnValue) {
this.returnValue = returnValue;
}
#Override
void ifSuccess(Consumer<Object> block) {
block.accept(returnValue);
}
}
static class Error extends ScriptResult {
private final Throwable throwable;
Error(Throwable throwable) {
this.throwable = throwable;
}
#Override
void ifError(Consumer<Throwable> block) {
block.accept(throwable);
}
}
}
My kotlin tests make use of the following assertion helper:
private lateinit var scriptResult: ScriptResult
inline fun <reified T : Throwable> shouldHaveThrown(): T {
scriptResult.ifSuccess { result ->
fail("should have thrown ${T::class.java.name}, but returned `$result´")
}
lateinit var holder: T // (1)
scriptResult.ifError { throwable ->
if (throwable is T) {
holder = throwable // (2)
} else {
fail("expected ${T::class.java.name} to be thrown, but threw `$throwable´")
}
}
return holder // (3)
}
The assertion helper is effective. I can use it like so:
val thrown = execution.shouldHaveThrown<MissingMethodException>()
assertThat(thrown.message).contains("missedMethod")
But I suspect there is a more idiomatic way to return throwable from shouldHaveThrown, then to (1) declaring a holder, (2) assigning it and (3) eventually returning it. How?

Related

kotlin dagger "'<any>' could not be resolved"

I have working java code
public class ItemCallback<T extends Identifiable<?>> extends DiffUtil.ItemCallback<T> {
#Inject
public ItemCallback() {}
#Override
public boolean areItemsTheSame(#NonNull T oldItem, #NonNull T newItem) {
return oldItem.getId().equals(newItem.getId());
}
#Override
public boolean areContentsTheSame(#NonNull T oldItem, #NonNull T newItem) {
return oldItem.compareContent(newItem);
}
}
and i wrote correspond kotlin code
class ItemCallback<T : ListElementModel<*>> #Inject constructor() : DiffUtil.ItemCallback<T>() {
override fun areItemsTheSame(oldItem: T, newItem: T): Boolean {
return oldItem.id == newItem.id
}
override fun areContentsTheSame(oldItem: T, newItem: T): Boolean {
return oldItem == newItem
}
}
and caught error
"error: InjectProcessingStep was unable to process 'ItemCallback()' because 'any' could not be resolved."
I understand that the error in star-projections. But I don't know how to solve it.

AOP implementation of return value decryption

demand:Decryption of database query results with AOP
MybatisPlus Return results,for example:List
I customize an annotation to intercept annotated methods,
But I intercepted the method and got that the return type is List,How can I get the VO type in the list
#Component
#Aspect
#Order
public class DecryptrResultAspect {
#Pointcut("#annotation(com.sgcc.hr.recruit.graduate.common.utils.NeedDncryptResult)")
public void rsaDecodeSecurityParameterAspect() {
}
#After("rsaDecodeSecurityParameterAspect()")
public void decode(JoinPoint joinPoint) {
try {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Class returnType = signature.getReturnType();
System.out.println(returnType);
// output interface java.util.List
} catch (Exception e) {
e.printStackTrace();
}
}
}

How to change this code to kotlin to view a pdf from firebase database

How can i change my java code to kotlin code to view a pdf from firebase database
public class javaclasActivity extends AppCompatActivity {
private TextView text1;
private PDFView pdfView;
private FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference mref = database.getReference("url");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pdf);
pdfView = (PDFView) findViewById(R.id.pdfView33);
text1 = (TextView) findViewById(R.id.text11);
mref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
String value = dataSnapshot.getValue(String.class);
text1.setText(value);
Toast.makeText(javaclasActivity.this, "updated", Toast.LENGTH_SHORT).show();
String url = text1.getText().toString();
new RetrivePdfStream().execute(url);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(javaclasActivity.this, "failed to load", Toast.LENGTH_SHORT).show();
}
});}
// i am facing a problen on this below code
class RetrivePdfStream extends AsyncTask<String, Void, InputStream> {
#Override
protected InputStream doInBackground(String... strings) {
InputStream inputStream = null;
try {
URL url = new URL(strings[0]);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
if (urlConnection.getResponseCode() == 200) {
inputStream = new BufferedInputStream(urlConnection.getInputStream());
}
} catch (IOException e) {
return null;
}
return inputStream;
}
#Override
protected void onPostExecute(InputStream inputStream) {
pdfView.fromStream(inputStream).load();
}
}
}
to this kotlin file
class pdfActivity : AppCompatActivity() {
lateinit var pdfview: PDFView
lateinit var text1 : TextView
var database:FirebaseDatabase=FirebaseDatabase.getInstance()
var mref :DatabaseReference=database.getReference("url")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_pdf)
pdfview=findViewById(R.id.pdfView33)
text1=findViewById(R.id.text11)
}
}
the main problem is this
class RetrivePdfStream <String, Void, InputStream> {
You might want to fix some of the formatting here.
Also, if I understood correctly, you want to migrate Java to Kotlin.
For the RetrivePdfStream in Kotlin, you aren't inheriting from AsyncTask.
Do this like so:
class RetrivePdfStream : AsyncTask<String, Void, InputStream>() { ... }

Retrofit error response handling

I am using retrofit 2.3.0 to consume API's in my app but a week ago I started receiving error message and existing code was not able to display error message in UI.
Previously, I was using errorBody.toString() then suddenly after few months I got error and then last week I tried with errorBody.string() but it dodn't work. Now today it's working.
I have attached screenshots of response from server and my error handling also. Here is my code to display error message.
private static void showToastForError(retrofit2.Response<Object> response, int requestType) {
if (response != null && response.errorBody() != null) {
try {
JSONObject jObjError = null;
try {
jObjError = new JSONObject(response.errorBody() != null ? response.errorBody().toString() : "");
Toast.makeText(Application.getAppContext(), jObjError.getString("message"), Toast.LENGTH_LONG).show();
} catch (JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
I think you should custom call adapter to handle error.
Here my custom adapter
public final class ErrorHandlingAdapter {
/**
* A callback which offers granular callbacks for various conditions.
*/
public interface MyCallback<T> {
/**
* Called for [200, 300) responses.
*/
void success(Response<T> response);
/**
* Called for 401 responses.
*/
void unauthenticated(Response<?> response);
/**
* Called for [400, 500) responses, except 401.
*/
void clientError(Response<?> response);
/**
* Called for [500, 600) response.
*/
void serverError(Response<?> response);
/**
* Called for network errors while making the call.
*/
void networkError(IOException e);
/**
* Called for unexpected errors while making the call.
*/
void unexpectedError(Throwable t);
}
public interface MyCall<T> {
void cancel();
void enqueue(MyCallback<T> callback);
MyCall<T> clone();
boolean isExcute();
}
public static class ErrorHandlingCallAdapterFactory extends CallAdapter.Factory {
#Override
public CallAdapter<?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit) {
if (getRawType(returnType) != MyCall.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalStateException(
"MyCall must have generic type (e.g., MyCall<ResponseBody>)");
}
Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);
Executor callbackExecutor = retrofit.callbackExecutor();
return new ErrorHandlingCallAdapter<>(responseType, callbackExecutor);
}
private static final class ErrorHandlingCallAdapter<R> implements CallAdapter<R> {
private final Type responseType;
private final Executor callbackExecutor;
ErrorHandlingCallAdapter(Type responseType, Executor callbackExecutor) {
this.responseType = responseType;
this.callbackExecutor = callbackExecutor;
}
#Override
public Type responseType() {
return responseType;
}
#Override
public <R1> R adapt(Call<R1> call) {
return (R) new MyCallAdapter(call, callbackExecutor);
}
}
}
/**
* Adapts a {#link Call} to {#link MyCall}.
*/
static class MyCallAdapter<T> implements MyCall<T> {
private final Call<T> call;
private final Executor callbackExecutor;
MyCallAdapter(Call<T> call, Executor callbackExecutor) {
this.call = call;
this.callbackExecutor = callbackExecutor;
}
#Override
public void cancel() {
call.cancel();
}
#Override
public void enqueue(final MyCallback<T> callback) {
call.enqueue(new Callback<T>() {
#Override
public void onResponse(Call<T> call, Response<T> response) {
// on that executor by submitting a Runnable. This is left as an exercise for the reader.
callbackExecutor.execute(new Runnable() {
#Override
public void run() {
int code = response.code();
if (code >= 200 && code < 300) {
callback.success(response);
} else if (code == 401) {
if (Storage.getInstance().isLogin())
Storage.getInstance().logout(App.self().getApplicationContext());
} else if (code >= 400 && code < 500) {
callback.clientError(response);
} else if (code >= 500 && code < 600) {
callback.serverError(response);
} else {
callback.unexpectedError(new RuntimeException("Unexpected response " + response));
}
}
});
}
#Override
public void onFailure(Call<T> call, Throwable t) {
// on that executor by submitting a Runnable. This is left as an exercise for the reader.
callbackExecutor.execute(new Runnable() {
#Override
public void run() {
if (t instanceof IOException) {
if (call.isCanceled()) {
return;
}
callback.networkError((IOException) t);
Toast.makeText(App.self(), R.string.error_no_connect_internet, Toast.LENGTH_SHORT).show();
} else {
callback.unexpectedError(t);
}
}
});
}
});
}
#Override
public MyCall<T> clone() {
return new MyCallAdapter<>(call.clone(), callbackExecutor);
}
#Override
public boolean isExcute() {
return call.isExecuted();
}
}
}
Here my config to add custom call adapter
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addCallAdapterFactory(new ErrorHandlingAdapter.ErrorHandlingCallAdapterFactory()) // custom call adapter
.addConverterFactory(GsonConverterFactory.create())
.client(getHeader())
.build();
And handle request, ex:
#GET("api/getSomething")
ErrorHandlingAdapter.MyCall<BaseResponse> getSomething(#Query("param"),...)
Handle response:
ErrorHandlingAdapter.MyCall<BaseResponse> mCalls = ApiUtils.getSomething(...);
mCalls.enqueue(new ErrorHandlingAdapter.MyCallback<BaseResponse>() {
#Override
public void success(Response<BaseResponse> response) {
//handle response
}
#Override
public void unauthenticated(Response<?> response) {
//handle unauthenticated error
}
#Override
public void clientError(Response<?> response) {
//handle clientError error
}
#Override
public void serverError(Response<?> response) {
//handle serverError error
}
#Override
public void networkError(IOException e) {
//handle networkError error
}
#Override
public void unexpectedError(Throwable t) {
//handle unexpectedError error
}
}

getInstance() Unresolved Kotlin

Showing getInstance() unresolved reference when ever call.
class GlobalHolder {
private var pickerManager: PickerManager? = null
private val ourInstance = GlobalHolder()
fun getInstance() {
return ourInstance
}
private fun GlobalHolder(){}
fun getPickerManager(): PickerManager? {
return pickerManager
}
fun setPickerManager(pickerManager: PickerManager) {
this.pickerManager = pickerManager
}
}
Call
lateinit var pickerManager: PickerManager
pickerManager=GlobalHolder.getInstance().getPickerManager()
FYI
This is original Java class
public class GlobalHolder {
private PickerManager pickerManager;
private static GlobalHolder ourInstance = new GlobalHolder();
public static GlobalHolder getInstance() {
return ourInstance;
}
private GlobalHolder() {
}
public PickerManager getPickerManager() {
return pickerManager;
}
public void setPickerManager(PickerManager pickerManager) {
this.pickerManager = pickerManager;
}
}
You're willing to have a singleton, right? Make GlobalHolder an object, which will automatically provide a singleton:
object GlobalHolder {
private var pickerManager: PickerManager? = null
fun getPickerManager(): PickerManager? {
return pickerManager
}
fun setPickerManager(pickerManager: PickerManager) {
this.pickerManager = pickerManager
}
}
And then your instance like this:
GlobalHolder.getPickerManager()