Hi i have 2 interfaces:
public interface SpendAction extends OpenGraphAction{
#PropertyName("namespace:transport") // I tried #PropertyName("transport") or without property
public void setTransport(OGObject object);
public OGObject getTransport();
}
And
public interface OGObject extends OpenGraphObject{
#PropertyName("namespace:hours")
public void setHours(int hours);
#PropertyName("namespace:minutes")
public void setMinutes(int minutes);
#PropertyName("namespace:seconds")
public void setSeconds(int seconds);
public int getHours();
public int getMinutes();
public int getSeconds();
public void setUrl(String url);
public String getUrl();
public void setTitle(String title);
public String getTitle();
public void setDescription(String message);
public String getDescription();
}
1st is an OpenGraphAction and 2nd one is object. I'm creating interfaces this way:
SpendAction action = GraphObject.Factory.create(SpendAction.class);
OGObject object = GraphObject.Factory.create(OGObject.class);
Then I'm setting object after filling it with data, url, title description etc.
action.setTransport(object);
// I've tried to replace this with action.addProperty("transport", object) and action.addProperty("namespace:transport", object")
//also action.setType("transport") and action.setType("namespace:transport)
action.setExplicitlyShared(true);
Facebook request creation:
Request request = new Request(
Session.getActiveSession(),
"me/namespace:spent",
null,
HttpMethod.POST,
new Request.Callback() {
#Override
public void onCompleted(Response response) {
if(response != null && response.getError() != null) Log.d("Facebook Share", "Error message:" + response.getError().getErrorCode() + ", " + response.getError().getErrorMessage());
if(response != null && response.getGraphObject() != null){
Toast.makeText(context, "Success!", Toast.LENGTH_SHORT).show();
}
}
}
);
request.setGraphObject(action);
request.executeAsync();
And I'm getting following error:
Error message:1611072, The action you're trying to publish is invalid because it does not specify any reference objects. At least one of the following properties must be specified: tv, transport, friends, studying, reading, shopping, cooking, cleaning, work, internet, personal_care, sport, sleeping, social_media, childcare, petcare, loo, games, sex, fun, hangover, smoking, eating.
I've already tried to set type for action, messed around with propertyname and nothing worked.
On facebook I have my story and there I have my custom object with some custom fields (hours, minutes, seconds).
Sharing custom story is working for me when I'm creating json object (String). But not with these interfaces.
Related
I am having a strange crash/error that happened without changing anything.
I am using Volley for network requests and i have a separate class with my URL end points.
I am using MY_REQUEST_URL + myparam=%s as the link and in the volley request i am using String.format(EndPoints.MY_REQUEST_URL, myparameter) and when I run this request in my app, it crashes (see the log below).
What is even stranger is that i am using the same type of requests in the same app and they all work fine except this and another one.
MyClass code:
public class MyClass extends Fragment{
// other declarations
ArrayList<JSONObject> data;
View view
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_myclass, null);
// initializing lots of views
data = new ArrayList<JSONObject>();
String userid = Utils.getStringFromPreferences(getActivity(), Utils.VAR_USERID); // this is a custom method of getting from shared preferences, it is static in my custom Utils class
getData(userid);
return view;
}
//different methods
//getData Method
private void getData(String userid) {
String url = String.format(EndPoints.URL_MY_REQUEST_URL, userid);
Log.d("request url debug", url);
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Result handling
Log.e("data", response);
if (!response.equals("") || response != null) {
try {
// response handling
} catch (JSONException e) {
// e.printStackTrace();
}
} else {
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("Something went wrong!");
error.printStackTrace();
}
});
stringRequest.setRetryPolicy(new DefaultRetryPolicy(
10000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
// Add the request to the queue - i have a custom class for this, used in every network request that works fine
VolleyRequestQue.getInstance(InsuitBusiness.getContext()).addToRequestQueue(stringRequest);
}
}
This is the Endpoints class:
public class Endpoints {
public static String MY_MAIN_URL = "https://www.myweb.com/"
public static String MY_REQUEST_URL = MY_MAIN_URL + "scripts/getData.php?userid=%s"
// the rest of the class is all the same like stringname = MY_MAIN_URL + "phpscript.php?parameter=%s"
}
This is the error log:
Caused by: java.util.MissingFormatArgumentException: Format specifier '%s'
at java.util.Formatter.format(Formatter.java:2490)
at java.util.Formatter.format(Formatter.java:2426)
at java.lang.String.format(String.java:2626)
at com.myapp.myapp.MyClass.getData(MyClass.java:1220)
at com.myapp.myapp.MyClass$getDataAsync.doInBackground(MyClass.java:1208)
at com.myapp.myapp.MyClass$getDataAsync.doInBackground(MyClass.java:1204)
at android.os.AsyncTask$2.call(AsyncTask.java:304)
MY_MAIN_URL which was supposed to have as value: "https://www.myweb.com/" i was mistakenly giving another value which contained "%s" and this is how i got the exception and the crash.
For future people having the same problem just make sure there aren't more "%s" in the link, Log the link in the debugger and see how it shows up.
Thanks to everyone for their time.
I'm working on a simple translation app as part of a university project. For the translation process, I query MyMemory's Translate API using Retrofit and I retrieve the translated output as a String. This is working fine for the most part, but it's causing some issues in other areas of my program.
When I make a call to retrieve a translation from the library, subsequent methods begin to run before the translation is fully recieved - this then prevents those methods from working fully since they rely on the received translation.
Here are some relevant snippets of my code that might explain the question better:
TranslateAPI: (Interface that i use to retrieve a translation)
public class TranslateAPI {
private static final String ENDPOINT = "http://api.mymemory.translated.net";
public final static String FRENCH = "FR";
public final static String ENGLISH = "EN";
public final static String ITALIAN = "IT";
public final static String GREEK = "EL";
public final static String SPANISH = "ES";
private final TranslateService mService;
String translation = "";
public interface TranslateService {
#GET("/get")
Call<TranslatedData> getTranslation(
#Query("q") String textToTranslate,
#Query(value = "langpair", encoded = true)
String languagePair);
}
public TranslateAPI() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.build();
mService = retrofit.create(TranslateService.class);
}
public String translate(final String textToTranslate, final String fromLanguage, final String toLanguage) {
mService.getTranslation(textToTranslate, URLEncoder.encode(fromLanguage + "|" + toLanguage))
.enqueue(new Callback<TranslatedData>() {
#Override
public void onResponse(Response<TranslatedData> response, Retrofit retrofit) {
String output =
String.format(response.body().responseData.translatedText);
String.format("Translation of: %s, %s->%s = %s", textToTranslate,
fromLanguage, toLanguage, response.body().responseData.translatedText);
System.out.println("Result: " + output);
translation = output;
System.out.println("The result of the field translation is: " + translation);
}
#Override
public void onFailure(Throwable t) {
System.out.println("[DEBUG]" + " RestApi onFailure - " + "");
}
});
return translation;
}
}
In the code above, the translate(final String textToTranslate, final String fromLanguage, final String toLanguage) method successfully returns the translated output as a string.
Now, to demonstrate exactly what goes wrong, assume the following code snippet for my main activity:
private void runChatBot() {
translateOutput(input, targetLanguage); //calls the translate method of the TranslateAPI class
System.out.println("translatedOutput value in MainActivity: " + translatedOutput);
//Use translated output here
}
What happens here is that the print statement in runChatbot() executes before the call to the translation API. This is not the desired behaviour, as I would like the translateOutput() method to execute fully before any following instructions.
Any help is much appreciated. Thanks in advance :)
UPDATE: Current code after initial answers
TranslateAPI - Declarations
public interface Callbacks {
void onTranslationReceived(String result);
void onTranslationFailed();
}
TranslateAPI - translate()
public void translate(final String textToTranslate, final String fromLanguage, final String toLanguage) {
mService.getTranslation(textToTranslate, URLEncoder.encode(fromLanguage + "|" + toLanguage))
.enqueue(new Callback<TranslatedData>() {
#Override
public void onResponse(Response<TranslatedData> response, Retrofit retrofit) {
String output =
String.format(response.body().responseData.translatedText);
String.format("Translation of: %s, %s->%s = %s", textToTranslate,
fromLanguage, toLanguage, response.body().responseData.translatedText);
System.out.println("Result: " + output);
translation = output;
System.out.println("The result of the field translation is: " + translation);
}
#Override
public void onFailure(Throwable t) {
System.out.println("[DEBUG]" + " RestApi onFailure - " + "");
}
});
}
MainActivity:
#Override
public void onTranslationReceived(String result) {
runChatBot();
}
#Override
public void onTranslationFailed() {
//Handle failure here
}
public void runChatBot() {
translatedOutput = translateAPI.getTranslation();
System.out.println("translatedOutput value in MainActivity: " + translatedOutput);
userOutputView.setText(translatedOutput);
ttsResponse(translatedOutput, TTSLanguage);
setVisualCue(chatBot.getVisualMatch());
chatBot.clearResults();
}
Since your translate() method is asynchronous, you should define a callback in TranslateAPI to send the result back to your Activity when the result is received. By doing this, you would then only perform work on the translation result once you know you've received a response from TranslateAPI.
So in TranslateAPI you would define a callback interface:
public interface Callbacks {
void onTranslationReceived(String result);
}
Then you would have your Activity implement TranslateAPI.Callbacks and implement the callback like this:
public void onTranslationReceived(String result) {
//do something with the result
runChatBot(result); //or something similar
}
Then, once you receive the response in the callback, you do whatever it is you have to do with the translation result. This way, you know you will never be executing anything on the translated result until the translation is complete.
EDIT IN RESPONSE TO COMMENTS
So in order to actually send the response to your Activity once the translate response is received, you need to pass a reference to your Activity into TranslateAPI. Since your Activity implements the callbacks, you can simply pass this in: TranslateAPI translateApi = new TranslateAPI(this);
Then in your TranslateAPI, you'll need to take this reference and use it as the "listener" of your callbacks. So in TranslateAPI you'll want to define a variable like this private Callbacks listener; and you'll assign this in your TranslateAPI constructor the value that's passed in from the Activity. So your TranslateAPI constructor might look like this:
public TranslateAPI(Callbacks listener) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.build();
mService = retrofit.create(TranslateService.class);
//this is the line you would add...
this.listener = listener;
}
And then in your onResponse() callback in TranslateAPI, you simply pass the value to the listener, which passes it back to the implemented method in your Activity. Like this:
#Override
public void onResponse(Response<TranslatedData> response, Retrofit retrofit) {
String output = String.format(response.body().responseData.translatedText);
String.format("Translation of: %s, %s->%s = %s", textToTranslate, fromLanguage, toLanguage, response.body().responseData.translatedText);
System.out.println("Result: " + output);
translation = output;
System.out.println("The result of the field translation is: " + translation);
//this is the line you would add...
listener.onTranslateReceived(translation);
}
Hope this helps clarify things. Let me know if you have any more questions!
this happens because code is executed asynchronous. Your retrofit network request takes some time to complete, so by default, java will execute the next line of code before it concludes. To solve this you must use the retrofit callback onResponse and onFailure.
I sugest you to create a new interface and pass it on constructor os method of your TranslateApiCode. Something like:
public interface OnTranslate {
void onSuccess(); // here you can pass any object you need later
void onError(); // here you can pass any object you need later
}
public String translate(final String textToTranslate, final String fromLanguage, final String toLanguage) {
mService.getTranslation(textToTranslate, URLEncoder.encode(fromLanguage + "|" + toLanguage))
.enqueue(new Callback<TranslatedData>() {
#Override
public void onResponse(Response<TranslatedData> response, Retrofit retrofit) {
String output =
String.format(response.body().responseData.translatedText);
String.format("Translation of: %s, %s->%s = %s", textToTranslate,
fromLanguage, toLanguage, response.body().responseData.translatedText);
System.out.println("Result: " + output);
translation = output;
System.out.println("The result of the field translation is: " + translation);
myOnTranslateVariable.onSuccess();
}
#Override
public void onFailure(Throwable t) {
System.out.println("[DEBUG]" + " RestApi onFailure - " + "");
myOnTranslateVariable.onError();
}
});
return translation;
}
private void runChatBot() {
translateOutput(input, targetLanguage, new OnTranslate() {
void onSucess() {
System.out.println("translatedOutput value in MainActivity: " + translatedOutput);
}
void onError() {
System.out.println("some error happened");
}
}); //calls the translate method of the TranslateAPI class
//Use translated output here
}
Try Using Handler to notify when translation is completed and then perform the required operations. Thanks
My ContentObserver for observing the history in the browser is not being called. I don't understand why it isn't. I'm not doing anything different or bizarre, I'm following the API specs exactly, but to no avail! Below is my code:
In my service:
public class MonitorService extends Service {
//some global variables declared here
private ContentObserver historyObserver, searchObserver, chromeObserver;
public void onCreate() {
super.onCreate();
isRunning = false;
this.preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
//this.historyObserver = new HistoryObserver();
this.historyObserver = new HistoryObserver(new Handler());
this.searchObserver = new HistoryObserver(new Handler());
this.chromeObserver = new HistoryObserver(new Handler());
getApplicationContext().getContentResolver().registerContentObserver(Uri.parse("content://com.android.chrome.browser/history"), false, this.chromeObserver);
getApplicationContext().getContentResolver().registerContentObserver(android.provider.Browser.BOOKMARKS_URI, false, this.historyObserver);
getApplicationContext().getContentResolver().registerContentObserver(android.provider.Browser.SEARCHES_URI, false, this.searchObserver);
}
//Other required methods in class
}//end of class
Then in my HistoryObserver Class we have:
public class HistoryObserver extends ContentObserver {
public final String TAG = "HistoryObserver";
public HistoryObserver(Handler handler) {
super(handler);
Log.d(TAG, "Creating new HistoryObserver");
}
public HistoryObserver() {
super(null);
Log.d(TAG, "Creating a new HistoryObserver without a Handler");
}
#Override
public boolean deliverSelfNotifications() {
Log.d(TAG, "delivering self notifications");
return true;
}
#Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Log.d(TAG, "onChange without uri: " + selfChange);
//onChange(selfChange, null);
}
public void onChange(boolean selfChange, Uri uri) {
super.onChange(selfChange, uri);
Log.d(TAG, "onChange: " + selfChange + "\t " + uri.toString());
}
}
Like I said there is nothing special or unique about this implementation. Yet, when I go go to a new website or search for something in Chrome, the onChange method is never fired.
I figured out the problem. The /history content provider isn't an observable. The observables come through the /bookmark uri. Once I discovered that, things got working very quickly and very well.
I'm trying to implement search autocompletion with android-query library
I have callback instance in my activity:
Callback:
class SearchCompleteCallback extends AjaxCallback<ItemSearchResult> {
public void callback(String url, ItemSearchResult searchResult, AjaxStatus status) {
Log.d("SCB", String.format("Url:%s\n Msg: %s\n Code: %s\n Error: %s",
url,
status.getMessage(),
status.getCode(),
status.getError()));
if (searchResult != null) {
Log.d("SCB", String.format("Status: %s\n Val: %s",
searchResult.getStatus(),
searchResult.getInnGroup().getItems()));
updateSearchResult(searchResult);
}
else {
Log.w("SCB", "Ajax failed");
}
}
}
Search routine, that called on text change:
private void doSearch(String query) {
ppApi.getSearchResult(query, searchCompleteListener);
}
and
APIClass
public class PPServerApi {
private AQuery aq;
private GsonTransformer transformer;
private static class GsonTransformer implements Transformer{
public <T> T transform(String url, Class<T> type, String encoding, byte[] data, AjaxStatus status) {
Gson g = new Gson();
return g.fromJson(new String(data), type);
}
}
public PPServerApi(AQuery newAq){
aq = newAq;
transformer = new GsonTransformer();
AQUtility.setDebug(true);
AjaxCallback.setTransformer(transformer);
}
public void getSearchResult(String itemName, AjaxCallback<ItemSearchResult> cb){
String url = "http://my.api.server/search?q=" + itemName;
aq.ajax(url, ItemSearchResult.class, cb.header("content-type", "application/json"));
}
}
So, the question is how to abort old queries before sending new one ?
(I don't need result of old queries if text in search field changed)
I've tried to call searchCompleteListener.abort() in doSearch(), but it causes exception in next going query:
08-09 20:59:10.551: W/AQuery(6854): get:http://my.api.server/search?q=abc
08-09 20:59:10.551: W/AQuery(6854): creating http client
08-09 20:59:10.561: W/AQuery(6854): java.io.IOException: Aborted
08-09 20:59:10.561: W/AQuery(6854): at com.androidquery.callback.AbstractAjaxCallback.httpDo(AbstractAjaxCallback.java:1569)
...
so, i can't perform even single query in this case.
There is no way of making android-query cancel an AJAX request once it has been started.
You'll have to use another library, sorry.
What you can do is to check if the request has become obsolete when it finishes.
You could do that by checking if the URL matches the latest URL you requested for
if (searchResult != null && url.equals(latestRequestUrl)) {
(note, you'd have to let getSearchResult return the URL)
You can use the droidQuery library instead. Using droidQuery, you can cancel all Ajax tasks using the call:
$.ajaxKillAll();
You can also perform your request with this:
$.ajax(new AjaxOptions().url(url).header("content-type", "application/json").type("json").dataType("GET").dataType("json").success(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
JSONObject json = (JSONObject) params[0];
//TODO handle json
}
}).error(new Function() {
#Override
public void invoke($ droidQuery, Object... params) {
AjaxError error = (AjaxError) params[0];
Log.e("Ajax", "Error " + error.status + ": " + error.reason);
}
}));
You can abort any aquery processing using this.
private AjaxCallback<String> ajaxCallback = new AjaxCallback<String>(){
#Override
public void callback(String url, String object, AjaxStatus status) {
//do your processing with server response
processInformation(result);
};
};
//on our previous code
query.ajax(remoteUrl,String.class,ajaxCallback);
public void cancelAquery(){
//this statement does cancel the request i.e. we won't receive any information on callback method
//ajaxCallback.async(null);
ajaxCallback.abort();
}
For more info, you can see this link https://laaptu.wordpress.com/tag/android-cancelling-aquery/
just call aq.ajaxCancel() for more details refer to the API docs
http://android-query.googlecode.com/svn/trunk/javadoc/com/androidquery/AbstractAQuery.html#ajaxCancel()
I'm getting acquainted with GWTP. I tried to output a table, that would contain the JSON values, taken with a help of Piriti mappers. It's not a real project's code, it's just an attempt to understand GWTP, so this may be not the most beautiful solution (in fact, it's not one for sure). Here are the two presenters that are involved in this procedure:
The FirstPresenter (that uses ProductListPresenter, that is a widget, I'm not sure that widget should be used here, but, according to this conversation, widget may do the trick):
public class FirstPresenter extends
Presenter<FirstPresenter.MyView, FirstPresenter.MyProxy> {
public static final Object SLOT_RATE = new Object();
public static final Object SLOT_PRODUCT = new Object();
private IndirectProvider<ProductListPresenter> productListFactory;
public interface MyView extends View {
public Panel getListProductPanel();
}
#Inject ProductListPresenter productListPresenter;
#ProxyCodeSplit
#NameToken(NameTokens.first)
public interface MyProxy extends ProxyPlace<FirstPresenter> {
}
#Inject
public FirstPresenter(final EventBus eventBus, final MyView view,
final MyProxy proxy, Provider<ProductListPresenter> productListFactory) {
super(eventBus, view, proxy);
this.productListFactory = new StandardProvider<ProductListPresenter>(productListFactory);
}
#Override
protected void revealInParent() {
}
#Override
protected void onBind() {
super.onBind();
}
#Inject
PlaceManager placeManager;
#Override
protected void onReset() {
super.onReset();
setInSlot(SLOT_PRODUCT, null);
for (int i = 0; i < 2; i++) { //TODO: change hardcoded value
productListFactory.get(new AsyncCallback<ProductListPresenter>() {
#Override
public void onSuccess(ProductListPresenter result) {
addToSlot(SLOT_PRODUCT, result);
}
#Override
public void onFailure(Throwable caught) {
}
});
}
}
}
The ProductListPresenter:
public class ProductListPresenter extends
PresenterWidget<ProductListPresenter.MyView> {
#Inject ProductListPiritiJsonReader reader;
public interface MyView extends View {
public Label getNameLabel();
public Label getCompanyLabel();
public Label getSerialLabel();
public Label getPricesLabel();
}
#Inject
public ProductListPresenter(final EventBus eventBus, final MyView view) {
super(eventBus, view);
}
#Override
protected void onBind() {
super.onBind();
}
#Override
protected void onReset() {
super.onReset();
try {
RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, "/jsongwtproject/products.json");
rb.setCallback(new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
ProductList productList = reader.read(response.getText());
for (Product product : productList.getProductList()) {
fetchDataFromServer();
}
}
#Override
public void onError(Request request, Throwable exception) {
Window.alert("Error occurred" + exception.getMessage());
}
});
rb.send();
}
catch (RequestException e) {
Window.alert("Error occurred" + e.getMessage());
}
}
//Takes the JSON string and uses showProductListData(String jsonString) method
public void fetchDataFromServer() {
try {
RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, "/jsongwtpproject/products.json");
rb.setCallback(new RequestCallback() {
#Override
public void onResponseReceived(Request request, Response response) {
showProductListData(response.getText());
}
#Override
public void onError(Request request, Throwable exception) {
Window.alert("Error occurred" + exception.getMessage());
}
});
rb.send();
}
catch (RequestException e) {
Window.alert("Error occurred" + e.getMessage());
}
}
//Uses Piriti mappers to take JSON values
private void showProductListData(String jsonString) {
ProductList productList = reader.read(jsonString);
for (Product product : productList.getProductList()) {
StringBuffer priceSb = new StringBuffer();
for (Double price : product.getPrices()) {
priceSb.append(price + ", ");
}
getView().getNameLabel().setText(product.getName());
getView().getCompanyLabel().setText(product.getCompany());
getView().getSerialLabel().setText(product.getSerialNumber());
getView().getPricesLabel().setText(priceSb.toString());
//break;
}
}
}
And the ProductListView.ui.xml:
<g:HTMLPanel>
<table border="1">
<tr>
<td><g:Label ui:field="nameLabel" /> </td>
<td><g:Label ui:field="companyLabel" /> </td>
<td><g:Label ui:field="serialLabel" /> </td>
<td><g:Label ui:field="pricesLabel" /> </td>
</tr>
</table>
</g:HTMLPanel>
Currrently there are two products in the JSON.
Here is what happens with this code: the first row with Product1 appears, then it changes to the first row that contains Product2's values, then again it contains Product1's values, then again Product2's, after that the second row with Product1 appears, then it changes to the second row that contains Product2's values, then again it contains Product1's values, then again Product2's.
So, there are two products and two rows, and in this code the values are changed twice, but in the end the table contains only Product2's values. If the break; is uncommented, Product1's values output twice in the first row, then in the second row, then the table contain only these Product1's values.
I do understand why that happens. But I haven't yet figured out how to make the correct output. It'd be great if someone could tell me how to do the correct output, or, well, provide an example (or would tell me which part, e.g. the widget usage, is terribly wrong).
The problem with your code is that you really don't have a real table in your ProductListView.ui.xml.
Of course if there were two records retrieved from the server, this part of the code is called twice:
getView().getNameLabel().setText(product.getName());
getView().getCompanyLabel().setText(product.getCompany());
getView().getSerialLabel().setText(product.getSerialNumber());
getView().getPricesLabel().setText(priceSb.toString());
the second call overwriting the value from the first call.
Points to improve your code:
You may want to read about CellTable for creating a real table view.
Do not use the PresenterWidget itself as data holder, instead create
a DTO that will be pass to the database and use this to retrieve the
data.