I am developing application which having Parse Platform. To fetch data I am calling ParseCloud.callFunctionInBackground function.
I have registered the Parse and its sub class into the Application class like below :
public class App extends Application {
#Override
public void onCreate(){
super.onCreate();
Parse.setLogLevel(Parse.LOG_LEVEL_VERBOSE);
OkHttpClient.Builder builder = new OkHttpClient.Builder();
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.networkInterceptors().add(httpLoggingInterceptor);
ParseObject.registerSubclass(ParseMessage.class);
Parse.initialize(new Parse.Configuration.Builder(this)
.applicationId("KEY")
.server("URL")
.build());
}
}
I have below model class which extends ParseObject :
#ParseClassName("ParseMessage")
public class ParseMessage extends ParseObject {
// Ensure that your subclass has a public default constructor
public ParseMessage() {
super();
}
public ParsePhoto getPhotos() {
return (ParsePhoto) getParseObject("photos");
}
public void setPhotos(ParsePhoto value) {
put("photos", value);
}
public String getCaption() {
return getString("caption");
}
public void setCaption(String value) {
put("caption", value);
}
}
When I calling this below method from my Fragment :
HashMap<String, Object> params = new HashMap<String, Object>();
ParseCloud.callFunctionInBackground("MY_METHOD", params, new FunctionCallback<ArrayList<ParseMessage>>() {
public void done(ArrayList<ParseMessage> mapObject, ParseException e) {
if (e == null) {
ParseMessage object = mapObject.get(i);
}
} else {
}
}
});
But I am getting below exception :
java.lang.ClassCastException: com.parse.ParseObject cannot be cast to
com.example.ParseMessage
I already searched lots of thins from Google and Stackoverflow, but I did not get any solutions of it. Can anyone help me into this as I already spend a lot of time on this. Below response which I am getting from Parse :
The info you have provided is not very concrete, but from the debugger screen, it looks like you are trying to convert ParsePhoto into ParseMessage. ParsePhoto is subclass of ParseObject, and I believe this is causing the issue.
Related
My question is about the possibility to use RxJava for Android to manipulate data from a Retrofit call.
I've just started to use these libraries, so if my questions are trivial, please be patient.
This is my scenario.
I have a json returned from the server that looks like this
{ <--- ObjectResponse
higher_level: {
data: [
{
...
some fields,
some inner object: {
....
},
other fields
}, <----- obj 1
....,
{
....
}<---- obj n
]<-- array of SingleObjects
}
} <--- whole ObjectResponse
I've already have retrofit get this response and parsed in a ObjectResponse. Parsing this object, I can obtain a List that I can pass as usual to my RecyclerView Adapter.
So retrofit returned the ObjectResponse which is the model for the entire server answer, and in the retrofit callback I manipulate ObjectResponse to extract my List to be then passed to my adapter.
Right now, I have something like this
Call<ObjectResponse> call = apiInterface.getMyWholeObject();
call.enqueue(new Callback<ObjectResponse>() {
#Override
public void onResponse(Call<ObjectResponse> call, Response<ObjectResponse> response) {
//various manipulation based on response.body() that in the ends
// lead to a List<SingleObject>
mView.sendToAdapter(listSingleObject)
}
#Override
public void onFailure(Call<ObjectResponse> call,
Throwable t) {
t.printStackTrace();
}
});
My question is:
Is there a way to obtain from retrofit an Observable that can ultimate lead me to emit the list of SingleObject (and manipulate it) without have to manipulate ObjectResponse as I would do in the retrofit callback? Or should I have to stick with the retrofit callback and only after obatin List I can manipulate with RxJava just before feed this list to my Adapter?
I'd like to obtain something like this
apiInterface
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<SingleObject>>() {
#Override
public void onCompleted() {
}
#Override
public void onError(Throwable e) {
}
#Override
public void onNext(List<Post> posts) {
mView.sendToAdapter(listSingleObject)
}
});
Retrofit converter factories solve that issue very nicely.
Jake Wharton talks about "envelope" objects in his "Making Retrofit Work For You" talk and points out how that can be solved.
Having defined an envelope class - a class with some extra fields that you do not care about:
public class Envelope<T> {
Meta meta;
List<Notification> notifications;
T response;
}
In this POJO fields meta and List<Notification> are being returned from the backend, but in the context of android app they are not interesting to us. Assume, that the real value that you need from the response is field named response, which might be any object (because it's generic).
Particularly in your example the POJO structure would be like this:
public class OriginalResponse {
HigherLevel higher_level;
}
public class HigherLevel {
Data data;
}
public class Data {
List<ActualData> list;
}
You have to implement your custom Converter.Factory:
public class EnvelopingConverter extends Converter.Factory {
#Nullable
#Override
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
Type envelopedType = TypeToken.getParameterized(Envelope.class, type).getType();
Converter<ResponseBody, Envelope<?>> delegate = retrofit.nextResponseBodyConverter(this, envelopedType, annotations);
return body -> {
Envelope<?> envelope = delegate.convert(body);
// Here return the object that you actually are interested
// in your example it would be:
// originalResponse = delegate.convert(body);
// return originalResponse.higher_level.data.list;
return envelope.response;
};
}
}
Add this converter to your retrofit builder:
new Retrofit.Builder()
...
.addConverterFactory(new EnvelopingConverter())
...
Then in your retrofit api interface instead of returning Single<OriginalResponse> return Single<List<ActualData>> directly:
interface Service {
#GET(...)
Single<List<ActualData>> getFoo();
}
Typical implementation in Kotlin:
class EnvelopeConverterFactory : Converter.Factory() {
override fun responseBodyConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<ResponseBody, *>? {
val envelopedType: Type = TypeToken.getParameterized(ParentObject::class.java, type).type
val delegate: Converter<ResponseBody, ParentObject> =
retrofit.nextResponseBodyConverter(this, envelopedType, annotations)
return Converter<ResponseBody, ChildObject> { body -> delegate.convert(body)?.childObject }
}
}
As far as I know, there's no way to do it. For best practice, you should create a Facade layer (maybe an ApiManager class) to manage all your APIs. In that case, you can use map/flatMap to map your ObjectResponse to SingleObject like:
public Observable<List<SingleObject>> getSingleObjects(){
return ServiceGenerator.getApiMethods().getObjectResponse.map(new Function<ObjectResponse, List<SingleObject>>() {
#Override
public List<SingleObject> apply(ObjectResponse response) throws Exception {
return reponse.getListSingleObjects();
}
})
}
After some days, I can post my own solution.
It is inspired by the idea suggested by azizbekian.
The center idea is on the Envelope class, which I've express using retrofit annotation to be sure it would adapt to different JSON response from server, parsing the
higher_level: {
data: [
mid_level: { .. },
...
]
}
structure that I've already explained in my original post
public class WrapperResponse<T> {
#SerializedName(value="higher_level", alternate={"mid_level", "other"})
#Expose
DataResponse<T> data;
public DataResponse<T> getData() {
return data;
}
public void setData(DataResponse<T> data) {
this.data = data;
}
}
The focus here is in the parameters of SerializedName, where I specify all the possible JSON objects name that appear in my server response.
Then I have
public class UnwrapConverterFactory extends Converter.Factory {
private GsonConverterFactory factory;
public UnwrapConverterFactory(GsonConverterFactory factory) {
this.factory = factory;
}
#Override
public Converter<ResponseBody, ?> responseBodyConverter(final Type type,
Annotation[] annotations, Retrofit retrofit) {
Type wrappedType = new ParameterizedType() {
#Override
public Type[] getActualTypeArguments() {
return new Type[] {type};
}
#Override
public Type getOwnerType() {
return null;
}
#Override
public Type getRawType() {
return WrapperResponse.class;
}
};
Converter<ResponseBody, ?> gsonConverter = factory
.responseBodyConverter(wrappedType, annotations, retrofit);
return new WrapperResponseBodyConverter(gsonConverter);
}
}
and
public class WrapperResponseBodyConverter<T>
implements Converter<ResponseBody, T> {
private Converter<ResponseBody, WrapperResponse<T>> converter;
public WrapperResponseBodyConverter(Converter<ResponseBody,
WrapperResponse<T>> converter) {
this.converter = converter;
}
#Override
public T convert(ResponseBody value) throws IOException {
WrapperResponse<T> response = converter.convert(value);
return response.getData().getData();
}
}
Used in my Retrofit Module (dagger2) to ensure that my Retrofit client unwrap any answer from server using the generic WrapperResponse and, in the end, I can write Retrofit method as
#GET("locations")
Observable<List<Location>> getLocation();
where List is exactly the result I wanted to obtain: a list of objects straight from Retrofit response, that I can further elaborate with RxJava.
Thanks all.
I want to interact with a RESTful webservice that responds only in JSON.
Any successful response from the server has this syntax:
{
"code": int code,
"data": object or list of objects
}
while on error response:
{
"code": int code,
"error": string,
"details": string
}
So I made two classes in my Android project like this (for GSON reflection):
public class ErrorEntity {
private String details;
private String error;
private int code;
public ErrorEntity() {
// Stub constructor
}
public String getDetails() {
return details;
}
public String getError() {
return error;
}
public int getCode() {
return code;
}
}
For a successful response I made a generic because I don't want to parse JSON data on overridden parseNetworkResponse:
public class SuccessfulEntity<T> {
private T data;
private int code;
public SuccessfulEntity() {
// Stub content
}
public T getData() {
return data;
}
public int getCode() {
return code;
}
}
Now, because my RESTful server requires some custom headers, I need to make a Request subclass, but I don't know from which class I need to inherit.
I saw this question: Send POST request with JSON data using Volley and though to do something like that.
Basically, I want to make a new class (VolleyRestClient) which has GET, POST, DELETE methods and API routings, and with this class make all requests I need to do.
Methods of this class need to make a new custom request and parse new objects response like SuccessfulEntity and ErrorEntity, and then parsing data in service/thread that make the VolleyRestClient call.
How can I do that?
After a long fight with generics and type erasure, I finally did it.
So I'm posting this for whoever has the same issue like me and needs a solution without freaking out.
My ErrorEntity and my SuccessfulEntity are still the same, but I created a new interface called RepositoryListener, like this:
public interface RepositoryListener {
public abstract void onErrorResponse(int code, String details);
public abstract void onSuccessfulResponse(int code, Object obj);
public abstract void onSuccessfulResponse2(int code, List<Object> obj);
}
Then I made a class, VolleyRestClient, like this:
public class VolleyRestClient extends RestClient {
private final DefaultRetryPolicy mRetryPolicy;
private final RequestQueue mQueue;
private final Gson gson = new Gson();
public VolleyRestClient(Context context) {
// Default retry policy
mRetryPolicy = new DefaultRetryPolicy(2000, 3, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
mQueue = Volley.newRequestQueue(context);
}
public RequestQueue getQueue() {
// Method to push requests for image download
return mQueue;
}
#Override
public void GET(boolean obj, boolean needAuth, String url, Type type,
RepositoryListener listener) {
// Choose which listener to construct
Response.Listener<myResponse> mListener = obj ?
// This uses objects
makeSuccessfulListener(listener, type) :
// This uses list of objects
makeSuccessfulListener2(listener, type);
myRequest mRequest =
new myRequest(Request.Method.GET, needAuth, url,
mListener, makeErrorListener(listener));
mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}
#Override
public void POST(boolean needAuth, String url, String body, Type type, RepositoryListener listener) {
myRequest mRequest = new myRequest(Request.Method.POST, needAuth, url, body,
makeSuccessfulListener(listener, type), makeErrorListener(listener));
mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}
#Override
public void DELETE(boolean needAuth, String url, Type type, RepositoryListener listener) {
myRequest mRequest =
new myRequest(Request.Method.DELETE, needAuth, url,
makeSuccessfulListener(listener, type), makeErrorListener(listener));
mRequest.setRetryPolicy(mRetryPolicy);
mQueue.add(mRequest);
}
private Response.Listener<myRequest> makeSuccessfulListener
(final RepositoryListener listener, final Type type) {
// TODO: test this method and implement lists
if (listener == null) {
return null;
} else {
return new Response.Listener<myRequest>() {
#Override
public void onResponse(myRequest response) {
SuccessfulEntity<Object> obj = gson.fromJson(response.getBody(), type);
listener.onSuccessfulResponse(response.getCode(), obj.getData());
}
};
}
}
private Response.Listener<myRequest> makeSuccessfulListener2
(final RepositoryListener listener, final Type type) {
// TODO: test lists
if (listener == null) {
return null;
} else {
return new Response.Listener<myRequest>() {
#Override
public void onResponse(myReqyest response) {
SuccessfulEntity<List<Object>> obj = gson.fromJson(response.getBody(), type);
listener.onSuccessfulResponse2(response.getCode(), obj.getData());
}
};
}
}
private Response.ErrorListener makeErrorListener(final RepositoryListener listener) {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try {
String jError = new String(error.networkResponse.data);
ErrorEntity mError = gson.fromJson(jError, ErrorEntity.class);
// Invoke listener closure
listener.onErrorResponse(error.networkResponse.statusCode, mError.getDetails());
} catch (Exception e) {
listener.onErrorResponse(404, e.getMessage());
}
}
};
}
}
This is very dependant by my needs, but I'll explain the general concept.
So I have a custom request, as explained in my question, and I want to parse it to the correct data type.
To be more specific, I could have a JSONArray data only on GET requests (paginated elements, etc...) so I need to find a way to distinguish between this two cases (of course, I know in which cases I'll get a List or an Object).
We cannot simply create POJO from Json within a generic class using its type (because Java Type Erasure), so we need object type upfront.
But what we can do is:
in our custom request, on parseNetworkResponse, do something like that:
#Override
protected Response<myResponse> parseNetworkResponse(NetworkResponse response) {
try {
// Using server charset
myResponse mResponse = new myResponse();
mResponse.setCode(response.statusCode);
mResponse.setBody(new String(response.data,
HttpHeaderParser.parseCharset(response.headers)));
// Return new response
return Response.success(mResponse, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
// Normally use 'utf-8'
return Response.error(new ParseError(e));
}
}
In other words, copy the raw string response body onto a new object myResponse;
Response body will be eventually parsed in VolleyRestClient with the appropriate type passed as a GET/DELETE/POST argument;
makeSuccessfulListener and makeSuccessfulListener2 construct a Response.Listener from a RepositoryListener, which has 3 methods to override: onSuccessfulResponse for objects data, onSuccessfulResponse2 for list of objects data, onErrorResponse for 4XX/5XX errors;
Our data object/list will be parsed to more generics type (List and Object) and then passed to our custom listener RepositoryListener.
A full example for this approach:
public void getNewLogin(String nickname, String password,
final TextView author, final TextView title, final TextView text) {
String json =
(new StringBuilder()
.append("{ \"nickname\": \"")
.append(nickname)
.append("\", \"password\": \"")
.append(password)
.append("\" }")).toString();
mRest.POST(false, "http://192.168.0.104:8000/api/session", json,
new TypeToken<SuccessfulEntity<Login>>(){}.getType(),
new RepositoryListener() {
#Override
public void onSuccessfulResponse2(int code, List<Object> obj) {
// Nothing happens here
}
#Override
public void onSuccessfulResponse(int code, Object obj) {
UserSession mInstance = UserSession.getInstance(null);
Login newLogin = (Login) obj;
title.setText(newLogin.getToken());
mInstance.setToken(newLogin.getToken());
Log.i("onSuccessfulResponse", mInstance.getToken());
Log.i("onSuccessfulResponse", mInstance.getmAuthorizationToken());
if (newLogin.getUser() != null) {
author.setText(newLogin.getUser().getNickname());
text.setText(newLogin.getUser().getUniversity());
}
}
#Override
public void onErrorResponse(int code, String error) {
Log.i("onErrorResponse", error);
}
});
mRest is a VolleyRestClient object, which performs a POST request to that address with Type constructed by Gson TypeToken (remember, our body is a SuccessfulEntity).
Since we'll have an Object data for sure, we'll just override onSuccessfulResponse, cast data object to the same type T of SuccessfulEntity used in TypeToken, and do our dirty work.
I don't know if I was clear, this approach works, if some of you needs some clarification, just ask :)
Server side, I construct a java.util.Hashmap, populate it with values (key and value are both String) and pass it back to the client via an async callback. It is empty when it gets back to the client side.
I can replicate this with a net new hashmap that is only used in one place server side. Java 6 and GWT 2.7
Server side service:
public class Service extends RemoteServiceServlet implements IService {
public Model buildModel() {
Model model = new Model();
model.addItemToMyMap("key", "value");
return model;
}
}
Model:
public class Model implements Serializable {
private Map<String, String> myMap = new HashMap<String, String>();
public void addItemToMyMap(String key, String value) {
if(key != null) {
myMap.put(key, value);
}
}
public Map<String, String> getMyMap() {
return myMap;
}
}
Async Interface:
public interface IServiceAsync {
public void buildModel(AsyncCallback<Model> callback); {
}
Client Side:
service.buildModel(new AsyncCallback<Model>() {
public void onSuccess(Model model) {
logger.warning(model.getMyMap().size());
}
public void onFailure(Throwable caught) {
logger.warning("ERROR!");
}
}
Problem solved. Eclipse save actions was making the map final and thus preventing serialization. When I removed the final modifier (and prevented Eclipse from adding it back), I was able to see the map's contents on the client side.
I have an android project in which I use a class to send http requests using the Volley library.
It is called WebServicesAdapter. I used a callback in it to return a value to the called activity but it prevents the new activity from starting because of some problems in the context.
How can I return a string without using a callback?
Below is my code. successcallback is the callback when I want to return a string instead.
public class WebServiceAdapter {
private static String BASE_URI = "http://192.168.42.94/getvoize/index.php";
private RequestQueue rQueue;
public String responseString;
public String status;
Context context;
public WebServiceAdapter(Context context){
this.context = context;
status = "new";
rQueue = Volley.newRequestQueue(context);
}
private WebServiceInterface wsi;
public void sendGetRequest(String page,Map<String,String> map, WebServiceInterface i){
wsi = i;
String query = "";
if(!map.isEmpty()){
for (Map.Entry<String, String> entry : map.entrySet())
{
query =query + entry.getKey()+"="+entry.getValue()+'&';
}
}
if(query.length() != 0)
query = query.substring(0,query.length()-1);
StringRequest sRequest = new StringRequest(Request.Method.GET,BASE_URI+page+"?"+query,
new Response.Listener<String>() {
#Override
public void onResponse(String response){
wsi.successCallback(response,context);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error){
wsi.errorCallback("failed",context);
}
});
rQueue.add(sRequest);
}
private Map<String,String> parameter;
private Map<String,String> headers;
public void sendPostRequest(String page,Map<String,String> body,Map<String,String> header,WebServiceInterface i){
wsi = i;
parameter = body;
headers = header;
Log.d("place", "Inpost");
StringRequest myReq = new StringRequest(Request.Method.POST,
BASE_URI+page,
new Response.Listener<String>() {
#Override
public void onResponse(String response){
wsi.successCallback(response, context);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error){
wsi.errorCallback("Failed", context);
}
}
) {
#Override
protected Map<String,String> getParams(){
Map<String,String> params = parameter;
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> params = headers;
return params;
}
};
rQueue.add(myReq);
}
You have not posted activity code where you are trying to start new activity. It would be helpful if you can share that piece here along with error logs if any.
In case you are trying to launch an activity from callback in the calling Activity, remember to do it in Main Thread (assuming the web servie is called from thread other than main thread).
Other input worth mentioning is - from your callback to activity, context is not required to be passed back. It would be readily available there in activity.
you can use below code:
runOnUiThread(new Runnable() {
public void run() {
//startActivity code here.
}
});
Define your callback interface (I assume you already have this and WebServiceInterface is the callback interface).
Your Activity should implement this interface.
Add a parameter WebServiceInterface to the WebServiceAdapter constructor. The constructor should store this in a private member variable.
When your Activity creates an instance of WebServiceAdapter, it should pass this as the WebServiceInterface parameter.
WHen you want to call back the Activity, just make your calls on the stored private member variable.
TLDR: I'd like to know how to extend fit.TypeAdaptor so that I can invoke a method that expects parameters as default implementation of TypeAdaptor invokes the binded (bound ?) method by reflection and assumes it's a no-param method...
Longer version -
I'm using fit to build a test harness for my system (a service that returns a sorted list of custom objects). In order to verify the system, I thought I'd use fit.RowFixture to assert attributes of the list items.
Since RowFixture expects the data to be either a public attribute or a public method, I thought of using a wrapper over my custom object (say InstanceWrapper) - I also tried to implement the suggestion given in this previous thread about formatting data in RowFixture.
The trouble is that my custom object has around 41 attributes and I'd like to provide testers with the option of choosing which attributes they want to verify in this RowFixture. Plus, unless I dynamically add fields/methods to my InstanceWrapper class, how will RowFixture invoke either of my getters since both expect the attribute name to be passed as a param (code copied below) ?
I extended RowFixture to bind on my method but I'm not sure how to extend TypeAdaptor so that it invokes with the attr name..
Any suggestions ?
public class InstanceWrapper {
private Instance instance;
private Map<String, Object> attrs;
public int index;
public InstanceWrapper() {
super();
}
public InstanceWrapper(Instance instance) {
this.instance = instance;
init(); // initialise map
}
private void init() {
attrs = new HashMap<String, Object>();
String attrName;
for (AttrDef attrDef : instance.getModelDef().getAttrDefs()) {
attrName = attrDef.getAttrName();
attrs.put(attrName, instance.getChildScalar(attrName));
}
}
public String getAttribute(String attr) {
return attrs.get(attr).toString();
}
public String description(String attribute) {
return instance.getChildScalar(attribute).toString();
}
}
public class MyDisplayRules extends fit.RowFixture {
#Override
public Object[] query() {
List<Instance> list = PHEFixture.hierarchyList;
return convertInstances(list);
}
private Object[] convertInstances(List<Instance> instances) {
Object[] objects = new Object[instances.size()];
InstanceWrapper wrapper;
int index = 0;
for (Instance instance : instances) {
wrapper = new InstanceWrapper(instance);
wrapper.index = index;
objects[index++] = wrapper;
}
return objects;
}
#Override
public Class getTargetClass() {
return InstanceWrapper.class;
}
#Override
public Object parse(String s, Class type) throws Exception {
return super.parse(s, type);
}
#Override
protected void bind(Parse heads) {
columnBindings = new TypeAdapter[heads.size()];
for (int i = 0; heads != null; i++, heads = heads.more) {
String name = heads.text();
String suffix = "()";
try {
if (name.equals("")) {
columnBindings[i] = null;
} else if (name.endsWith(suffix)) {
columnBindings[i] = bindMethod("description", name.substring(0, name.length()
- suffix.length()));
} else {
columnBindings[i] = bindField(name);
}
} catch (Exception e) {
exception(heads, e);
}
}
}
protected TypeAdapter bindMethod(String name, String attribute) throws Exception {
Class partypes[] = new Class[1];
partypes[0] = String.class;
return PHETypeAdaptor.on(this, getTargetClass().getMethod("getAttribute", partypes), attribute);
}
}
For what it's worth, here's how I eventually worked around the problem:
I created a custom TypeAdapter (extending TypeAdapter) with the additional public attribute (String) attrName. Also:
#Override
public Object invoke() throws IllegalAccessException, InvocationTargetException {
if ("getAttribute".equals(method.getName())) {
Object params[] = { attrName };
return method.invoke(target, params);
} else {
return super.invoke();
}
}
Then I extended fit.RowFixture and made the following overrides:
public getTargetClass() - to return my class reference
protected TypeAdapter bindField(String name) throws Exception - this is a protected method in ColumnFixture which I modified so that it would use my class's getter method:
#Override
protected TypeAdapter bindField(String name) throws Exception {
String fieldName = camel(name);
// for all attributes, use method getAttribute(String)
Class methodParams[] = new Class[1];
methodParams[0] = String.class;
TypeAdapter a = TypeAdapter.on(this, getTargetClass().getMethod("getAttribute", methodParams));
PHETypeAdapter pheAdapter = new PHETypeAdapter(fieldName);
pheAdapter.target = a.target;
pheAdapter.fixture = a.fixture;
pheAdapter.field = a.field;
pheAdapter.method = a.method;
pheAdapter.type = a.type;
return pheAdapter;
}
I know this is not a neat solution, but it was the best I could come up with. Maybe I'll get some better solutions here :-)