text:
//
//  Copyright 2011 Catch.com, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

package com.catchnotes.api;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParserException;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.net.Uri;
import android.os.Build;
import android.text.format.Time;
import android.util.Log;
import android.util.TimeFormatException;

import com.android.http.multipart.FilePart;
import com.android.http.multipart.MultipartEntity;
import com.android.http.multipart.Part;
import com.android.http.multipart.StringPart;

/**
 * Java Android interface to the Catch API.
 */
public class CatchAPI {
    public static final int RESULT_ERROR = 0;
    public static final int RESULT_OK = 1;
    public static final int RESULT_UNAUTHORIZED = 2;
    public static final int RESULT_ERROR_PENDING = 3;
    public static final int RESULT_ERROR_PARSER = 4;
    public static final int RESULT_ERROR_RESPONSE = 5;
    public static final int RESULT_AVAILABLE = 6;
    public static final int RESULT_UNAVAILABLE = 7;
    public static final int RESULT_BAD_REQUEST = 8;
    public static final int RESULT_NOT_FOUND = 9;
    public static final int RESULT_OVER_QUOTA = 10;
    public static final int RESULT_SERVER_ERROR = 11;
    public static final int RESULT_UNSUPPORTED_MEDIA = 12;

	private static final String ENCODING = "UTF-8";
    private String userAgent = "CatchAPI (Android)";
    private String source = "CatchAPI for Android";
	public static final String LOGCAT_NAME = "CatchAPI";
    private static final int BUFFER_SIZE = 8 * 1024;

    private String catchBaseUrl = "https://api.catch.com";
	private static final String API_ENDPOINT_ACCOUNT_INFO = "/v2/user";
	private static final String API_ENDPOINT_NOTES = "/v2/notes";
    private static final String API_ENDPOINT_BULK_NOTES = "/v2/bulk_notes";
	private static final String API_ENDPOINT_COMMENTS = "/v2/comments";
	private static final String API_ENDPOINT_COMMENT = "/v2/comment";
	private static final String API_ENDPOINT_MEDIA = "/v2/media";

    public static final String IMAGE_SMALL = "small";
    public static final String IMAGE_MEDIUM = "medium";
    public static final String IMAGE_LARGE = "large";

    private VersionedCatchHttpClient httpClientAccessToken = null;
    private HttpClient httpClientNoToken = null;

	private Time timestamper;
	private SimpleDateFormat rfc3339;
	private Context mContext;
	public boolean loggingEnabled = false;

	/**
	 * Constructor.
	 *
	 * @param appName The name of your application.
	 * @param context Android context.
	 */
	public CatchAPI(String appName, Context context) {
		source = appName;
		mContext = context;
		String version  = "x.xx";

		try {
			PackageInfo info = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
			version = info.versionName;
		} catch (Exception e) { }

		StringBuilder locale = new StringBuilder(5);
		String language = Locale.getDefault().getLanguage();

		if (language != null) {
			locale.append(language);
			String country = Locale.getDefault().getCountry();

			if (country != null) {
				locale.append('-');
				locale.append(country);
			}
		}

		userAgent = appName + '/' + version + " (Android; " +
			Build.VERSION.RELEASE + "; " + Build.BRAND + "; " +
			Build.MODEL + "; " + locale.toString() + ')';

		try {
			if (Integer.parseInt(Build.VERSION.SDK) >= Build.VERSION_CODES.ECLAIR_0_1) {
				// We can use Time & TimeFormatException on Android 2.0.1
				// (API level 6) or greater. It crashes the VM otherwise.
				timestamper = new Time();
			}
		} catch (Exception e) { }
	}

	/**
	 * Sign in with a username and password.
	 *
	 * @param user Username or email address of the account.
	 * @param password Account password.
	 * @param account An optional CatchAccount object that will be filled in with
	 * account information.
	 * @return RESULT_OK on success.
	 */
	public int signIn(String user, String password, CatchAccount account) {
		CatchAccount acct = account;
		if (acct == null) {
			acct = new CatchAccount();
		}

		int returnCode = getAccountInfo(user, password, acct);
		if (returnCode == RESULT_OK) {
			setAccessToken(acct.auth_token);
		}

		return returnCode;
	}

	/**
	 * Sign out.
	 */
	public void close() {
		if (httpClientAccessToken != null) {
			httpClientAccessToken.close();
		}
	}

	private VersionedCatchHttpClient getHttpClient() {
		if (httpClientAccessToken == null) {
			httpClientAccessToken = VersionedCatchHttpClient.newInstance(userAgent, mContext);
		}

		return httpClientAccessToken;
	}

	private HttpClient getHttpClientNoToken() {
		if (httpClientNoToken == null) {
			HttpParams params = new BasicHttpParams();
			HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
			HttpProtocolParams.setUserAgent(params, userAgent);
			HttpProtocolParams.setContentCharset(params, "UTF-8");
			httpClientNoToken = new DefaultHttpClient(params);
		}

		return httpClientNoToken;
	}

	/**
	 * Sign-in using a previously obtained access token.
	 *
	 * @param accessToken The access token.
	 */
	public void setAccessToken(String accessToken) {
        getHttpClient().setAccessToken(accessToken);
	}

	/**
	 * Get information about a user's account (user name, date created, etc).
	 *
	 * @param user Username or email address.  Pass null if already signed in.
	 * @param password Account password.  Pass null if already signed in.
	 * @param account CatchAccount object where information will be returned.
	 * @return RESULT_OK on success.
	 */
	public int getAccountInfo(String user, String password, CatchAccount account) {
		int returnCode = RESULT_ERROR;

		if (account == null) {
			return returnCode;
		}

		HttpResponse response = null;

		if (user != null && password != null && user.length() > 0 && password.length() > 0) {
			// Use user auth to get user info and obtain auth_token
			response = performPOST(API_ENDPOINT_ACCOUNT_INFO, null, null, false, user + ':' + password);
		} else {
			response = performPOST(API_ENDPOINT_ACCOUNT_INFO, null, null, true, null);
		}

		if (response != null) {
			if (isResponseOK(response)) {
				boolean parseResult = false;

				try {
					JSONObject json = new JSONObject(istreamToString(response.getEntity().getContent()));

					// "user" block
					JSONObject userblock = json.getJSONObject("user");
					account.id = userblock.getLong("id");
					account.username = userblock.getString("user_name");
					account.email = userblock.getString("email");
					account.accountCreatedOn = parse3339(userblock.getString("created_at"));
					account.auth_token = userblock.getString("access_token");

					// "account_limits" block
					if (userblock.has("account_limits")) {
						JSONObject limitsblock = userblock.getJSONObject("account_limits");
						account.periodLimit = limitsblock.getLong("monthly_upload_limit");
					}

					// "account_upload_activity_periodic" block
					if (userblock.has("account_upload_activity_periodic")) {
						JSONArray activityarray = userblock.getJSONArray("account_upload_activity_periodic");

						if (activityarray.length() > 0) {
							JSONObject currentPeriod = activityarray.getJSONObject(0);
							account.periodStart = parse3339(currentPeriod.getString("period_start"));
							account.periodUsage = currentPeriod.getLong("period_activity");
							account.periodEnd = parse3339(currentPeriod.getString("period_end"));
						}
					}

					// account info
					if (userblock.has("account_level")) {
						account.accountLevel = userblock.getInt("account_level");
					}

					if (userblock.has("account_level_desc")) {
						account.accountDescription = userblock.getString("account_level_desc");
					}

					// "account_subscription_end_advisory"
					if (userblock.has("account_subscription_end_advisory")) {
						String subEnd = userblock.getString("account_subscription_end_advisory");

						if (subEnd != null && !"null".equals(subEnd)) {
							account.subscriptionEnd = parse3339(subEnd);
						}
					}

					parseResult = true;
				} catch (JSONException e) {
					log("caught a JSONException processing response from POST " + API_ENDPOINT_ACCOUNT_INFO, e);
				} catch (IOException e) {
					log("caught an IOException processing response from POST " + API_ENDPOINT_ACCOUNT_INFO, e);
				}

				returnCode = (parseResult == true) ? RESULT_OK : RESULT_ERROR_RESPONSE;
			} else if (isResponseUnauthorized(response)) {
				returnCode = RESULT_UNAUTHORIZED;
			} else if (isResponseServerError(response)) {
				returnCode = RESULT_SERVER_ERROR;
			}

			consumeResponse(response);
		}

		return returnCode;
	}

	/**
	 * Fetches a list of note references representing all of the user's notes.
	 *
	 * @param noteRefs List where fetched note refs will be returned.
	 * @return RESULT_OK on success.
	 */
    public int getSyncV2(List<CatchNoteRef> noteRefs) {
        int returnCode = RESULT_ERROR;

        if (noteRefs == null) {
            return returnCode;
        }

        String endpoint = API_ENDPOINT_NOTES + ".xml";
        HttpResponse response = performGET(endpoint, null, true);

        if (response != null) {
            if (isResponseOK(response)) {
                boolean parseResult = false;

                try {
                    CatchNotesXmlParser xmlParser = new CatchNotesXmlParser();
                    xmlParser.parseSyncV2XML(response, noteRefs);
                    parseResult = true;
                } catch (IllegalArgumentException e) {
                    log("caught an IllegalArgumentException processing response from GET " + endpoint, e);
                } catch (XmlPullParserException e) {
                    log("caught an XmlPullParserException processing response from GET " + endpoint, e);
                } catch (IOException e) {
                    log("caught an IOException processing response from GET " + endpoint, e);
                }

                returnCode = (parseResult == true) ? RESULT_OK : RESULT_ERROR_RESPONSE;
            } else if (isResponseUnauthorized(response)) {
                returnCode = RESULT_UNAUTHORIZED;
            } else if (isResponseServerError(response)) {
				returnCode = RESULT_SERVER_ERROR;
			}

            consumeResponse(response);
        }

        return returnCode;
    }

    /**
     * Fetches a list of specific requested notes.
     *
     * @param noteRefs List of note refs representing the notes you want to fetch.
     * @param notes List where fetched notes will be returned.
     * @return RESULT_OK on success.
     */
    public int getNotesBulk(List<CatchNoteRef> noteRefs, ArrayList<CatchNote> notes) {
        int returnCode = RESULT_ERROR;

        if (notes == null) {
            return returnCode;
        }

        String endpoint;
        endpoint = API_ENDPOINT_BULK_NOTES + ".xml";
        StringBuilder bulkNotes = new StringBuilder("{\"notes\": [\"");
        Iterator<CatchNoteRef> syncIterator = noteRefs.iterator();

        while (syncIterator.hasNext()) {
            bulkNotes.append(syncIterator.next().nodeId);

            if (syncIterator.hasNext()) {
                bulkNotes.append("\", \"");
            }
        }

        bulkNotes.append("\"]}");
        List <NameValuePair> params = new ArrayList <NameValuePair>();
        params.add(new BasicNameValuePair("bulk", bulkNotes.toString()));
        HttpResponse response = performPOST(endpoint, params, null, true, null);

        if (response != null) {
            if (isResponseOK(response)) {
                boolean parseResult = false;

                try {
                    CatchNotesXmlParser xmlParser = new CatchNotesXmlParser();
                    xmlParser.parseNotesXml(response, notes, -1);
                    parseResult = true;
                } catch (IllegalArgumentException e) {
                    log("caught an IllegalArgumentException processing response from POST " + endpoint, e);
                } catch (XmlPullParserException e) {
                    log("caught an XmlPullParserException processing response from POST " + endpoint, e);
                } catch (IOException e) {
                    log("caught an IOException processing response from POST " + endpoint, e);
                }

                returnCode = (parseResult == true) ? RESULT_OK : RESULT_ERROR_RESPONSE;
            } else if (isResponseUnauthorized(response)) {
                returnCode = RESULT_UNAUTHORIZED;
            } else if (isResponseServerError(response)) {
				returnCode = RESULT_SERVER_ERROR;
			}

            consumeResponse(response);
        }

        return returnCode;
    }

    /**
     * Fetches a list of all of the user's notes.
     *
     * @param notes List where fetched notes will be returned.
     * @return RESULT_OK on success.
     */
	public int getNotes(ArrayList<CatchNote> notes) {
		return getComments(-1, notes);
	}

	/**
	 * Fetches a list of comments belonging to a certain note.
	 *
	 * @param parentId The parent note of the requested comments.
	 * @param notes List where fetched comments will be returned.
	 * @return RESULT_OK on success.
	 */
	public int getComments(long parentId, ArrayList<CatchNote> notes) {
		int returnCode = RESULT_ERROR;

		if (notes == null) {
			return returnCode;
		}

		String endpoint;
		List<NameValuePair> params = null;

		if (parentId != -1) {
			endpoint = API_ENDPOINT_COMMENTS + '/' + parentId + ".xml";
		} else {
			endpoint = API_ENDPOINT_NOTES + ".xml";
			params = new ArrayList <NameValuePair>();
	        params.add(new BasicNameValuePair("full", "1"));
		}

		HttpResponse response = performGET(endpoint, params, true);

		if (response != null) {
			if (isResponseOK(response)) {
				boolean parseResult = false;

				try {
					CatchNotesXmlParser xmlParser = new CatchNotesXmlParser();
					xmlParser.parseNotesXml(response, notes, parentId);
					parseResult = true;
				} catch (IllegalArgumentException e) {
					log("caught an IllegalArgumentException processing response from GET " + endpoint, e);
				} catch (XmlPullParserException e) {
					log("caught an XmlPullParserException processing response from GET " + endpoint, e);
				} catch (IOException e) {
					log("caught an IOException processing response from GET " + endpoint, e);
				}

				returnCode = (parseResult == true) ? RESULT_OK : RESULT_ERROR_RESPONSE;
			} else if (isResponseUnauthorized(response)) {
				returnCode = RESULT_UNAUTHORIZED;
			} else if (isResponseServerError(response)) {
				returnCode = RESULT_SERVER_ERROR;
			}

			consumeResponse(response);
		}

		return returnCode;
	}

	/**
	 * Gets a data stream for a media item.
	 *
	 * @param uri The URI of the media to fetch.  See {@link CatchMedia#src}.
	 * @param size If the media is an image, then you may pass IMAGE_SMALL,
	 * IMAGE_MEDIUM, or IMAGE_LARGE.  Otherwise pass null.
	 * @param outputStream Data is returned here.
	 * @return RESULT_OK on success.
	 */
	public int getMedia(String uri, String size, OutputStream outputStream) {
		int returnCode = RESULT_ERROR;

		if (uri == null || outputStream == null) {
			return returnCode;
		}

		try {
            List<NameValuePair> httpParams = new ArrayList<NameValuePair>();

			if (size != null) {
	            httpParams.add(new BasicNameValuePair("size", size));
			}

			if (uri.contains("viewImage.action?")) {
				// Legacy viewImage.action image source URLs need to be pulled
				// apart a bit so as to fit into the new logic
				httpParams.add(new BasicNameValuePair("imageId", Uri.parse(uri).getQueryParameter("imageId")));
				uri = uri.split("\\?")[0];
			}

			HttpResponse response = performGET(uri, (httpParams.size() > 0) ? httpParams : null, true);

			if (response != null) {
				if (isResponseOK(response)) {
					BufferedInputStream inputStream = new BufferedInputStream(response.getEntity().getContent(), BUFFER_SIZE);

					byte[] b = new byte[BUFFER_SIZE];
					int read;

					while ((read = inputStream.read(b)) != -1) {
						outputStream.write(b, 0, read);
					}

					outputStream.flush();
					outputStream.close();
				    inputStream.close();
					returnCode = RESULT_OK;
				} else if (isResponseUnauthorized(response)) {
					returnCode = RESULT_UNAUTHORIZED;
				} else if (isResponseNotFound(response)) {
					returnCode = RESULT_NOT_FOUND;
				} else if (isResponseServerError(response)) {
					returnCode = RESULT_SERVER_ERROR;
				}

				consumeResponse(response);
			}
		} catch (IOException e) {
			log("caught a IOException in getImage() for " + uri, e);
		}

		return returnCode;
	}

	/**
	 * Adds a new note to the account.
	 *
	 * @param note Note to be added.
	 * @return RESULT_OK on success.
	 */
	public int addNote(CatchNote note) {
		int returnCode = RESULT_ERROR;

		if (note == null) {
			return returnCode;
		}

		List <NameValuePair> params = new ArrayList <NameValuePair>();
		params.add(new BasicNameValuePair("text", (note.text == null) ? "" : note.text.toString()));
		params.add(new BasicNameValuePair("created_at", Long.toString(note.creationTime)));
		params.add(new BasicNameValuePair("modified_at", Long.toString(note.modificationTime)));

		if (note.source == null || note.source.length() == 0 || note.source.equals(CatchNote.NOT_SET)) {
			params.add(new BasicNameValuePair("source", source));
		} else {
			params.add(new BasicNameValuePair("source", note.source));

			if (note.sourceUrl != null && note.source.length() > 0 && note.sourceUrl.equals(CatchNote.NOT_SET)) {
				params.add(new BasicNameValuePair("source_url", note.sourceUrl));
			}
		}

		//XXXaes
        if (note.annotations != null) {
            for (String key: note.annotations.keySet()) {
                params.add(new BasicNameValuePair(CatchNotesXmlParser.CATCH_NAMESPACE_PREFIX + ":" + key, note.annotations.get(key)));
            }
        }

		String endpoint;

		if (note.parentId != -1) {
			// adding a comment
			endpoint = API_ENDPOINT_COMMENTS + '/' + note.parentNodeId + ".xml";
		} else {
			// adding a note
			endpoint = API_ENDPOINT_NOTES + ".xml";
			params.add(new BasicNameValuePair("mode", (note.mode == null) ? CatchNote.MODE_PRIVATE : note.mode.toString()));
			params.add(new BasicNameValuePair("reminder_at", Long.toString(note.reminderTime)));
			params.add(new BasicNameValuePair("latitude", Double.toString(note.latitude)));
			params.add(new BasicNameValuePair("longitude", Double.toString(note.longitude)));
			params.add(new BasicNameValuePair("altitude", Double.toString(note.altitude)));
			params.add(new BasicNameValuePair("speed", Double.toString(note.speed)));
			params.add(new BasicNameValuePair("bearing", Double.toString(note.bearing)));
			params.add(new BasicNameValuePair("accuracy_position", Double.toString(note.accuracyPosition)));
			params.add(new BasicNameValuePair("accuracy_altitude", Double.toString(note.accuracyAltitude)));
		}

		HttpResponse response = performPOST(endpoint, params, null, true, null);

		if (response != null) {
			if (isResponseOK(response)) {
				boolean parseResult = false;

				try {
					CatchNotesXmlParser xmlParser = new CatchNotesXmlParser();
					ArrayList<CatchNote> notes = new ArrayList<CatchNote>(1);
					xmlParser.parseNotesXml(response, notes, note.parentId);

					if (notes.size() > 0 && notes.get(0) != null) {
						// Copy the returned note values into the original note object
						note.copy(notes.get(0));
						parseResult = true;
					}
				} catch (IllegalArgumentException e) {
					log("caught an IllegalArgumentException processing response from POST " + endpoint, e);
				} catch (XmlPullParserException e) {
					log("caught an XmlPullParserException processing response from POST " + endpoint, e);
				} catch (IOException e) {
					log("caught an IOException processing response from POST " + endpoint, e);
				}

				returnCode = (parseResult == true) ? RESULT_OK : RESULT_ERROR_RESPONSE;
			} else if (isResponseUnauthorized(response)) {
				returnCode = RESULT_UNAUTHORIZED;
			} else if (isResponseNotFound(response)) {
				returnCode = RESULT_NOT_FOUND;
			} else if (isResponsePaymentRequired(response)) {
				returnCode = RESULT_OVER_QUOTA;
			} else if (isResponseServerError(response)) {
				returnCode = RESULT_SERVER_ERROR;
			} else {
                returnCode = RESULT_ERROR_PENDING;
            }

			consumeResponse(response);
		}

		return returnCode;
	}

	/**
	 * Adds a media item to a note.
	 *
	 * @param media A CatchMedia object that specifies the media data and note ID.
	 * @return RESULT_OK on success.
	 */
	public int addMedia(CatchMedia media) {
		int returnCode = RESULT_ERROR;

		if (media == null || media.data == null || media.content_type == null || media.note_id == null) {
			return returnCode;
		}

		try {
			String endpoint = API_ENDPOINT_MEDIA + '/' + media.note_id;

			StringPart contentType = new StringPart("content_type", media.content_type, HTTP.UTF_8);
			StringPart createdAt = new StringPart("created_at", Long.toString(media.created_at), HTTP.UTF_8);
			StringPart voiceHint = new StringPart("voicenote_hint", "true", HTTP.UTF_8);
			FilePart data = new FilePart("data", media.data, media.content_type, null);

			HttpResponse response;

			if (media.voice_hint) {
				response = performPOST(endpoint, null, new Part[] { contentType, createdAt, voiceHint, data }, true, null);
			} else {
				response = performPOST(endpoint, null, new Part[] { contentType, createdAt, data }, true, null);
			}

			if (response != null) {
				if (isResponseOK(response)) {
					boolean parseResult = false;

					try {
						JSONObject json = new JSONObject(istreamToString(response.getEntity().getContent()));
						media.id = json.getString("id");
						media.src = json.getString("src");
						media.size = json.getLong("size");
						media.content_type = json.getString("type");
						media.created_at = parse3339(json.getString("created_at"));
						media.voice_hint = json.getBoolean("voicenote_hint");
						parseResult = true;
					} catch (JSONException e) {
						log("caught a JSONException processing response from POST " + endpoint, e);
					} catch (IOException e) {
						log("caught an IOException processing response from POST " + endpoint, e);
					}

					returnCode = (parseResult == true) ? RESULT_OK : RESULT_ERROR_RESPONSE;
				} else if (isResponsePaymentRequired(response)) {
					returnCode = RESULT_OVER_QUOTA;
				} else if (isResponseUnsupportedMedia(response)) {
					returnCode = RESULT_UNSUPPORTED_MEDIA;
				} else if (isResponseUnauthorized(response)) {
					returnCode = RESULT_UNAUTHORIZED;
				} else if (isResponseBadRequest(response)) {
					returnCode = RESULT_BAD_REQUEST;
				} else if (isResponseServerError(response)) {
					returnCode = RESULT_SERVER_ERROR;
				}

				consumeResponse(response);
			}
		} catch (FileNotFoundException e) {
			log("caught a FileNotFoundException in addMedia() for file: " + media.data.getAbsolutePath(), e);
		}

		return returnCode;
	}

	/**
	 * Edits an existing note.
	 *
	 * @param note Note to be updated. note.id must be a valid existing note id.
	 * @return RESULT_OK on success.
	 */
	public int editNote(CatchNote note) {
		int returnCode = RESULT_ERROR;

		if (note == null) {
			return returnCode;
		}

		List <NameValuePair> params = new ArrayList <NameValuePair>();
		params.add(new BasicNameValuePair("text", (note.text == null) ? "" : note.text.toString()));
		params.add(new BasicNameValuePair("source", source));

		// TODO: if we supply server_modified_at, the backend will perform conflict detection
		//params.add(new BasicNameValuePair("server_modified_at", Long.toString(note.serverModifiedAt)));

		params.add(new BasicNameValuePair("modified_at", Long.toString(note.modificationTime)));

		String endpoint;

		if (note.parentId != -1) {
			// editing a comment
			params.add(new BasicNameValuePair("comment", note.id));
			endpoint = API_ENDPOINT_COMMENT + '/' + note.parentNodeId + ".xml";
		} else {
			// editing a note
			endpoint = API_ENDPOINT_NOTES + '/' + note.id + ".xml";
			params.add(new BasicNameValuePair("mode", (note.mode == null) ? CatchNote.MODE_PRIVATE : note.mode.toString()));
			params.add(new BasicNameValuePair("reminder_at", Long.toString(note.reminderTime)));
		}

		//XXXaes
        if (note.annotations != null) {
            for (String key: note.annotations.keySet()) {
                params.add(new BasicNameValuePair(CatchNotesXmlParser.CATCH_NAMESPACE_PREFIX + ":" + key, note.annotations.get(key)));
            }
        }

		HttpResponse response = performPOST(endpoint, params, null, true, null);

		if (response != null) {
			if (isResponseOK(response)) {
				boolean parseResult = false;

				try {
					CatchNotesXmlParser xmlParser = new CatchNotesXmlParser();
					ArrayList<CatchNote> notes = new ArrayList<CatchNote>(1);
					xmlParser.parseNotesXml(response, notes, note.parentId);

					if (notes.size() > 0 && notes.get(0) != null) {
						// Copy the returned note values into the original note object
						note.copy(notes.get(0));
						parseResult = true;
					}
				} catch (IllegalArgumentException e) {
					log("caught an IllegalArgumentException processing response from POST " + endpoint, e);
				} catch (XmlPullParserException e) {
					log("caught an XmlPullParserException processing response from POST " + endpoint, e);
				} catch (IOException e) {
					log("caught an IOException processing response from POST " + endpoint, e);
				}

				returnCode = (parseResult == true) ? RESULT_OK : RESULT_ERROR_RESPONSE;
			} else if (isResponseUnauthorized(response)) {
				returnCode = RESULT_UNAUTHORIZED;
			} else if (isResponseNotFound(response)) {
				returnCode = RESULT_NOT_FOUND;
			} else if (isResponsePaymentRequired(response)) {
				returnCode = RESULT_OVER_QUOTA;
			} else if (isResponseServerError(response)) {
				returnCode = RESULT_SERVER_ERROR;
			} else {
                returnCode = RESULT_ERROR_PENDING;
            }

			consumeResponse(response);
		}

		return returnCode;
	}

	/**
	 * Deletes a note.
	 *
	 * @param id ID of the note to be deleted
	 * @param parentNodeId If you are deleting a comment, this is the parent note's ID.
	 * @return RESULT_OK on success
	 */
    public int deleteNote(String id, String parentNodeId) {
        int returnCode = RESULT_ERROR;
        HttpResponse response;

        if (parentNodeId == null || CatchNote.NODE_ID_NEVER_SYNCED.equals(parentNodeId)) {
            response = performDELETE(API_ENDPOINT_NOTES + '/' + id, null);
        } else {
            List <NameValuePair> params = new ArrayList <NameValuePair>();
            params.add(new BasicNameValuePair("comment", id));
            response = performDELETE(API_ENDPOINT_COMMENT + '/' + parentNodeId, params);
        }

        if (response != null) {
            if (isResponseOK(response)) {
                returnCode = RESULT_OK;
            } else if (isResponseUnauthorized(response)) {
                returnCode = RESULT_UNAUTHORIZED;
            } else if (isResponseNotFound(response)) {
                returnCode = RESULT_NOT_FOUND;
            } else if (isResponseServerError(response)) {
				returnCode = RESULT_SERVER_ERROR;
			} else {
                returnCode = RESULT_ERROR_PENDING;
            }

            consumeResponse(response);
        }

        return returnCode;
    }

    /**
     * Deletes a media item.
     *
     * @param noteId The note containing the media you want to remove.
     * @param mediaId ID of the media.
     * @return RESULT_OK on success.
     */
	public int deleteMedia(String noteId, String mediaId) {
		int returnCode = RESULT_ERROR;
		HttpResponse response = performDELETE(API_ENDPOINT_MEDIA + '/' + noteId + '/' + mediaId, null);

		if (response != null) {
			if (isResponseOK(response)) {
				returnCode = RESULT_OK;
			} else if (isResponseUnauthorized(response)) {
				returnCode = RESULT_UNAUTHORIZED;
			}

			consumeResponse(response);
		}

		return returnCode;
	}

	private HttpResponse performGET(String method,
			List<NameValuePair> httpParams, boolean useToken) {
		HttpGet httpget;
		String uri = method;

		if (!uri.startsWith("http")) {
			// method isn't a fully-qualified URI
			uri = catchBaseUrl + uri;
		}

		if (httpParams == null || httpParams.isEmpty()) {
			httpget = new HttpGet(uri);
		} else {
			httpget = new HttpGet(uri + '?' + URLEncodedUtils.format(httpParams, "UTF-8"));
		}

		HttpResponse response = null;

		try {
			response = useToken ? getHttpClient().execute(httpget) : getHttpClientNoToken().execute(httpget);
		} catch (ClientProtocolException e) {
			log("caught ClientProtocolException performing GET " + httpget.getURI(), e);
			return null;
		} catch (UnknownHostException e) {
			log("caught UnknownHostException performing GET " + httpget.getURI(), null);
			return null;
		} catch (IOException e) {
			log("caught IOException performing GET " + httpget.getURI(), e);
			return null;
		}

		sync_trace("GET " + httpget.getURI() + " returned " +
				response.getStatusLine().getStatusCode() + ' ' +
				response.getStatusLine().getReasonPhrase());
		return response;
	}

	private HttpResponse performPOST(String method,
			List<NameValuePair> parameters, Part[] parts, boolean useToken, String auth) {
		HttpPost httppost = new HttpPost(catchBaseUrl + method);

		if (parameters != null && !parameters.isEmpty()) {
			try {
				httppost.setEntity(new UrlEncodedFormEntity(parameters, HTTP.UTF_8));
			} catch (UnsupportedEncodingException e) {
				log("caught UnsupportedEncodingException performing POST " + httppost.getURI(), e);
				return null;
			}
		} else if (parts != null) {
			HttpProtocolParams.setUseExpectContinue(httppost.getParams(), false);
			httppost.setEntity(new MultipartEntity(parts, httppost.getParams()));
		}

		if (auth != null) {
			if (useToken) {
				return null;
			}

			try {
				httppost.addHeader("Authorization", "Basic " +  new String(Base64.encodeBase64(auth.getBytes("UTF-8"))));
			} catch (UnsupportedEncodingException e) {
				Log.e(LOGCAT_NAME, "unable to perform basic auth, UTF-8 encoding not supported!");
				return null;
			}
		}

		HttpResponse response = null;

		try {
			response = useToken ? getHttpClient().execute(httppost) : getHttpClientNoToken().execute(httppost);
		} catch (ClientProtocolException e) {
			log("caught ClientProtocolException performing POST " + httppost.getURI(), e);
			return null;
		} catch (IOException e) {
			log("caught IOException performing POST " + httppost.getURI(), e);
			return null;
		}

		sync_trace("POST " + httppost.getURI() + " returned " +
				response.getStatusLine().getStatusCode() + ' ' +
				response.getStatusLine().getReasonPhrase());
		return response;
	}

	private HttpResponse performDELETE(String method, List<NameValuePair> httpParams) {
		HttpDelete httpdelete;

		if (httpParams == null || httpParams.isEmpty()) {
			httpdelete = new HttpDelete(catchBaseUrl + method);
		} else {
			httpdelete = new HttpDelete(catchBaseUrl + method + '?' + URLEncodedUtils.format(httpParams, "UTF-8"));
		}

		HttpResponse response = null;

		try {
			response = getHttpClient().execute(httpdelete);
		} catch (ClientProtocolException e) {
			log("caught ClientProtocolException performing DELETE " + httpdelete.getURI(), e);
			return null;
		} catch (IOException e) {
			log("caught IOException performing DELETE " + httpdelete.getURI(), e);
			return null;
		}

		sync_trace("DELETE " + httpdelete.getURI() + " returned " +
				response.getStatusLine().getStatusCode() + ' ' +
				response.getStatusLine().getReasonPhrase());
		return response;
	}

	private boolean isResponseOK(HttpResponse response) {
		return (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK);
	}

	private boolean isResponseUnauthorized(HttpResponse response) {
		return (response.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED);
	}

	private boolean isResponseNotFound(HttpResponse response) {
		return (response.getStatusLine().getStatusCode() == HttpStatus.SC_NOT_FOUND);
	}

	private boolean isResponseBadRequest(HttpResponse response) {
		return (response.getStatusLine().getStatusCode() == HttpStatus.SC_BAD_REQUEST);
	}

	private boolean isResponsePaymentRequired(HttpResponse response) {
		return (response.getStatusLine().getStatusCode() == HttpStatus.SC_PAYMENT_REQUIRED);
	}

	private boolean isResponseUnsupportedMedia(HttpResponse response) {
		return (response.getStatusLine().getStatusCode() == HttpStatus.SC_UNSUPPORTED_MEDIA_TYPE);
	}

	private boolean isResponseServerError(HttpResponse response) {
		return (response.getStatusLine().getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR);
	}

	private void consumeResponse(HttpResponse response) {
		if (response != null && response.getEntity() != null) {
			try {
				response.getEntity().consumeContent();
			} catch (IOException e) {
				log("caught an IOException attempting to consume the content of an HttpResponse", e);
			}
		}
	}

	private long parse3339(String time) {
		if (time == null || time.length() == 0) {
			return 0;
		}

		if (timestamper != null) {
			try {
				timestamper.parse3339(time);
			} catch (TimeFormatException e) {
				log("caught a TimeFormatException parsing timestamp: \"" + time + '"', e);
				return 0;
			}

			return timestamper.normalize(false);
		} else {
			Date timestamp = new Date();

			if (rfc3339 == null) {
				rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
				rfc3339.setTimeZone(TimeZone.getTimeZone("GMT+0"));
				rfc3339.setLenient(true);
			}

			try {
				timestamp = rfc3339.parse(time);
			} catch (ParseException e) {
				log("caught a ParseException parsing timestamp: \"" + time + '"', e);
				return 0;
			}

			return timestamp.getTime();
		}
	}

	// from Translate.java
	/*
	 * Copyright (C) 2008 Google Inc.
	 *
	 * Licensed under the Apache License, Version 2.0 (the "License");
	 * you may not use this file except in compliance with the License.
	 * You may obtain a copy of the License at
	 *
	 *      http://www.apache.org/licenses/LICENSE-2.0
	 *
	 * Unless required by applicable law or agreed to in writing, software
	 * distributed under the License is distributed on an "AS IS" BASIS,
	 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	 * See the License for the specific language governing permissions and
	 * limitations under the License.
	 */
	private static String istreamToString(InputStream inputStream) throws IOException {
		StringBuilder outputBuilder = new StringBuilder();
		String string;

		if (inputStream != null) {
			BufferedReader reader =
				new BufferedReader(new InputStreamReader(inputStream, ENCODING));

			while (null != (string = reader.readLine())) {
				outputBuilder.append(string).append('\n');
			}

			reader.close();
		}

		return outputBuilder.toString();
	}

	// Helper function to log error messages & exceptions.
	private void log(String msg, Exception e) {
		Log.e(LOGCAT_NAME, msg, e);
	}

	// Helper function to log tracing messages.
	private void sync_trace(String msg) {
		if (loggingEnabled) {
			Log.d(LOGCAT_NAME, msg);
		}
	}

	/**
	 * Helper function to turn return codes into readable text.
	 *
	 * @param code The code to convert.
	 * @return The String representation of the code.
	 */
	public static String resultToString(int code) {
		switch (code) {
			case RESULT_ERROR:
				return "RESULT_ERROR";
			case RESULT_OK:
				return "RESULT_OK";
			case RESULT_UNAUTHORIZED:
				return "RESULT_UNAUTHORIZED";
			case RESULT_ERROR_PENDING:
				return "RESULT_ERROR_PENDING";
			case RESULT_ERROR_PARSER:
				return "RESULT_ERROR_PARSER";
			case RESULT_ERROR_RESPONSE:
				return "RESULT_ERROR_RESPONSE";
			case RESULT_AVAILABLE:
				return "RESULT_AVAILABLE";
			case RESULT_UNAVAILABLE:
				return "RESULT_UNAVAILABLE";
			case RESULT_BAD_REQUEST:
				return "RESULT_BAD_REQUEST";
			case RESULT_NOT_FOUND:
				return "RESULT_NOT_FOUND";
			case RESULT_OVER_QUOTA:
				return "RESULT_OVER_QUOTA";
			case RESULT_SERVER_ERROR:
				return "RESULT_SERVER_ERROR";
			case RESULT_UNSUPPORTED_MEDIA:
				return "RESULT_UNSUPPORTED_MEDIA";
			default:
				return "UNKNOWN (" + code + ")";
		}
	}
}

redpajama_set_name: RedPajamaGithub


text:
Arrests, evictions and scapegoating: Coronavirus takes a toll on LGBT+ Africans
by Nita Bhalla and Alice McCool | Thomson Reuters Foundation
Thursday, 16 April 2020 16:34 GMT
ARCHIVE PHOTO: LGBT activists react after a ruling by Kenya's high court to upheld a law banning gay sex, outside the Milimani high Court in Nairobi, Kenya May 24, 2019. REUTERS/Baz Ratner
About our LGBT+ coverage
We delve deeper into the issues faced by LGBT+ communities around the world.
LGBT+ Africans suffer persecution, hardships as COVID-19 cases rise
By Nita Bhalla and Alice McCool
NAIROBI/KAMPALA, April 16 (Thomson Reuters Foundation) - Just before breakfast on a Sunday morning, Ugandan security forces stormed an LGBT+ shelter outside the capital Kampala, accusing more than 20 gay, bisexual and transgender people of spreading the new coronavirus.
Eye-witnesses said the police took everyone's phones and shoes and soldiers bound their hands with rope and marched them barefoot to a nearby police station in Kyengera town.
"At first the only question they kept asking was why there were condoms in house," said Charles Senna, who works at the shelter run by the charity, Children of The Sun Foundation.
"Then they changed to asking why there were so many people in the shelter ... and saying that they were failing to follow the directions of the president on social distancing."
More than two weeks on, 20 members of the group are languishing in prison awaiting trial after being charged with disobeying COVID-19 social distancing rules and risking the spread of the virus.
The raid on the Ugandan shelter, say LGBT+ rights groups, is just one in a rising number of incidents that are taking a toll on Africa's sexual and gender minorities as COVID-19 cases rise across the continent.
"The community already faces so much discrimination but now with this coronavirus, things are getting worse," said Frank Mugisha, executive director of Sexual Minorities Uganda (SMUG).
"We've had reports of LGBTQI members being blamed for the virus. Due to lockdowns, many people cannot work and pay rent. We know some are being evicted and forced to return to their families who kicked them out. It's causing a lot of anguish."
PRETEXT
African countries have some of the world's most prohibitive laws governing homosexuality. Gay sex is a crime across most of continent, with punishments ranging from imprisonment to death.
Gay rights groups say the laws promote intolerance and discrimination against minorities in the workplace, housing, education and health care, as well as hate crimes like blackmail - with most victims too scared to go to the police for help.
The March 29 raid on the shelter shows the pandemic has given authorities with a history of targeting gay, bisexual and trans Africans a pretext for fresh attacks, said Mawethu Nkosana, an LGBT+ campaigner with civil society group, CIVICUS.
"The arrests have nothing to do with violating COVID-19 social distancing rules, but are based on the state's prejudice against the LGBTI community - this has been the case even before the COVID-19 pandemic," said Nkosana.
"There is no justification for these arrests and the activists should be released immediately."
Ugandan police have said they were enforcing social distancing rules which included a ban on public gatherings of 10 or more people at that time.
"If the house was targeted because it was a shelter for LGBT - we still have offences of unnatural sex in our law books - we would have charged them with that law but we didn't," said Patrick Onyango, deputy police spokesman.
Scores of people were arrested last year in raids on a gay-friendly bar and office in Uganda, where gay sex carries a possible life sentence.
DISTURBING GOD'S ORDER
COVID-19 has also increased anti-gay rhetoric from religious leaders who regard the virus as a punishment sent by God for the sin of homosexuality.
"Our governments are wicked, disturbing Gods order by allowing and legalising same sex marriages, and homosexuality," Oscar Peter Bougardt, a Cape Town pastor said on Facebook.
South Africa is the only African nation to legalise gay marriage.
"This pestilence called Covid 19 aka Caronavirus is the wrath of God upon this wicked world," wrote Bougardt, who has previously faced legal action for anti-gay hate speech.
The Ghana Muslim Mission said in a statement on COVID-19 that it was important to acknowledge sins "especially the most abominable acts such as homosexuality, lesbianism, transgender, destruction of water bodies and forests".
The World Health Organization, which is leading the global fight against the outbreak, has called for an end to misinformation, warning it fuels stigma and discrimination.
'HOMOPHOBIC STRESS'
The physical and mental health of vulnerable LGBT+ people is a key concern for rights groups as numerous African countries have introduced restrictions to halt the spread of the virus, including curfews and lockdowns.
Many people living with HIV/AIDS have been unable to get to clinics to collect their medicines while penniless waiters, artists and informal sector workers have been forced to live with abusive families or partners, say campaigners.
"They are suffering a lot of homophobic and transphobic stress due to family members," said Mugisha of SMUG, which is providing counselling and tips to help LGBT+ people survive lockdown by being helpful, blending in and ignoring insults.
"They are forced to stay with them in very difficult and hostile circumstances."
The apparent suicide of a gay Ugandan refugee outside the Nairobi offices of the United Nations refugee agency (UNHCR) on Monday highlighted LGBT+ refugees' need for support, with estimates of more than 750 LGBT+ refugees in Kenya.
Scores live in the remote northern Kakuma refugee camp where they face physical attacks, while others stay in urban areas where they struggle to find work and are often evicted by homophobic landlords and community members.
Police are investigating the death, but those who knew the deceased said the man had no money, and the frustration of waiting to be resettled in a safer country and restrictions linked to the pandemic may have worsened his mental health.
"He was upset. His monthly financial assistance from UNHCR had stopped two months ago and he was depressed about the fact that he had not got resettlement," said Mbazira Moses from Refugee Flag Kakuma, a LGBT+ refugee group.
"The coronavirus made things worse. He wasn't able to move around find work as transport costs have gone up, and there was no hope of immediate resettlement as there is freeze on processing asylum applications ... this depressed him."
UNHCR said in a statement that it was cooperating with police investigators and would do all it could to support refugees during the pandemic.
"UNHCR is concerned about the growing challenges faced by refugees and asylum-seekers as well as communities hosting them, in meeting their basic needs in the current difficult context," said Fathiaa Abdalla, UNHCR representative in Kenya.
Ugandan rights groups demand release of LGBT+ people jailed over coronavirus
LGBT+ group sues Ukraine religious figure linking coronavirus to gay marriage
Coronavirus lockdown exposes LGBT+ people to family abuse in Middle East
U.S. and Israeli religious figures blame LGBT+ people for coronavirus
(Reporting by Nita Bhalla @nitabhalla and Alice McCool. Writing by Nita Bhalla. Additional reporting by Kim Harrisberg and Vincent Desmond. Editing by Katy Migiro. Please credit the Thomson Reuters Foundation, the charitable arm of Thomson Reuters, that covers the lives of people around the world who struggle to live freely or fairly. Visit http://news.trust.org)
((nita.bhalla@thomsonreuters.com; +254 798188824; Reuters Messaging: nita.bhalla.reuters.com@reuters.net))
LGBT - People
EXPLORE MORE LGBT+ NEWS
Gilead says counterfeit HIV drugs ended up with patients
Why are there no openly gay players in elite men's tennis?
Hormones help trans teens, U.S. study finds, as state bans loom

redpajama_set_name: RedPajamaCommonCrawl


text:
(, na numeração romana) foi um ano comum do século XVII do actual Calendário Gregoriano, da Era de Cristo,  e a sua letra dominical foi C, teve 52 semanas,  início a uma sexta-feira e terminou também a uma sexta-feira.

Eventos
 Os franceses fundam uma colónia em Saint Kitts, nas Caraíbas.
 1ª edição da Nova Atlântida, obra póstuma de Francis Bacon.
 Último auroque existente no mundo morto por caçadores na Polônia.

Em andamento
 Guerra dos Trinta Anos (1618–1648).

Nascimentos
 25 de Janeiro - Robert Boyle, cientista anglo-irlandês.
 27 de Setembro - Jacques Bossuet, Téorico Absolutista.

redpajama_set_name: RedPajamaWikipedia


Pomegranate juice has already shown cytotoxicity to a variety of cancer cell lines in lab studies. This has been further validated by pre-clinical studies on lab animals showing that oral feeding of pomegranate extract inhibits the growth of lung, skin, colon and prostate tumors. So compelling is the lab evidence that ten clinical trials have been registered with the NIH to use pomegranate extract against cancer (nine trials on prostate cancer, one on follicular lymphoma). Clinical success has already been demonstrated in a Phase II trial for prostate cancer: PSA doubling time was significantly increased for those patients taking a pomegranate extract in pill form which is equivalent to eight ounces of pomegranate juice. Now it appears that pomegranate juice may also be effective against breast cancer.
Researchers at the University of California Riverside applied two different concentrations of pomegranate juice (one and five percent) to ER+ and ER- breast cancer cell lines (MCF-7 and MD-MBA-231) as well as to healthy cells (MCF10A). The result: one percent juice completely stopped cancer cell growth in both cancer cell lines, while five percent juice stopped growth and also killed significant portions of the cancer cells. More importantly, even the one percent juice stimulated the expression of genes that suppressed the metastatic process in several ways. First, cancer cell adhesion was significantly increased, which is important in keeping the cancer cells clumped together so they don't invade neighboring tissues. Second, the ability of the cancer cells to migrate was significantly suppressed. Third, the chemical attraction of the cancer cells towards bones (chemotaxis to SDF1-alpha) was markedly decreased (thereby inhibiting bone metastases). Most impressive of all was that none of these effects were seen on the normal breast cells.
In addition to the above effects, the pomegranate juice potently suppressed pro-inflammatory cytokines/chemokines while increasing the levels of anti-inflammatory cytokines. This is important, as increased inflammation is now understood to accelerate the metastatic process, and cancer patients with increased inflammation markers usually have a worse prognosis.
Achieving the one percent concentration of pomegranate juice as used in this study might not be easy since it would translate into a 165 lb (75 kg) woman drinking 24 ounces (three cups) of pomegranate juice, and that's assuming all the active phytochemicals (ellagic acid, luteolin, punicic acid) are absorbed intact and distributed evenly throughout the body (pharmacokinetic studies tell us that isn't the case). However, the success in treating prostate cancer with just one cup daily of pomegranate juice (or equivalent pill) indicates that some level of protection is also likely for breast cancer. If you choose to use pomegranate to fight or avoid breast cancer, you may want to consider adding soy (which contains genistein), or a genistein supplement. That's because a recent study showed that the combination of pomegranate juice and genistein inhibited growth of, and killed, MCF-7 breast cancer cells better than either agent alone.


text:
Q: Adding values to model and passing trough ModelState vaidation I am trying to understand what would be the best approach to my problem. Let's say I have a model like this:
public class Customer
{
   [Key]
   public int Id { get; set; }
   public string Name { get; set; }
   [Required]
   public int StoreId { get; set;}
   [Required]
   public DateTime UpdatedAt {get; set;}
}

and I have an API controller that will have a method like the following to insert a new customer in the database:
public IHttpActionResult Insert(Customer customer)
{
    customer.StoreId = 5; //just for example
    customer.UpdatedAt = DateTime.Now; //again, just as example

    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    db.Customers.Add(customer);
    db.SaveChanges();

    return Ok(customer.Id);
}

Now as you can see in the method, let's assume the StoreId and the UpdatedAt fields won't be included in the original http request posted to this method, because those values need to be calculated and assigned at the server side (let's say basically the client is not supposed to send those values to the server side method). In this case, the ModelState won't be valid anymore, as it is missing two required fields.
One way you can get around it, is to clear the errors on the model state one by one, by doing:
 ModelState["Store.Id"].Errors.Clear();
 ModelState["UpdatedBy"].Errors.Clear();

and then doing the validation, but it doesn't look a good way especially if you have many fields that need to be taken care of on the server side.
What are the better solutions?

A: The good way ? Create a view model specific to the view and have only properties which the view is supposed to provide.
public class CustomerVm
{
   public int Id { get; set; }
   public string Name { get; set; }
}

In your GET action, send an object of this to the view
public ActionResult Edit(int id)  //Or even Create
{
  var vm=new CustomerVm { Id=id, Name="Scott to be edited"};
  return View(vm);
}

Now your view will be strongly typed to this
@model CustomerVm
@using(Html.BeginForm())
{
  @Html.HiddenFor(s=>s.Id)
  @Html.TextBoxFor(s=>s.Name)
  <input type="submit" />
}

and in your HttpPost action, Use the same view model as your method parameter, read the property values and use that
[HttpPost]
public ActionResult Create(CustomerVm model)
{
   var customerEntity = new Customer { Name= model.Name };
   //Stuff server should set goes now
   customerEntity.StoreId = 23;
   customerEntity.UpdatedAt = DateTime.Now;

   db.Customers.Add(customerEntity);
   db.SaveChanges();
   return Ok(customerEntity.Id);
}

redpajama_set_name: RedPajamaStackExchange


Gaithersburg Church of the Nazarene (GCN), 8921 Warfield Road (the corner of Goshen and Warfield roads), will continue its tradition of presenting the Christmas story through a Live Nativity on Sunday, Dec. 16. The outdoor program, which is free, has performances at 5 and 6 p.m.
The program features live animals, costumed performers and a narration of the birth of Jesus Christ. After each performance, attendees are invited inside the church for hot chocolate and cookies.
People of all ages enjoy the program, and children are especially excited to see the animals. Over the years, local farmers have provided lambs, donkeys and goats to lend authenticity to the stable where the Bible says that Christ was born. After each performance, individuals can get a closer look at the animals and may even be able to pet them.
In addition to the Live Nativity, GCN invites the community to morning holiday services on Sundays, Dec. 23 and Dec. 30 at 10 a.m., and a Christmas Eve candlelight service on Monday, Dec. 24 at 7 p.m.
For more information, call 301-330-0366.


Welcome to the home page Stroud and District Canine Society.
The society was founded in 1944 and hosts an open show every year.
The Best In Show judge is David Bell.
G/R 12, Labs 15, Irish Set 18,Pointer 12, AMCocker 3,C/Span 7, GSP 6, English Set 5, HV1, Ret Flatcoat 9, AVNSC Gundog 26, AV Gundog, Gundog Veteran 7.
The President is Diederick Opperman. The Chairman is Mrs Shirley Roe; the Vice Chairman is Mr Rob Brown; the Treasurer is Miss Linda Lane; and the Secretary is Mrs Celia Vines ().
If you are interested, please join the society. Membership fee is only £2.00 single or £3.00 joint membership per year.
In 2019 our show will be on Sunday, 24 November 2019.
We will again have an online entry for this show at Fosse Data.
Here are some sites that may help you and your dog.


text:
Visit London Remembers
www.londonremembers.com
Memorial types
Subject types
Sculpture: Leon Cladel's Ompdrailles
Title: "Le Tombeau des Lutteurs" ("The Fighters' Tomb") or "Mort D'Ompdrailles" ("The Death of Ompdrailles"). Ompdrailles was a triumphant gladiator who, in his old age, committed suicide. This magnificent sculpture depicts the scene where the Northern Bear, Arribial, his old rival, presents the body for the crowd's adoration. The sculptor's name is inscribed on the monument with what looks like "X 92", meaning "October 1892". For a picture from behind see the Leopold II statue in Jardin du Roi. The sculpture was originally tried out at Place Poelaert but it was dwarfed by the Palais de Justice (what wouldn't be?) and was moved to its present location, where it is now dwarfed by the Phénix. Van der Stappen asked Horta to design the base but there were budgetary constraints which meant that the intended red granite was replaced with bluestone, and that Horta's Art Nouveau iron grills were rejected as "hitherto unknown, and somewhat bizarre forms". Jean-Michel Pochet points out that the base is signed "Victor Horta" on the right side, at the bottom.
Inaugurated June 1897.
Site: Leon Cladel's Ompdrailles (1 memorial)
1000, Jardin du Roi, facing the traffic roundabout at top
View this memorial on a map
This section lists the subjects commemorated on the memorial on this page:
Leon Cladel's Ompdrailles
Information Subjects commemorated
Ompdrailles
Fiction, Literature
Léon Cladel
French novelist, born at Montauban (Tarrf-et-Garonne) the son of an artisan. ...
This section lists the subjects who helped to create/erect the memorial on this page:
Information Created by
Victor Horta
Born Ghent, died Brussels. The first, and greatest, Art Nouveau architect. ...
Charles van der Stappen
War dead, Sculpture
This section lists some other interesting Sculptures
Information Other Sculptures
European Year of the Environment
Although the sculpture does not divulge the information we can tell you that ...
The plinth of the sculpture is placed in the middle of a stone which has the ...
Charles Woeste at St Boniface
The monument, dating from 1926, was placed here due to Woeste's role in the c...
Everard t'Serclaes at l'Etoile
Inaugurated 20 July 1902. Julien invited his brother Gustave to do the surro...
Right to a home
Perhaps "A.C.W." are the initials of the sculptor.
Types of Memorials
Fountain/Statue
Mad, bad and dangerous to know.
You have nothing to lose but your chains!
Edith Cavell
Nurse who helped soldiers escape from occupied Belgium during WW1.
Fell in love in Brussels.
© 2021 Brussels Remembers, All Rights Reserved


Self Description: I am a brave woman who is not afraid to make a risk because I think we will never know unless we try. I am very approachable, easy to deal with. I am easy to get along with. I like to learn something new every day. I dream about good life and nice family. I am also family oriented and down to earth person.
Comments: I want to meet a guy who is loving, caring, trustworthy, honest, sincere and knows how to value his words. No age limit as long as he will love and respect me, that's all that matters. I need a man who is serious in terms of handling relationship. A man who keeps everything right.
My additional Photos My additional Photos See My Video Cebu City Tour Photos Meet Kate On The Cebu Tour Write Me Now! Send flowers Call me Now!


Same owner for 50+ years, this ranch home located on a cul-de-sac has hardwood floors and some new windows. Beautiful solarium with ceramic tile floor and gorgeous natural light perfect for plants and relaxing year-round. Breezeway to garage off of kitchen and full basement. Located on a corner lot, with nature surrounding in a great location between Hurley and Rosendale. Owner will consider all offers.


The Constantinople poem from Tango with Cows. Text printed letterpress, wallpaper screenprinted.
Tango with Cows, published in Moscow in 1914, is a key document of Russian futurism, modernist typography, visual poetry, and artist's books. Printed on the back of brightly colored wallpaper, the book combines poetry by Vasily Kamensky with three drawings by Vladimir and David Burliuk. All of the poems are early examples of experimental typography and visual poetry and are set in wide and riotous variety of typefaces. The book is particularly known for Kamensky's six 'ferro-concrete poems,' which entirely dispense with the linear order of text and instead allow the reader to encounter the page spatially and associatively.
The first ever translation, by Eugene Ostashevsky and Daniel Mellis, is in progress. Not only will the playfulness of Kamensky's language be preserved, but also the visual and material qualities of the original. The wallpaper will be remade with silkscreen printing and the typography will be nearly identical to the original. Exact Roman equivalents of the cyrillic typefaces have been identified and digital versions created. The translation will be letterpress printed to more closely match the texture of the letterforms and bound just like the original: side-stapled with glued-on covers. The result will be a volume that gives its readers a linguistic, visual, and haptic experience as close as possible to the 1914 publication. A facsimile and commentary volume will also accompany the translation.
This project has been generously supported by grants from the PEN/Heim Translation Fund, the College Book Art Association, the Community Arts Assistance Program of the City of Chicago Department of Cultural Affairs and Special Events, the Illinois Arts Council, a state agency, and the Interdisciplinary Arts Department of Columbia College Chicago.


text:
HomeBlogIsraeli Forces Detain Jerusalem Governor for 2nd Time (VIDEO)
Israeli Forces Detain Jerusalem Governor for 2nd Time (VIDEO)
November 25, 2018 Blog, News, Videos
Adnan Ghaith, Jerusalem's Palestinian governor. (Photo: via MEMO)
Israeli forces detained the Palestinian Governor of Jerusalem, Adnan Ghaith, on Sunday morning, after raiding his home in the Silwan neighborhood, in occupied East Jerusalem.
Local sources confirmed that following Ghaith's detention, Israeli forces transferred him to an interrogation center in Jerusalem City.
It is noteworthy that this is Ghaith's second detention in less than a month.
Ghaith was summoned several times by Israeli intelligence and security forces, who banned him from entering the West Bank for six months and from traveling outside Palestine.
The ban was ordered under the pretext of incitement and posing a "threat to the security of the State of Israel."
In less than 2 months he was kidnapped 4 times… #Zionist occupation forces have kidnapped today at dawn the #Palestinian Governor of occupied Jerusalem Adnan Ghaith from his home, occupied Palestine, 25 November 2018. pic.twitter.com/NYNi46FvgS
— United for Palestine (@Unity4Palestine) November 25, 2018
Israeli authorities also issued an order banning Ghaith from interacting with a number of Palestinian government officials, whether it is directly or indirectly.
The Palestinian government has decried Israel's arrest of Jerusalem governor Adnan Ghaith in a raid in the occupied city on Sunday. https://t.co/MOlqSfASsW
— ANews (@anewscomtr) November 25, 2018
Secretary-General of the Palestine Liberation Organization's (PLO) Executive Committee, Saeb Erekat, condemned the ban and called upon the international community "to hold Israel accountable for decades of violations of international humanitarian law and international law, mainly the sacred right of self-determination for the people of Palestine."
(Ma'an, PC, Social Media)
Hamas: Normalizing Ties with Israel 'Stab in the Back'
'Our Day': A Song for Gaza
What Does Israel Have against Palestinian Singer, Mohammed Assaf?
October 28, 2020 Articles, Commentary, Editorials
Why does Israel hate Palestinian singer, Mohammed Assaf? On October 16, Avi Dichter, Israeli Member of Parliament from the right-wing Likud Party, announced that Assaf's special permit to enter the occupied Palestinian West Bank would […]
Chile Latest BDS Battleground as Boycotting Israel Ruled Illegal at a Local Level
December 8, 2018 Blog, News
The Chilean National Comptroller ruled this week that it is illegal for local municipalities in the South American country to boycott Israel, wading into an ongoing national debate over the BDS movement. Earlier this summer, […]
Five Jewish Seminary Students Arrested over Palestinian Woman's Killing (VIDEO)
January 7, 2019 Blog, News, Videos
Israel has arrested five Jewish seminary students in the occupied West Bank in connection with a rock attack on a Palestinian car that killed a woman, the Israeli domestic intelligence service said on Sunday. Aisha […]


Travel mugs, brewers and accessories for coffee, tea or soups on the road, at home or office.
Travel Coffee Makers, Tea Brewers, Travel French Press, Thermal Mugs, Beverage Heaters, Travel Bar Sets, by Bodum, Cutter & Buck, Zelco and others. Travel beverage accessories are convenient and can save you a lot of money. They make great gifts too!
Lewis N Clark Deluxe Traveler's Immersion Heater.
BUILT Origami Style Wine Tote...the way to give wine!


text:
The Peerless-Premier Appliance Company is an appliance manufacturer located in Belleville, Illinois, United States, that manufactures kitchen ranges for residential use.

History

1873-1974

The history of Peerless-Premier is closely intertwined with the metal working and foundry industry in Belleville, Illinois. The first stove foundry in Belleville was built in 1873.  By 1915, there were 15 large foundries in Belleville of which seven were exclusively casting stoves. Over time there were new foundries built, foundries that went out of business, others that were merged, or names and assets transferred, making the history of the foundry business in Bellville rather non-linear.

The history of 'Peerless-Premier' can be traced primarily to two companies: The Premier Stove Company and the Peerless Enamel Products Co. although elements of other foundries would also eventually become part of the company.

The Premier Stove Company was founded in Belleville, in 1912 by Maurice G. Klemme and Arthur C. Krebs.  In 1915, the Father and brother of Maurice Klemme, Gottlieb and Alvin, located the Cabirange Stove Manufacturing Company in Belleville.

The Peerless Enamel Products Co. was founded in 1928. This company was exclusively a contract enameling company and did not have a foundry or produce finished stoves.

During World War II, Premier had a contract for bomb casings.

1975-present

In November, 1975, Peerless acquired all capital stock of Premier.  Premier was a wholly owned subsidiary of Peerless until January 1982, when the current company was formed by combining the operating units into one company.

In 1981, Peerless-Premier purchased the Eagle Product line. The Eagle name was first used in Belleville by a foundry built in 1883 by Gottlieb D. Klemme and William Schott. At one time, Eagle had an annual output of over 100,000 ranges and heaters.

In 1990, the company acquired assets of Top Shelf, a manufacturer of stands that allowed a microwave oven to be stacked above a range.

A fire at the Belleville plant in 1997 damaged the enameling furnace forcing the plant to shut down and furlough about 380 workers.  Production resumed after making arrangements with four different porcelainizing suppliers with a planned production levels of 950 ranges per day.

It was reported in 2004 that Peerless-Premier received a grant of $44,000 from the State of Illinois for employee training based on 2003 revenues of $55,555,555.

In 2005 Peerless-Premier laid off 100 of its 250 workers in Belleville, IL and moved the jobs to Clinton, KY citing more favorable wages and competition from Mexico.

By 2013, of the previously numerous stove manufacturers in Belleville, there remained only two descendants: Peerless-Premier and Empire Comfort Systems (formerly Empire Stove).

Current Products

The company currently manufactures a wide range of electric and gas ranges under the Premier name and manufactures a microwave accessory shelf under the  Top Shelf trade name.

Electric ranges are available in 20, 24 and 30" widths. Gas ranges are available in 20, 24, 30 and 36" widths.

There is also a Pro-series line of gas ranges in 20 to 36" widths.

The products are marketed through various retail outlets, including Best Buy, Home Depot, and AJ Madison

Patents and Trademarks

As is common with many corporations, the company applied for and was granted patents for its products over the course of its existence. It has also become the assignee for patents for companies that it has acquired.

Invention Patents

 Sealed burner mounting assembly

Registered Trademarks

 Premier
 Top Shelf

References

External links
 Peerless-Premier

Home appliance brands
Home appliance manufacturers of the United States
Manufacturing companies based in Illinois
Manufacturing companies established in 1912
1912 establishments in Illinois


text:
Q: JOIN TABLES in CODEIGNITER ISSUE I have Fours tables tto join.

My model code:
public function get_all_customers()
{

    $this->db->select('*, customerID, custstr, CONCAT(custstr, '.', customerID) AS custcode')->from('customers');

$this->db->join('deliverydays', 'customers.DeliveryDaysID = deliverydays.DeliveryDaysID', 'left');
$this->db->join('deliveryman', 'customers.DeliveryPersonID=deliveryman.DeliveryManID');
$this->db->join('reference', 'reference.referenceID=customers.referenceID');
$this->db->order_by('customerID','asc');
$query = $this->db->get();

   return $query->result_array();
}

My Controller Code:
$customers=$this->customer_model->get_all_customers();
$data ['customers'] = $customers;
$this->loadViews("customer_view", $this->global,  $data);

View code is:
<?php foreach($customers as $customer){?>

                 <?php echo $customer->custcode;?>
                 <?php echo $customer->Name;?>
                <<?php echo $customer->dmName;?>
                 <?php echo $customer->referenceName;?>

<?php }?>

PROBLEM
Problem is that it is giving errors
Message: Trying to get property of non-object
Where is issue? I an not figure it out.

A: This issue is cause because you returning data from your model as array format result_array() and you retrieving as object in view page.
So Change your model return as following code
return $query->result();

Hope it will solve...


text:
Godzilla Killer – Nissan Pulsar GTi-R
Following in the footsteps of the awesome Nissan Skyline GT-R, the Nissan Pulsar GTi-R (also known as the Nissan Sunny GTi-R on UK spec models) built a huge cult following for this rally born hot hatch with as little as just word of mouth. So much so, that this is also how the Nissan Sunny GTi-R came about, with a campaign from Nissan's UK importers in 1992 that persuaded Nissan to produce the UK spec version. But, the model we're discussing at this point is the more powerful, Japanese specification, the imported Nissan Pulsar GTi-R which originally went on sale in Japan in 1990.
The Nissan Pulsar GTi-R was a pocket rocket, see it as a Japanese city hatchback with a little, well, pretty BIG trick up its sleeve. This little car was blessed to share the Nissan Skyline's phenomenal all-wheel drive and turbocharged attitude.
The Nissan Pulsar GTi-R, as previously said, was a rally born machine, built to take on the giants (or 'Godzilla's if you will) of that era like the Ford Escort RS Cosworth, the Toyota Celica GT-Four, the Mitsubishi Galant VR-4, the Lancia Delta Integrale, etc. Cars which were already established in the rally field.
The Nissan Pulsar GTi-R immediately settled in comfortably amongst this crowd, with very few cars in the same genre being able to show this hot hatch a clean pair of heels. This is all due to the little Pulsar being able to hit 0-60mph in a blistering 5.4 seconds and a top speed of 143mph, and that's from the factory.
This gave it the prowess to hold its own on the road, even when up against the more recent VW's or Audi's. There were very little could get anywhere near the Pulsar GTi-R.
Due to the shared Nissan Skyline All-wheel drive system (although the Pulsar's is a 50/50 mechanical system and not as advanced as the Skyline), the handling on this little rocket is almost second to none. You will get very little understeer, even on wet surfaces, and on dry surfaces you're only likely to hear tyre squeal when cornering hard. This car goes exactly where you point it and will stick to the road like, well you know what sticks to a blanket.
With its rally core, the little Nissan was also a fantastic road car, one of the contributing reasons why Nissan's UK Importers campaigned for a UK spec model.
Out of the factory, the Pulsar GTi-R came with a 2-litre 16v Turbocharged engine (also known as the SR20DET engine, to be later used within both the Nissan Primera and the Nissan 200SX) that pushed around 227bhp through a 5-speed gearbox. Given all of that, tied with the all-wheel drive system just adds to the immense driving pleasure. By no means is this car a pretty car with a prestige badge, some would even pass it by without a second glance, if only it wasn't for that huge bonnet scoop, but that is all part of the appeal to owning a Pulsar GTi-R.
The car was easy to climb in and out of, had ample space for four passengers plus driver, a good-sized boot, a rather inconspicuous ordinary black plastic interior and great all-round visibility. But once you're in the car you'd be quick to forget what this car was built for. Only to be reminded once that accelerator pedal was planted into the carpet.
That being said, I'm pretty sure that the additional gauges, the bucket seats that hug both front passengers and the higher speed increments on the speedometer would give the game away sooner.
One of the most common modifications made by owners is to move the intercooler from its original position on the top of the engine to the front just behind the bumper. This is due to achieving better air flow as it's no longer sitting where all of the hot air and heat from the engine goes. Brake upgrades are also a favourite (the model we photographed had upgrade Brembo callipers) with larger callipers and discs required to stop the ever-increasing engine modifications the Nissan Pulsar GTi-R owners perform. Other modifications come in the forms of aftermarket wheels, suspension upgrades, larger turbo's and clutch upgrades to handle the huge increase in torque.
There is an unfortunate downside to the Nissan Pulsar GTi-R over the UK Sunny variant, and that is that the bodywork is prone to being affected by rust much easier. The common places that rust occurs is around the wheel arches and where exterior parts like the spoiler or wing mirrors are attached to the car.
If you can find one for sale with little rust, snap it up as finding one of these are very few and far between.
To put in perspective, the Nissan Pulsar GTi-R is a Godzilla Killer and there aren't many cars whether it be that BMW, Audi, Ford or Lancia from that era, that can put it in its place.
Words and Photography by Marc Morris of Chilli Custom Automotive Photography
This entry was posted by Lee in Blog, Feature Cars and tagged car club, car show, carporn, carshow, classic car, classic car show, classic cars, drift cars, Godzilla Killer, gti-r, jap, jdm, jdm spec, low, lowered, nissan, nissan pulsar, nissan pulsar gti-r, nissan sunny, nissan sunny gti-r, ohsoretro, old skool, pulsar, race car, retro, retro car, retro cars, slammed, stance, vintage.
← London To Brighton Mini Run 2018
Players Classic 2018 →


text:
Francesca Dego: The Italian Violin
About this playlist
As the birthplace of the violin, Italy has maintained a special connection with the instrument. Local composers Vivaldi and Paganini championed it, and are credited with helping it to achieve iconic status among instruments. This playlist features evergreen interpretations of classics, hidden gems of all eras, and recent reinterpretations of old favourites. I've also included a feast of glorious concertos and chamber music by composers perhaps better known for their operas and symphonic music. Ruggerio Ricci was the first violinist to record Paganini's Caprices, in 1947. My 2012 recording was made on the same violin, a 1734 Guarneri del Gesù. Can you recognise its sound?
Paganini: Violin Concerto No.1 in Eb major, Op. 6
3. Rondo. Allegro spiritoso
Francesca Dego
Vivaldi: Violin Concerto in F minor, Op. 8/4
2. Largo
Berio: 34 Duetti
III. Yossi (Pecker)
Alexandr Bulov
VI. Bruno (Maderna)
Love Theme From "Cinema Paradiso" (Arr. Nikoloz Rachveli for Violin, Cello and Orchestra)
Verdi: I Lombardi alla prima Crociata
Filarmonica della Scala
Verdi: String Quartet in E minor
Quartetto Italiano
Castelnuovo-Tedesco: Violin Concerto No.2, Op. 66
Grave e meditative "Isaiah"
Locatelli: Violin Concerto in D major, Op. 3/1
Capriccio I
Capricci Opus 1 No.4 In C Maestoso
Busoni: Violin Sonata No.2, BV244
I. Langsam -
Per Enoksson
Tartini
Sonata a violino e basso in G Minor "Il Trillo del Diavolo": II. Allegro
Tartini: L'arte del arco
Variations on a theme of Corelli - Arr. Kreisler
Domenico Nordio
Paganini: Violin Concerto No.2 in B minor, Op. 7
3. Rondo à la clochette, 'La campanella'
Salvatore Accardo
Paganini: Grand sonata in A major, Op. 39
Grand Sonata M.S.3 per chitarra e violino - In A Major
Paganini: 24 Caprices, MS25
No. 5 in A Minor: Prelude - Agitato - Finale
Massimo Quarta
Sciarrino: 6 Capricci
No. 1. Vivace
Carolin Widmann
Puccini: Crisantemi, SC65
Crisantemi
Respighi: Sonata for Violin and Piano in B Minor
1. Moderato
Rossini: Sonata for Strings No.3 in C Major
'Figaro', Fantasia for Violin and Piano from 'Il Barbiere di Siviglia'
Viotti: Violin Concerto No. 22 in A Minor, wi 22
Violin Concerto No. 22 in A Minor, WI:22: III. Agitato assai
Gioconda de Vito
Vivaldi: Concerto No. 10 in B minor, Op. 3/10
Vivaldi - Concerto in B Minor for 4 Violins, Op. 3 no.10 RV 580: I Allegro
Viktoria Mullova, Giovanni Antonini, Il Giardino Armonico
Rota: Trio for Flute, Violin and Piano
II. Andante sostenuto
Massimo Palumbo
Busoni: Violin Concerto in D major, BV243
III. Allegro impetuoso
Szymanowski: 3 Paganini Caprices, M42
3. Caprice No. 24
Silvia Colasanti: Il canto di Atropo
Il canto di Atropo
Pergolesi: Violin Concerto in Bb major
Stravinsky: Suite italienne from Pulcinella
Stravinsky: Pucinella - Suite italienne: III. Tarantella
Wolf-Ferrari: Violin Concerto in D major, Op. 26
1. Fantasia


Unlock all functionality of closed mode printing with 3rd party resins!
This universal cartridge enables you to print with any third party resin in closed mode on your Form 2 printer using any of the Formlabs resin profiles. The cartridge enables all functions like the heater, wiper and auto refill. These functions increase part accuracy and quality. The cartridge can be reprogrammed to any resin type and be easily reset when one liter of resin is used(normally, cartridges are disabled after 1 liter).
Why? Resins offered by the manufacturer are expensive($180 per liter and up). There are third party companies like Photocentric 3D, ApplyLabWork and 3DResyns offering high quality and special resins for much less(as low as $60 per liter). However, they can only print in the so called "open mode", which disables the wiper, heater and auto refill of the tank.
Printing quality and accuracy is much higher when printing in closed mode and some resins can only be printed in this mode and will otherwise fail when printing. This cartridge allows you to use the full functionality of the machine with alternative resins.
You can program the cartridge and module using a small tool which needs to run on a Windows PC.
Two different options are offered as international shipping rates for complete cartridges can be very expensive. If you choose option 1, your cartridge is ready to run when it arrives. For option 2, you need to modify an existing cartridge (drilling 3 holes and soldering 2 wires). Simple instructions will be included in the shipping.
Shipping costs There are different shipping rates available. - For the module; you can choose insured shipping or mailbox package. The mailbox package does not contain tracking and is shipped as your own risk. However, there is so far a 99.5% successful delivery. - Ready-to-run cartridge; the price of this option includes the insured shipping upgrade worldwide. Select mailbox shipping at checkout and it will be upgraded to insured shipping by DHL, DPD or PostNL.
The product arrived quite rapidly, the modification of an empty cartridge is very easy. Very useful and reactive communication with seller, now works perfectly. Thanks.
Universal Cart Assembled One Word "Awesome"
Took a while to get to the US but arrived in about 2.5 weeks pretty good considering it's international. Simple to use, really plug and play. Only issue, minor, was I had to change to a different USB port on same computer. Just Download the "Tool" from link provided. Select comm port and your profile and in about 15 seconds you have a fully programmed Resin Tank.
If you get an error on comm port just unplug the USB and reinsert check comm port drop down and select the new one there. Works like a champ. I have reprogrammed the tank about 7 times trying different profiles with different resins, such as Clear with DF Grey to get more detail. Works every time. Takes 15 seconds to reprogram. I am putting about 200 ml in the tank after initially filling the tank. Keeps my printer going all night. You could fill it up if you want. Documentation was good, very simple. Communication with seller has been excellent. LOVE IT! Everything works, heater, wiper, auto fill!
When you go to the URL to download the required software, it is unavailable. A link to an "info" email is available to request the software. Requests receive no response. This product is 100% useless brick without the software, I've been ripped off.
Sorry to hear things are not yet working for you. Please check the URL for the software, it has been updated several days ago with the correct link to an updated version of the software. I could not find a record of your message so please send me the email again with your questions and I'll be happy to answer them.
The product has received a lot of positive feedback since it went online and I'm sure we can make it work for you as well.
We've updated the instructions that are shipped with the product. The error indeed has no effect on the function of the cartridge, we're updating the software so this confusing error does not pop up anymore.


text:
Conversations, Featured, Lit.
The Impossible, The Parallel, The Intimate: A Conversation with Eugene Lim
Eugene Lim's novels tread the line between the hypnotically familiar and the surreptitiously terrifying. His latest novel, The Strangers, follows multiple sets of twins through landscapes alternately recognizable and surreal. Underground film scenes, stand-up comedy, shipborne communities, and totalitarian states all appear, and yet the entire work remains even-tempered and cohesive. As the publisher of Ellipsis Press, Lim has ushered books from the likes of Norman Lock and Eugene Marten into the world. As an admirer of both The Strangers and his earlier novel Fog & Car, I was curious to learn more about Lim's process, and so we checked in earlier this month via email.
Early in The Strangers, there's a long meditation on stand-up comedy. What prompted this as a starting point for the novel?
Comedians are sometimes called stand-up artists. I always liked this idea of the job just being a person standing up and talking. Especially I like that this rather personal, almost quaint occupation survives — and in fact thrives (in comparison to the personal, almost quaint occupation of the novelist) in an era of entertainment defined as visual spectacle. In addition, and maybe more importantly, this novel is structured as a series of monologues. A monologist is a particular type of character, trapped by the sound of their own voice and in the deep gravity well of their own point of view. One goal of the book was to show a long series of these moated, solipsistic monologues (which we sometimes trade with one another and then dignify the exchange with the term conversation) as a rendering of everyone's dazzling alienation. I thought a "stand-up artist" might be a good one to start off such a series.
Your new novel features everything from shipboard life to underground filmmaking circles to life in a totalitarian state. Where did all of these disparate elements come from, and how did you start to bring them together?
When I first moved to New York, in the late 90s, one of the highlights of my week was reading J. Hoberman's film criticism in The Village Voice. He's terrific, a giant, and much of the cinema ideas in the book owe a debt to him. The totalitarian state in the novel probably comes equally from reading about the CIA's so-called "enhanced interrogation techniques" and Abu Ghraib and the incredible kidnapping and escape story of Eun-hee Choi and Sang-ok Shin. I've never been on a cruise ship. I'm not sure where all the elements in the book came from, but I can say that I wanted the sections to be complete and whole in tone and style yet disparate from one another. And then the odd sections are placed next to each other with just a few, vital threads holding the pieces in place.
Both The Strangers and Fog & Car make use of characters with distinctive, stylized names. What attracts you to this approach, and how do you come up with the right name for a particular character?
I'm not sure. In Fog & Car the names refer to a perhaps false dichotomy of styles, and the names of characters given in the chapter titles actually change or evolve, indicating a progression from abstractions to more traditional characterizations. A "Ms. Car" becomes "Sarah Car" and then becomes just "Sarah". The names in The Strangers are less schematically purposed. "Oona" was the first name of the daughter of Eugene O'Neill, a playwright a family story says I was named after. "Noona" also means older sister in Korean. Little factoids coalescing into influence… The idea of our identities in "real life" may seem much more solid compared to ideas of characters in fiction, but that seems less and less true once one starts writing narratives. Tobias sent me this email. Eugene is typing now. All seems clear at first. But when writing a story one realizes how artificial the concept of character can be. You can do a find-and-replace and change occupation, gender, race. Slightly more editing work and you change sense of humor, affect. And there are Twilight Zone implications once you see that these lessons extend from fiction characters to our understandings of so-thought more stable notions of identity. Is the Tobias emailing me the same that I spoke to? Would he be very different if his name were Eugene? Who actually received his email? Paralysis, nausea, the beginnings of religious ritual or game play.
At BookThugNation, you spoke of the novel having more realistic and more surreal plotlines — how do you go about finding the appropriate balance between the two?
Continuity is a (useful) illusion. And I think we experience it something just like that. It's an illusion we allow ourselves to be convinced by. However, semi-secretly from ourselves, parenthetically, we know it's a utility, not reality itself (or if so, then only one aspect of it). I wanted the book to operate somewhat like that as well. Within a section I aimed for it to have its own physics and sense of unity and be an integrated whole. However each would then be placed next to another equally whole narrative. Could they survive the juxtaposition? Lines of poetry can. Elements of a collage can. Our senses of self do.
There's a blurb from Harry Mathews on the back cover of The Strangers, and one of the other blurbs invokes George Perec. Was the Oulipo an influence on this book?
Not directly. I love both of those writers, but this wasn't a novel created by Oulipian-type constraints. Unless it was unconsciously the beautiful "Canada Dry" constraint I recently learned about (from this interview with the novelist Jeremy M. Davies), which is to write "something that reads as though it was written under a constraint, but was not."
Follow Vol. 1 Brooklyn on Twitter, Facebook, Google +, our Tumblr, and sign up for our mailing list.
Eugene LimHarry Mathews


Are you wanting to lend your time to Project Zulu?
Whether you have 5 minutes or 5 hours we want to hear from you. Project Zulu is a small charity so we're always extremely thankful to people who are able to donate any amount of their time to help with our work.
The fastest and easiest way to help Project Zulu is to spread the word. Any sharing of information you do can make a huge difference to our work. Follow us on Facebook, Twitter and Instagram to like and share our posts. Or tell your friends over a traditional cup of tea or a pint.
If you're an expert blogger and poster then why not post about Project Zulu? Either write your own post or use Project Zulu's content to share with your followers. Don't forget to include the all-important links to our website!
Based in Bristol, our small office team always welcome the opportunity to help students or ambitious career types of any age to gain valuable work experience while also supporting the work of Project Zulu. If you'd like to gain experience in the Project Zulu office then please send us your CV and a covering letter.
Open your doors to the Project Zulu Choir. Whilst the choir are on their UK tours we rely on the good will of families based in and around Bristol to welcome the choir into their family and make them feel safe and loved in their new home away from home. We are currently hosting families for our 2016 Tour. For information about our hosting experiences and how to apply see our 'Being a Host' Pack.
Project Zulu have plenty of events throughout the year. Whether during our tours or in the lead up to them These events can only take place with help from volunteers. If you're an expert promoter or a dab hand at organising prior to an event or if you're a happy, smiley person wanting to support on an event day, we want to work with you! See our full list of events to get involved.
When the Project Zulu choir visit the UK it's all hands on deck for the duration of their visit. There is no such thing as too many volunteers! If we're visiting your area and you want to get involved by helping with tickets, organising costumes backstage, helping at meal times or generally lending a helping hand with the day-to-day tour activities then we'd love to hear from you.
To find out more about any of our volunteering opportunities, to sign up or to offer your own ideas it couldn't be easier. Just get in touch and the Project Zulu Team will support you all the way!


Le Cupcakes original designs are protected by the 1968 copyright law.
21st Birthday cake for my niece!, originally uploaded by kylie lambert.
Chocolate mud cupcakes with chocolate ganache icing topped with lace patterned fondant.
A chocolate mud top cutting cake, with chocolate ganach & fondant.
On an original "Le Cupcake" designed tiered stand - only available at "Le Cupcake".
More Cupcakes with sprinkled chocolates, originally uploaded by kylie lambert.
Caramel mud aupccakes with sprinkled chocolate diskon top.
Birthday Cupcakes with chocolate tops!
Male Birthday Cupcakes, originally uploaded by kylie lambert.
Caramel mud cupcakes with chocolates, sprinkles and cachous (silver balls).
More Birthday Cupcakes, originally uploaded by kylie lambert.
Caramel mud cupcakes with meringue buttercream, adorned with funky chocolate bottles.


The death has occurred of Bridget Hancox (née Ryan), Kilmacow, Kilkenny.
Removal from Thompson's Funeral Home, Barrack Street, Waterford on Wednesday at 6.15oc to the Holy Family Church. Requiem Mass on Thursday at 11.00oc followed by burial in St. Mary's Cemetery, Ballygunner, Waterford. Family flowers only, donations to University Hospital Waterford Palliative Home Care Team.
The death has occurred of Brenda Holden, Polerone, Mooncoin, Kilkenny.
Deeply regretted by her loving parents William and Noreen, brothers Jimmy and Michael, sisters Fiona and Sinead, sister-in-law, brothers-in-law, aunts, uncles, nieces, nephews, grandnieces, grandnephews, relatives and friends.
Reposing at Donnacha Doyle & Sons Funeral Home, Grannagh, Kilmacow on Tuesday from 4.00pm with removal at 7.00pm to The Church of the Assumption, Mooncoin. Requiem Mass on Wednesday at 11.00am. Burial after in the New Cemetery.
The death has occurred of Wayne O'Neill, Cloneen, Clogh, Castlecomer, Kilkenny / Athy, Kildare.
(Formerly Townspark, Athy, Co. Kildare) Reposing at Rigney's Funeral Home, Athy tomorrow Tuesday from 10am with Rosary at 8pm. Removal on Wednesday morning to St. Patrick's Church, Clogh for Requiem Mass at 11am. Burial afterwards in St. Michael's New Cemetery, Athy.


Learning a new skill will help you build confidence, fuel creativity, and make you a more interesting person!
Share proof of attempting, completing or mastering the challenges below on Twitter, Facebook, and Instagram with #cornerstonedrone.
Answer the following four questions to see how you compare in the #cornerstonedrone challenge.
Great, this should be right up your alley.
By feeding learner curiosity, 37% of organizations see greater employee productivity.
We get it, learning something new takes time.
Did you complete the drone challenges we gave you?
Nice work, now try flipping your drone!
Oh no, don't give up! Learn how now!
Did you know most employees only have only 1% of the work week available for learning?
What frustrated you the most about the learning a new skill?
We've got your back! Get some help here.
By the way, more than 70% of organizations report that online learning helps boost their competitive edge.
Grab some co-workers and make it a group learning event.
Did you know that building and embracing a learning culture can boost productivity by up to 50%?
Nah, you have always been interesting – but well done!
Did you know 35% of core job skills will change in a mere 3 years?
Great, now share the love and teach a coworker something new.
75% of organizations still employ old-fashioned training approaches that "fall short of empowering employees to acquire skills and take responsibility to improve the work itself.
Fill out the form below and discover the secret to creating an engaging learning experience for your team today!
Great, this should be right up your ally.
Oh no, don't give up and learn how now!
Learn more about how Cornerstone can help your organization achieve its business goals!


This torch-worked and colorful quail is on its way to lifting off into the wild blue yonder. The exhilaration of flight is anticipated in this moment of sprinting. Its chest is white with red and black dots and its wings are swirled with green, turquoise, white and orange. The head is adorned with black and white feathers.


Beautifully remodeled, custom dream estate has too many upgrades to list! Breathtaking designer details include granite counters thru-out, SS built-in appliances, spacious master w/His&Hers walk-ins+dressing areas, luxury bath has walk-in shower w/4 shower heads (2 rain), guest quarters has private entry, recent HVAC, hardwood & tile flooring. 2 out-buildings: 1st is a 2353 sq ft amazing shop & 2nd building has full bath--perfect for guest house or office. Majestic stone gazebo & water feature w/bridge!


Vice President Dr Mahamudu Bawumia has outlined 10 measures introduced by various Ministries, Departments and Agencies over the past nine months in an effort to improve Ghana's business environment.
According to Dr Bawumia, "these reforms are further demonstration of government's commitment to removing the obstacles that have long kept businesses in Ghana from reaching their full potential. We aim to unleash the Ghanaian entrepreneurial spirit and open our doors to the world".
The Doing Business Report has become the global benchmark for measuring how friendly countries are for businesses. The "zero-sum ranking" fosters keen competition among countries as those that don't reform faster than their peers can go down in the ranking even if their business environment does not change.
Ghana ranked 114thin the 2019 ranking, up from 120th in 2018.
"Through our work in advising Government in over 80 countries globally and over 30 in this region, we know that having the commitment at the highest level of leadership is one of most important ingredients of the reform agenda,"said Ronke-Amoni Ogunsulire, IFC Country Manager for Benin, Burkina Faso, Ghana, Niger, and Togo.
"With the appropriate reform structures in place, efficient coordination and accountability mechanisms, Ghana has the right formula to succeed and implementing an investment climate conducive to growth of businesses" she added.


text:
Pricing could strengthen on Mexican limes
Supplies of limes from Mexico are ample right now.
Steven Leal with S&J Distributing in Edinburg, TX says supplies are coming in from multiple regions in Mexico. "The mindset for a lot of people is that limes come from one specific area--Veracruz. That's far from the case right now because at least four to five areas in Veracruz are producing as well as states in the south and on the west coast. There are at least 10 regions in producing fruit right now," he says.
In turn, USDA crossings from Mexico indicate there's a surplus of fruit coming in. "Last week this year there were 420 crossings. This week it's 630 crossings so we've seen an increase," adds Leal.
Sizing however is fairly even. Some areas are coming in with big fruit and others with smaller fruit. "The strength of the market right now is in the middle, the 175-200 sizes. The weakness is on the ends, but more so on the larger fruit--110s, 150 counts. They're on the lower side of the price spectrum," he says.
Holiday demand
At the same time, demand is weak currently as it tends to be post-holiday, whether it's Thanksgiving or Christmas. "I would say from here demand would have to improve. There's too much historical data there showing that Thanksgiving is slow but then it takes off again. Not aggressively, but it's better," Leal says.
He adds though that there is a price disconnect between Mexico and the U.S. currently. "Mexico is stating that the price point on average is hovering around $20 between all sizes. Right now the market is about $2-$4 off from that. Large fruit right now is close to $15-$16 despite reports saying it's $18-$20. There's a disconnect between reporting actual sales and Mexican requests. That's not helping demand either," says Leal.
He does note that likely as demand picks up towards Christmas, there should be an incremental price increase of a few dollars a week over the next two to three weeks.
Steve Leal
S&J Distributing
steve@snjdistributing.com
Publication date: Wed 8 Dec 2021
Author: Astrid Van Den Broek
© FreshPlaza.com
2022-01-20 Putting it all on citrus
2022-01-20 "The difficulties of the Navelina are already being transferred to the rest of the orange varieties"
2022-01-20 Tunisia started exports of Maltese oranges to Marseille
2022-01-20 Small businesses the most affected by price increases
2022-01-20 "Chinese lemons suffer competition from Turkey and Egypt this season"
2022-01-20 China: Tangerines falling both in volume and price
2022-01-20 "We want to revive the consumption of white pomelos in France!"
2022-01-19 Egypt opens new export season of Valencia oranges
2022-01-19 Brussels leaves the control on South African citrus imports demanded by Spain hanging in the air
2022-01-19 Promotional campaigns that are practically below cost should stop
2022-01-19 'The citrus season is a success despite bottlenecks'
2022-01-19 Zimbabwe to enter into citrus export deal with China
2022-01-18 Italy's Limoré and its unexpected international success
2022-01-18 "There's a high demand from China for Egyptian oranges, especially for Valencia"
2022-01-18 Maharashtra government to set up 'citrus estate' in Paithan to provide sweet lime saplings
2022-01-17 Pakistan: This year's production of red blood oranges down in Khanpur
2022-01-17 'Coordinated HLB treatment is essential in California'
2022-01-17 Kenya considers imports of Pakistani kinnows and mangoes
2022-01-17 "As long as Florida's grapefruit production is limited, Spanish and South African grapefruit will be able to coexist"
2022-01-17 "There is a higher demand for clementines than we are able to meet"