text:
package pt.ptcris;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.um.dsi.gavea.orcid.client.exception.OrcidClientException;
import org.um.dsi.gavea.orcid.model.common.ElementSummary;
import org.um.dsi.gavea.orcid.model.common.ExternalId;
import org.um.dsi.gavea.orcid.model.common.ExternalIds;
import org.um.dsi.gavea.orcid.model.common.FundingType;
import org.um.dsi.gavea.orcid.model.common.WorkType;
import org.um.dsi.gavea.orcid.model.funding.Funding;
import org.um.dsi.gavea.orcid.model.person.externalidentifier.ExternalIdentifier;
import org.um.dsi.gavea.orcid.model.work.Work;
import org.um.dsi.gavea.orcid.model.work.WorkSummary;

import pt.ptcris.exceptions.InvalidActivityException;
import pt.ptcris.handlers.ProgressHandler;
import pt.ptcris.utils.ExternalIdsDiff;
import pt.ptcris.utils.ORCIDFundingHelper;
import pt.ptcris.utils.ORCIDHelper;
import pt.ptcris.utils.ORCIDWorkHelper;
import pt.ptcris.utils.UpdateRecord;

/**
 *

 * An implementation of the PTCRISync synchronization service based on the
 * version 0.4.3 of the specification, enhanced with minimal quality criteria.
 * This service allows CRIS services to maintain their repositories synchronized
 * with ORCID. This requires the CRIS service to have access to the ORCID Member
 * API.
 *

 *
 *

 * The service has two main functionalities: to keep a set of local activities
 * updated in an ORCID user profile through an
 * {@link #exportBase(ORCIDHelper, List, Collection, boolean, ProgressHandler)
 * export} procedure, and import activities not known locally from the ORCID
 * profile, either through the
 * {@link #importBase(ORCIDHelper, List, Collection, ProgressHandler) import}
 * for completely new activities or through the
 * {@link #importUpdatesBase(ORCIDHelper, List, Collection, ProgressHandler)
 * import} for new information for already known entries. Activities must meet
 * certain quality criteria to be imported (the set of invalid activities can be
 * retrieved as well through
 * {@link #importInvalidBase(ORCIDHelper, List, Collection, ProgressHandler)}.
 *

 *
 *

 * The implementation of the service assumes that the local CRIS communicates
 * the local activities following the established ORCID schema, according to the
 * ORCID Member API 2.0. This uniforms the API and simplifies the
 * synchronization process. The current version focuses on synchronizing
 * research productions and funding entries, which must be encoded as ORCID
 * {@link Work works} and {@link Funding funding} activities.
 *

 *
 *

 * The communication with ORCID is encapsulated in an ORCID {@link ORCIDClient
 * client} that contains information regarding the CRIS Member API and the ORCID
 * profile that is to be managed. An {@link ORCIDHelper helper} provides utility
 * methods for the synchronization of activities.
 *

 *
 *

 * The procedures do not currently consider the contributors (authors) of activities
 * when assessing the quality criteria nor when assessing whether they are
 * up-to-date, as this information is not available in ORCID summaries and would
 * require additional calls to the ORCID API.
 *

 *
 * See https://ptcris.pt/hub-ptcris/.
 */
public final class PTCRISync {

	/**
	 *

	 * Exports a list of local CRIS productions to an ORCID profile and keeps
	 * them up-to-date. This procedure manages the work activities in the ORCID
	 * user profile that are sourced by the CRIS, both previously specified in
	 * the {@code client}.
	 *

	 *
	 *

	 * The procedure detects every CRIS sourced work in the ORCID profile that
	 * matches any local entry that is being exported; if there is no matching
	 * local entry, the ORCID activity is deleted from the profile. Otherwise it
	 * will be updated with the meta-data of one of the matching local entries.
	 * Finally, for local entries without any matching ORCID activity, new ones
	 * are created. The matching is performed by detecting shared
	 * {@link ExternalIdentifier external identifiers} (see
	 * {@link ORCIDWorkHelper#getSelfExternalIdsDiffS(ElementSummary, Collection)}
	 * ).
	 *

	 *
	 *

	 * Activities are only updated if the meta-data is not up-to-date.
	 * Currently, the title, the publication year and the publication are
	 * considered (see {@link ORCIDWorkHelper#isUpToDateE(ElementSummary, ElementSummary)}).
	 *

	 *
	 *

	 * The procedure expects the CRIS service to provide the local works in the
	 * ORCID schema, in particular encoding them as {@link Work works}. Thus,
	 * the meta-data of the CRIS sourced entries in the ORCID profile is exactly
	 * that of the provided local entries that are to be exported. The put-code
	 * of these local entries is assumed to be used as local key identifiers,
	 * and are disregarded during the update of the ORCID profile (new entries
	 * are assigned fresh put-codes and updated entries use the put-code of the
	 * existing ORCID entry).
	 *

	 *
	 *

	 * The provided local activities must pass a quality criteria to be kept
	 * synchronized in ORCID. Currently, this forces the existence of external
	 * identifiers, the title, the publication year and the publication type
	 * (see {@link ORCIDWorkHelper#testMinimalQuality(ElementSummary)}.
	 *

	 *
	 *

	 * The procedure reports the status for each of the input local activities,
	 * identifying them by the provided local put-code, including the ORCID
	 * error if the process failed. See {@link PTCRISyncResult} for the codes.
	 * If the local put-code is empty, returns a default value, which currently
	 * is the put-code remotely assigned by ORCID.
	 *

	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the list of local productions to be exported that should be
	 *            kept synchronized in the ORCID user profile
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the result of the synchronization of each of the provided local
	 *          work
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static Map<BigInteger, PTCRISyncResult<Work>> exportWorks(ORCIDClient client, List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return exportBase(new ORCIDWorkHelper(client), locals, Arrays.asList(WorkType.values()), false, handler);
	}

	/**
	 * @deprecated Replaced by {@link #exportWorks(ORCIDClient, List, ProgressHandler)}
	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the list of local productions to be exported that should be
	 *            kept synchronized in the ORCID user profile
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the result of the synchronization of each of the provided local
	 *          work
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	@Deprecated
	public static Map<BigInteger, PTCRISyncResult<Work>> export(ORCIDClient client, List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return exportWorks(client, locals, handler);
	}

	/**
	 *

	 * Exports a list of local CRIS productions to an ORCID profile and keeps
	 * them up-to-date. This procedure manages the work activities in the ORCID
	 * user profile that are sourced by the CRIS, both previously specified in
	 * the {@code client}.
	 *

	 *
	 *

	 * The procedure detects every CRIS sourced work in the ORCID profile that
	 * matches any local entry that is being exported; if there is no matching
	 * local entry, the ORCID activity is deleted from the profile. Otherwise it
	 * will be updated with the meta-data of one of the matching local entries.
	 * Finally, for local entries without any matching ORCID activity, new ones
	 * are created. The matching is performed by detecting shared
	 * {@link ExternalIdentifier external identifiers} (see
	 * {@link ORCIDWorkHelper#getSelfExternalIdsDiffS(ElementSummary, Collection)}
	 * ).
	 *

	 *
	 *

	 * Activities are always updated, even if already up-to-date (no test is
	 * performed). The caller of this method should guarantee that the input
	 * local productions have been effectively updated, otherwise there will be
	 * unnecessary calls to the ORCID API.
	 *

	 *
	 *

	 * The procedure expects the CRIS service to provide the local works in the
	 * ORCID schema, in particular encoding them as {@link Work works}. Thus,
	 * the meta-data of the CRIS sourced entries in the ORCID profile is exactly
	 * that of the provided local entries that are to be exported. The put-code
	 * of these local entries is assumed to be used as local key identifiers,
	 * and are disregarded during the update of the ORCID profile (new entries
	 * are assigned fresh put-codes and updated entries use the put-code of the
	 * existing ORCID entry).
	 *

	 *
	 *

	 * The provided local activities must pass a quality criteria to be kept
	 * synchronized in ORCID. Currently, this forces the existence of external
	 * identifiers, the title, the publication year and the publication type
	 * (see {@link ORCIDWorkHelper#testMinimalQuality(ElementSummary)}.
	 *

	 *
	 *

	 * The procedure reports the status for each of the input local activities,
	 * identifying them by the provided local put-code, including the ORCID
	 * error if the process failed. See {@link PTCRISyncResult} for the codes.
	 * If the local put-code is empty, returns a default value, which currently
	 * is the put-code remotely assigned by ORCID.
	 *

	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the list of local productions to be exported that should be
	 *            kept synchronized in the ORCID user profile
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the result of the synchronization of each of the provided local
	 *          work
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static Map<BigInteger, PTCRISyncResult<Work>> exportWorksForced(ORCIDClient client, List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return exportBase(new ORCIDWorkHelper(client), locals, Arrays.asList(WorkType.values()), true, handler);
	}

	/**
	 * @deprecated Replaced by {@link #exportWorksForced(ORCIDClient, List, ProgressHandler)}
	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the list of local productions to be exported that should be
	 *            kept synchronized in the ORCID user profile
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the result of the synchronization of each of the provided local
	 *          work
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	@Deprecated
	public static Map<BigInteger, PTCRISyncResult<Work>> exportForce(ORCIDClient client, List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return exportWorksForced(client, locals, handler);
	}

	/**
	 *

	 * Exports a list of local CRIS funding entries to an ORCID profile and
	 * keeps them up-to-date. This procedure manages the funding activities in
	 * the ORCID user profile that are sourced by the CRIS, both previously
	 * specified in the {@code client}.
	 *

	 *
	 *

	 * The procedure detects every CRIS sourced funding activity in the ORCID
	 * profile that matches any local entry that is being exported; if there is
	 * no matching local entry, the ORCID activity is deleted from the profile.
	 * Otherwise it will be updated with the meta-data of one of the matching
	 * local entries. Finally, for local entries without any matching ORCID
	 * activity, new ones are created. The matching is performed by detecting
	 * shared {@link ExternalIdentifier external identifiers} (see
	 * {@link ORCIDFundingHelper#getSelfExternalIdsDiffS(ElementSummary, Collection)}
	 * ).
	 *

	 *
	 *

	 * Activities are only updated if the meta-data is not up-to-date.
	 * Currently, the title, the start year, the funding type and the funding
	 * organization are considered (see
	 * {@link ORCIDFundingHelper#isUpToDateE(ElementSummary, ElementSummary)}).
	 *

	 *
	 *

	 * The procedure expects the CRIS service to provide the local funding
	 * entries in the ORCID schema, in particular encoding them as
	 * {@link Funding funding activities}. Thus, the meta-data of the CRIS
	 * sourced entries in the ORCID profile is exactly that of the provided
	 * local entries that are to be exported. The put-code of these local
	 * entries is assumed to be used as local key identifiers, and are
	 * disregarded during the update of the ORCID profile (new entries are
	 * assigned fresh put-codes and updated entries use the put-code of the
	 * existing ORCID entry).
	 *

	 *
	 *

	 * The provided local activities must pass a quality criteria to be kept
	 * synchronized in ORCID. Currently, this forces the existence of external
	 * identifiers, the title, the start year, the funding type and the funding
	 * organization (see
	 * {@link ORCIDFundingHelper#testMinimalQuality(ElementSummary)}.
	 *

	 *
	 *

	 * A set of funding types can be provided to allow the independent
	 * synchronization of different types of entries. Local and remote
	 * activities outside the provided types are simply ignored (they are not
	 * considered invalid).
	 *

	 *
	 *

	 * The procedure reports the status for each of the input local activities,
	 * identifying them by the provided local put-code, including the ORCID
	 * error if the process failed. See {@link PTCRISyncResult} for the codes.
	 * If the local put-code is empty, returns a default value, which currently
	 * is the put-code remotely assigned by ORCID.
	 *

	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the list of local productions to be exported that should be
	 *            kept synchronized in the ORCID user profile
	 * @param types
	 *            the types of ORCID funding entries that should be considered
	 *            (others are simply ignored).
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the result of the synchronization of each of the provided local
	 *         funding entry
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static Map<BigInteger, PTCRISyncResult<Funding>> exportFundings(ORCIDClient client, List<Funding> locals, Collection<FundingType> types, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return exportBase(new ORCIDFundingHelper(client), locals, types, false, handler);
	}

	/**
	 *

	 * Exports a list of local CRIS activities to an ORCID profile and keeps
	 * them up-to-date. This procedure manages the activities in the ORCID user
	 * profile that are sourced by the CRIS, both previously specified in the
	 * {@code client}.
	 *

	 *
	 *

	 * The procedure detects every CRIS sourced activity in the ORCID profile
	 * that matches any local entry that is being exported; if there is no
	 * matching local entry, the ORCID activity is deleted from the profile.
	 * Otherwise it will be updated with the meta-data of one of the matching
	 * local entries. Finally, for local entries without any matching ORCID
	 * activity, new ones are created. The matching is performed by detecting
	 * shared {@link ExternalIdentifier external identifiers} (see
	 * {@link ORCIDHelper#getSelfExternalIdsDiffS(ElementSummary, Collection)}
	 * ).
	 *

	 *
	 *

	 * The procedure expects the CRIS service to provide the local activities in
	 * the ORCID schema, in particular encoding them as {@link ElementSummary
	 * activities}. Thus, the meta-data of the CRIS sourced entries in the ORCID
	 * profile is exactly that of the provided local entries that are to be
	 * exported. The put-code of these local entries is assumed to be used as
	 * local key identifiers, and are disregarded during the update of the ORCID
	 * profile (new entries are assigned fresh put-codes and updated entries use
	 * the put-code of the existing ORCID entry).
	 *

	 *
	 *

	 * The provided local activities must pass a quality criteria to be kept
	 * synchronized in ORCID (see
	 * {@link ORCIDHelper#testMinimalQuality(ElementSummary)}.
	 *

	 *
	 *

	 * A set of funding types can be provided to allow the independent
	 * synchronization of different types of entries. Local and remote
	 * activities outside the provided types are simply ignored (they are not
	 * considered invalid).
	 *

	 *
	 *

	 * The procedure reports the status for each of the input local activities,
	 * identifying them by the provided local put-code, including the ORCID
	 * error if the process failed. See {@link PTCRISyncResult} for the codes.
	 * If the local put-code is empty, returns a default value, which currently
	 * is the put-code remotely assigned by ORCID.
	 *

	 * *
	 *

	 * Unless {@code forced}, the ORCID activities are only updated if the
	 * meta-data is not up-to-date (see
	 * {@link ORCIDHelper#isUpToDateE(ElementSummary, ElementSummary)}).
	 *

	 *
	 *

	 * The update stage must be two-phased in order to avoid potential
	 * conflicts: the first phase removes external identifiers that are obsolete
	 * from the CRIS sourced activities, so that there are no conflicts with the
	 * new ones inserted in the second phase.
	 *

	 *
	 *

	 * This procedure performs a single GET call to the API to obtain the
	 * summaries and PUT or POST calls for each of the local input activities.
	 * Bulk POST requests are performed when supported. Additionally, DELETE
	 * calls can also be performed. The procedure only fails if the initial GET
	 * fails, otherwise individual failures are reported in the output. No
	 * asynchronous workers are used.
	 *

	 *
	 * @param helper
	 *            helper that encapsulates the ORCID client defining the CRIS
	 *            Member API and user the profile to be managed
	 * @param locals
	 *            the list of local activities to be exported that should be
	 *            kept synchronized in the ORCID user profile
	 * @param types
	 *            the types of ORCID activities that should be considered
	 *            (others are simply ignored).
	 * @param forced
	 *            whether the update of ORCID activities should be forced,
	 *            without testing if up-to-date
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the result of the synchronization of each of the provided local
	 *         activity
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	private static <E extends ElementSummary, S extends ElementSummary, G, T extends Enum<T>> Map<BigInteger, PTCRISyncResult<E>> exportBase(
			ORCIDHelper<E, S, G, T> helper, List<E> locals,
			Collection<T> types, boolean forced, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {

		if (helper == null || locals == null || handler == null)
			throw new IllegalArgumentException("Null arguments.");

		if (types == null)
			types = new HashSet<T>();

		handler.setCurrentStatus("ORCID_SYNC_EXPORT_STARTED");

		List<S> orcids = helper.getSourcedSummaries();

		Map<BigInteger, PTCRISyncResult<E>> result = new HashMap<BigInteger, PTCRISyncResult<E>>();

		// start by filtering local works that do not pass the quality criteria
		handler.setCurrentStatus("ORCID_SYNC_EXPORT_QUALITY",locals.size());
		Set<E> invalids = new HashSet<E>();
		for (int c = 0; c != locals.size(); c++) {
			E local = locals.get(c);

			if (!types.contains(helper.getTypeE(local))) {
				invalids.add(local);
			} else {
				try {
					helper.tryMinimalQualityE(local, locals);
				} catch (InvalidActivityException invalid) {
					invalids.add(local);
					result.put(ORCIDHelper.getActivityLocalKey(local,
							BigInteger.valueOf(c)), PTCRISyncResult
							.<E>invalid(invalid));
				}
			}
			handler.step();
		}
		locals.removeAll(invalids);

		// detect which remote works should be deleted or updated
		handler.setCurrentStatus("ORCID_SYNC_EXPORT_ITERATION",orcids.size());
		List<UpdateRecord<E,S>> toUpdate = new LinkedList<UpdateRecord<E,S>>();
		List<UpdateRecord<E,S>> toUpdateFundedBy = new LinkedList<UpdateRecord<E,S>>();
		for (int c = 0; c != orcids.size(); c++) {
			S orcid = orcids.get(c);

			Map<E, ExternalIdsDiff> worksDiffs = helper.getSelfExternalIdsDiffS(orcid, locals);
			// there is no local work matching a CRIS sourced remote work
			if (worksDiffs.isEmpty()) {
				// TODO: the delete may fail (the result is returned); how to communicate this to the caller?
				helper.delete(orcid.getPutCode());
			}
			// there is at least one local work matching a CRIS sourced remote work
			else {
				boolean isIncluded = false;
				E local = worksDiffs.keySet().iterator().next();
				// if the remote work is not up-to-date or forced updates
				if (forced || !helper.isUpToDateS(local, orcid)) {
					toUpdate.add(new UpdateRecord<E,S>(local, orcid, worksDiffs.get(local)));
					isIncluded = true;
				}
				else
					result.put(ORCIDHelper.getActivityLocalKey(local, BigInteger.valueOf(c)),
							PTCRISyncResult.<E>uptodate());
				locals.remove(local);

				// if the remote work isn't update in what concerns of FundedBy identifiers
				ExternalIdsDiff fundedByExternalIdsDiff = helper.getFundedByExternalIdsDiff(local, orcid);
				if (!isIncluded && (forced || !(fundedByExternalIdsDiff.more.isEmpty() && fundedByExternalIdsDiff.less.isEmpty())) ) {
					fundedByExternalIdsDiff.same.addAll(worksDiffs.get(local).same);
					toUpdateFundedBy.add(new UpdateRecord<E,S>(local, orcid, fundedByExternalIdsDiff));
				}
			}
			handler.step();
		}

		// first update phase, remove spurious identifiers
		handler.setCurrentStatus("ORCID_SYNC_EXPORT_UPDATING_PHASE_1",toUpdate.size());
		for (int c = 0; c != toUpdate.size(); c++) {

			UpdateRecord<E,S> update = toUpdate.get(c);
			// the remote work has spurious external identifiers
			if (!update.eidsDiff.more.isEmpty()) {
				E local = update.preElement;
				ExternalIds weids = new ExternalIds();
				List<ExternalId> ids = new ArrayList<ExternalId>(update.eidsDiff.same);
				ids.addAll(helper.getPartOfExternalIdsE(local).getExternalId());
				ids.addAll(helper.getFundedByExternalIdsE(local).getExternalId());
				weids.setExternalId(ids);
				helper.setExternalIdsE(local,weids);

				PTCRISyncResult<E> res = helper.update(update.posElement.getPutCode(), local);
				result.put(ORCIDHelper.getActivityLocalKey(local, BigInteger.valueOf(c)),res);
			}
			handler.step();
		}

		// Outputs with changes only on "Funded by" identifiers. first update phase, remove spurious identifiers.
		treatOuputWithChangesOnlyOnFundedBy_1Phase(helper, handler, result, toUpdateFundedBy);

		// second update phase, add missing identifiers
		handler.setCurrentStatus("ORCID_SYNC_EXPORT_UPDATING_PHASE_2",toUpdate.size());
		for (int c = 0; c != toUpdate.size(); c++) {

			// the remote work is missing external identifiers or not updated in the 1st phase
			UpdateRecord<E,S> update = toUpdate.get(c);
			if (!update.eidsDiff.less.isEmpty() || update.eidsDiff.more.isEmpty()) {
				E local = update.preElement;
				ExternalIds weids = new ExternalIds();
				List<ExternalId> ids = new ArrayList<ExternalId>(update.eidsDiff.same);
				ids.addAll(update.eidsDiff.less);
				ids.addAll(helper.getPartOfExternalIdsE(local).getExternalId());
				ids.addAll(helper.getFundedByExternalIdsE(local).getExternalId());
				weids.setExternalId(ids);
				helper.setExternalIdsE(local,weids);

				PTCRISyncResult<E> res = helper.update(update.posElement.getPutCode(), local);
				result.put(ORCIDHelper.getActivityLocalKey(local, BigInteger.valueOf(c)),res);
			}
			handler.step();
		}

		// Outputs with changes only on "Funded by" identifiers. second update phase, add missing identifiers
		treatOuputWithChangesOnlyOnFundedBy_2Phase(helper, handler, result, toUpdateFundedBy);

		// add the local works that had no match
		// the progress handler must be moved to the helper due to bulk additions
		handler.setCurrentStatus("ORCID_SYNC_EXPORT_ADDING",locals.size());
		List<PTCRISyncResult<E>> res = helper.add(locals,handler);

		int pad = result.size();
		for (int i = 0; i < res.size(); i++)
			result.put(ORCIDHelper.getActivityLocalKey(locals.get(i), BigInteger.valueOf(pad+i)),res.get(i));

		handler.done();
		return result;
	}

	private static <E extends ElementSummary, S extends ElementSummary, G, T extends Enum<T>> void treatOuputWithChangesOnlyOnFundedBy_2Phase(
			ORCIDHelper<E, S, G, T> helper, ProgressHandler handler, Map<BigInteger, PTCRISyncResult<E>> result,
			List<UpdateRecord<E, S>> toUpdateFundedBy) {
		for (int c = 0; c != toUpdateFundedBy.size(); c++) {

			// the remote work is missing external identifiers or not updated in the 1st phase
			UpdateRecord<E,S> update = toUpdateFundedBy.get(c);
			if (!update.eidsDiff.less.isEmpty() || update.eidsDiff.more.isEmpty()) {
				E local = update.preElement;
				ExternalIds weids = new ExternalIds();
				List<ExternalId> ids = new ArrayList<ExternalId>(update.eidsDiff.same);
				ids.addAll(update.eidsDiff.less);
				ids.addAll(helper.getPartOfExternalIdsE(local).getExternalId());
				weids.setExternalId(ids);
				helper.setExternalIdsE(local,weids);

				PTCRISyncResult<E> res = helper.update(update.posElement.getPutCode(), local);
				result.put(ORCIDHelper.getActivityLocalKey(local, BigInteger.valueOf(c)),res);
			}
			handler.step();
		}
	}

	private static <E extends ElementSummary, S extends ElementSummary, G, T extends Enum<T>> void treatOuputWithChangesOnlyOnFundedBy_1Phase(
			ORCIDHelper<E, S, G, T> helper, ProgressHandler handler, Map<BigInteger, PTCRISyncResult<E>> result,
			List<UpdateRecord<E, S>> toUpdateFundedBy) {
		for (int c = 0; c != toUpdateFundedBy.size(); c++) {

			UpdateRecord<E,S> update = toUpdateFundedBy.get(c);
			// the remote work has spurious external identifiers
			if (!update.eidsDiff.more.isEmpty()) {
				E local = update.preElement;
				ExternalIds weids = new ExternalIds();
				List<ExternalId> ids = new ArrayList<ExternalId>(update.eidsDiff.same);
				ids.addAll(helper.getPartOfExternalIdsE(local).getExternalId());
				weids.setExternalId(ids);
				helper.setExternalIdsE(local,weids);

				PTCRISyncResult<E> res = helper.update(update.posElement.getPutCode(), local);
				result.put(ORCIDHelper.getActivityLocalKey(local, BigInteger.valueOf(c)),res);
			}
			handler.step();

		}
	}

	/**
	 *

	 * Discovers new valid works in an ORCID profile given a set of known local
	 * CRIS productions. Creates creation notifications for each work group at
	 * ORCID (merged into as a single work by the {@link ORCIDWorkHelper helper}
	 * ) without matching local productions (i.e., those without shared
	 * {@link ExternalId external identifiers}). To import updates for works
	 * with shared external identifiers
	 * {@link #importWorkUpdates(ORCIDClient, List, ProgressHandler)} should be
	 * used instead.
	 *

	 *
	 *

	 * Currently, these creation notifications simply take the shape of ORCID
	 * works themselves (representing a merged work group). The group merging
	 * selects the meta-data of the preferred activity and the external
	 * identifiers of the whole group (see
	 * {@link ORCIDWorkHelper#group(Object)}). The selection of the
	 * meta-data from a group could be changed without affecting the correction
	 * of the procedure.
	 *

	 *
	 *

	 * Since the put-code attribute is used as a local key of each activity, it
	 * is null for these creation notifications (and not the put-code of the
	 * remote ORCID activity that gave origin to it). Since only the external
	 * identifiers of the local productions are used to search for matches, the
	 * remainder meta-data of the input local activities could be left null.
	 *

	 *
	 *

	 * ORCID activities without minimal quality are ignored by this procedure.
	 * Currently, the quality criteria forces the existence of external
	 * identifiers, the title, publication year and publication type (see
	 * {@link ORCIDWorkHelper#testMinimalQuality(ElementSummary)}). Works that do
	 * not match the criteria can be imported with
	 * {@link #importInvalid(ORCIDClient, List, ProgressHandler)}. Note that
	 * currently group merging simply collects the meta-data (other than the
	 * external identifiers) from the preferred activity, which is used in the
	 * quality assessment.
	 *

	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local productions
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the list of new valid works found in the ORCID profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws InterruptedException
	 *             if the asynchronous GET process is interrupted
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static List<Work> importWorks(ORCIDClient client, List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, InterruptedException, IllegalArgumentException {
		return importBase(new ORCIDWorkHelper(client), locals, Arrays.asList(WorkType.values()), handler);
	}

	/**
	 *

	 * Discovers new valid funding activities in an ORCID profile given a set of
	 * known local CRIS funding entries. Creates creation notifications for each
	 * funding group at ORCID (merged into as a single funding entry by the
	 * {@link ORCIDFundingHelper helper} ) without matching local entries (i.e.,
	 * those without shared {@link ExternalId external identifiers}). To import
	 * updates for funding activities with shared external identifiers
	 * {@link #importFundingUpdates(ORCIDClient, List, Collection, ProgressHandler)}
	 * should be used instead.
	 *

	 *
	 *

	 * Currently, these creation notifications simply take the shape of ORCID
	 * funding activities themselves (representing a merged activity group). The
	 * group merging selects the meta-data of the preferred activity and the
	 * external identifiers of the whole group (see
	 * {@link ORCIDFundingHelper#group(Object)}). The selection of the meta-data
	 * from a group could be changed without affecting the correction of the
	 * procedure.
	 *

	 *
	 *

	 * Since the put-code attribute is used as a local key of each activity, it
	 * is null for these creation notifications (and not the put-code of the
	 * remote ORCID activity that gave origin to it). Since only the external
	 * identifiers of the local funding entries are used to search for matches,
	 * the remainder meta-data of the input local activities could be left null.
	 *

	 *
	 *

	 * ORCID activities without minimal quality are ignored by this procedure.
	 * Currently, the quality criteria forces the existence of external
	 * identifiers, the title, publication year and publication type (see
	 * {@link ORCIDFundingHelper#testMinimalQuality(ElementSummary)}). Funding
	 * entries that do not match the criteria can be imported with
	 * {@link #importInvalid(ORCIDClient, List, ProgressHandler)}. Note that
	 * currently group merging simply collects the meta-data (other than the
	 * external identifiers) from the preferred activity, which is used in the
	 * quality assessment.
	 *

	 *
	 *

	 * A set of funding types can be provided to allow the independent
	 * synchronization of different types of entries. Local and remote
	 * activities outside the provided types are simply ignored (they are not
	 * considered invalid).
	 *

	 * *
	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local funding entries
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @param types
	 *            the types of ORCID funding activities that should be
	 *            considered (others are simply ignored)
	 * @return the list of new valid funding activities found in the ORCID
	 *         profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws InterruptedException
	 *             if the asynchronous GET process is interrupted
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static List<Funding> importFundings(ORCIDClient client, List<Funding> locals, Collection<FundingType> types, ProgressHandler handler)
			throws OrcidClientException, InterruptedException, IllegalArgumentException {
		return importBase(new ORCIDFundingHelper(client), locals, types, handler);
	}

	/**
	 *

	 * Discovers new valid activities in an ORCID profile given a set of known
	 * local CRIS entries. Creates creation notifications for each activity
	 * group at ORCID (merged into as a single entry by the {@link ORCIDHelper
	 * helper} ) without matching local entries (i.e., those without shared
	 * {@link ExternalId external identifiers}). To import updates for
	 * activities with shared external identifiers
	 * {@link #importBase(ORCIDHelper, List, Collection, ProgressHandler)}
	 * should be used instead.
	 *

	 *
	 *

	 * Currently, these creation notifications simply take the shape of ORCID
	 * activities themselves (representing a merged activity group). The group
	 * merging selects the meta-data of the preferred activity and the external
	 * identifiers of the whole group (see
	 * {@link ORCIDHelper#group(ElementSummary)}). The selection of the
	 * meta-data from a group could be changed without affecting the correction
	 * of the procedure.
	 *

	 *
	 *

	 * Since the put-code attribute is used as a local key of each activity, it
	 * is null for these creation notifications (and not the put-code of the
	 * remote ORCID activity that gave origin to it). Since only the external
	 * identifiers of the local activities are used to search for matches, the
	 * remainder meta-data of the input local activities could be left null.
	 *

	 *
	 *

	 * ORCID activities without minimal quality are ignored by this procedure.
	 * Activities that do not match the criteria can be imported with
	 * {@link #importInvalid(ORCIDClient, List, ProgressHandler)}. Note that
	 * currently group merging simply collects the meta-data (other than the
	 * external identifiers) from the preferred activity, which is used in the
	 * quality assessment.
	 *

	 *
	 *

	 * A set of activity types can be provided to allow the independent
	 * synchronization of different types of entries. Local and remote
	 * activities outside the provided types are simply ignored (they are not
	 * considered invalid).
	 *

	 *
	 *

	 * This procedure performs a GET call to the API to obtain the summaries and
	 * an additional GET call for each activity identified as valid. Bulk GET
	 * requests are performed when supported. The procedure only fails if the
	 * initial GET fails. Asynchronous workers are used for getting the full
	 * activities.
	 *

	 *
	 * @param helper
	 *            helper that encapsulates the ORCID client defining the CRIS
	 *            Member API and user the profile to be managed
	 * @param locals
	 *            the full list of local activities
	 * @param types
	 *            the types of ORCID activities that should be considered
	 *            (others are simply ignored)
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the list of new valid activities found in the ORCID profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws InterruptedException
	 *             if the asynchronous GET process is interrupted
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	private static <E extends ElementSummary, S extends ElementSummary, G, T extends Enum<T>> List<E> importBase(
			ORCIDHelper<E, S, G, T> helper, List<E> locals,
			Collection<T> types, ProgressHandler handler)
			throws OrcidClientException, InterruptedException, IllegalArgumentException {

		if (helper == null || locals == null || handler == null)
			throw new IllegalArgumentException("Null arguments.");

		if (types == null)
			types = new HashSet<T>();

		handler.setCurrentStatus("ORCID_SYNC_IMPORT_STARTED");

		List<S> orcids = helper.getAllTypedSummaries(types);

		Map<BigInteger, PTCRISyncResult<E>> toImport = new HashMap<BigInteger, PTCRISyncResult<E>>();

		// filter novel works only
		List<S> temp = new ArrayList<S>();
		handler.setCurrentStatus("ORCID_SYNC_IMPORT_ITERATION",orcids.size());
		for (int c = 0; c != orcids.size(); c++) {
			S mergedOrcidWork = orcids.get(c);
			Map<E, ExternalIdsDiff> matchingWorks = helper.getSelfExternalIdsDiffS(mergedOrcidWork, locals);
			if (matchingWorks.isEmpty() && helper.testMinimalQuality(mergedOrcidWork).isEmpty()) {
				temp.add(mergedOrcidWork);
			}
			handler.step();
		}

		handler.setCurrentStatus("ORCID_SYNC_IMPORT_GETTING",temp.size());
		helper.getFulls(temp, toImport, handler);

		List<E> results = new ArrayList<E>();
		for (PTCRISyncResult<E> r : toImport.values())
			if (r.act != null)
				results.add(r.act);
			else {
				// TODO: r instanceof OrcidClientException
				// meaning that the GET of a particular work failed
			}

		handler.done();
		return new LinkedList<E>(results);
	}

	/**
	 *

	 * Counts new valid works in an ORCID profile given a set of
	 * known local CRIS productions, following the criteria of
	 * {@link #importWorks(ORCIDClient, List, ProgressHandler)}
	 * but is more efficient, generating less API calls.
	 *

	 *
	 * @see #importWorks(ORCIDClient, List, ProgressHandler)
	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local productions
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the number of new valid works found in the ORCID
	 *         profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static Integer importWorkCounter(ORCIDClient client, List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return importCounterBase(new ORCIDWorkHelper(client), locals, Arrays.asList(WorkType.values()), handler);
	}

	/**
	 * @deprecated Replaced by
	 *             {@link #importWorkCounter(ORCIDClient, List, ProgressHandler)}
	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local productions
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the number of new valid works found in the ORCID profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	@Deprecated
	public static Integer importCounter(ORCIDClient client, List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return importWorkCounter(client, locals, handler);
	}

	/**
	 *

	 * Counts new valid funding activities in an ORCID profile given a set of
	 * known local CRIS funding entries, following the criteria of
	 * {@link #importFundings(ORCIDClient, List, Collection, ProgressHandler)}
	 * but is more efficient, generating less API calls.
	 *

	 *
	 * @see #importFundings(ORCIDClient, List, Collection, ProgressHandler)
	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local funding entries
	 * @param types
	 *            the types of ORCID funding entries that should be considered
	 *            (others are simply ignored)
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the number of new valid funding activities found in the ORCID
	 *         profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static Integer importFundingCounter(ORCIDClient client, List<Funding> locals, Collection<FundingType> types, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return importCounterBase(new ORCIDFundingHelper(client), locals, types, handler);
	}

	/**
	 *

	 * Counts new valid activities in an ORCID profile given a set of known
	 * local CRIS entries, following the criteria of
	 * {@link #importBase(ORCIDHelper, List, Collection, ProgressHandler)}.
	 *

	 *
	 *

	 * This procedure simply performs a GET call to the API to obtain the
	 * summaries, since the remainder meta-data is irrelevant, rendering it more
	 * efficient than
	 * {@link #importBase(ORCIDHelper, List, Collection, ProgressHandler)}.
	 *

	 *
	 * @see #importBase(ORCIDHelper, List, Collection, ProgressHandler)
	 *
	 * @param helper
	 *            helper that encapsulates the ORCID client defining the CRIS
	 *            Member API and user the profile to be managed
	 * @param locals
	 *            the full list of local entries
	 * @param types
	 *            the types of ORCID activities that should be considered
	 *            (others are simply ignored)
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the number of new valid activities found in the ORCID profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	private static <E extends ElementSummary, S extends ElementSummary, G, T extends Enum<T>> Integer importCounterBase(
			ORCIDHelper<E, S, G, T> helper, List<E> locals,
			Collection<T> types, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {

		if (helper == null || locals == null || handler == null)
			throw new IllegalArgumentException("Null arguments.");

		if (types == null)
			types = new HashSet<T>();

		handler.setCurrentStatus("ORCID_SYNC_IMPORT_COUNTER_STARTED");

		List<S> orcids = helper.getAllTypedSummaries(types);

		int counter = 0;

		// filter novel works only
		handler.setCurrentStatus("ORCID_SYNC_IMPORT_COUNTER_ITERATION",orcids.size());
		for (int c = 0; c != orcids.size(); c++) {
			S mergedOrcidWork = orcids.get(c);
			Map<E, ExternalIdsDiff> matchingWorks = helper.getSelfExternalIdsDiffS(mergedOrcidWork, locals);
			if (matchingWorks.isEmpty() && helper.testMinimalQuality(mergedOrcidWork).isEmpty()) {
				counter++;
			}
			handler.step();
		}

		handler.done();
		return counter;
	}

	/**
	 *

	 * Discovers new invalid works (that do not pass the quality criteria, see
	 * {@link ORCIDWorkHelper#testMinimalQuality(ElementSummary)}) in an ORCID
	 * profile given a set of known local CRIS entries, as well as the causes
	 * for invalidity (defined at {@link ORCIDWorkHelper}). Other than the
	 * criteria, the behavior is similar to that of
	 * {@link #importWorks(ORCIDClient, List, ProgressHandler)}.
	 * Note that currently group merging simply collects the meta-data (other
	 * than the external identifiers) from the preferred activity, which is used
	 * in the quality assessment.
	 *

	 *
	 * @see #importWorks(ORCIDClient, List, ProgressHandler)
	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local works
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the list of new invalid works found in the ORCID profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws InterruptedException
	 *             if the asynchronous GET process is interrupted
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static Map<Work, Set<String>> importInvalidWorks(ORCIDClient client,
			List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, InterruptedException, IllegalArgumentException {
		return importInvalidBase(new ORCIDWorkHelper(client), locals,
				Arrays.asList(WorkType.values()), handler);
	}

	/**
	 * @deprecated Replaced by
	 *             {@link #importInvalidWorks(ORCIDClient, List, ProgressHandler)}
	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local works
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the list of new invalid works found in the ORCID profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws InterruptedException
	 *             if the asynchronous GET process is interrupted
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	@Deprecated
	public static Map<Work, Set<String>> importInvalid(ORCIDClient client,
			List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, InterruptedException, IllegalArgumentException {
		return importInvalidWorks(client, locals, handler);
	}

	/**
	 *

	 * Discovers new invalid funding activities (that do not pass the quality
	 * criteria, see
	 * {@link ORCIDFundingHelper#testMinimalQuality(ElementSummary)}) in an
	 * ORCID profile given a set of known local CRIS entries, as well as the
	 * causes for invalidity (defined at {@link ORCIDFundingHelper}). Other than
	 * the criteria, the behavior is similar to that of
	 * {@link #importFundings(ORCIDClient, List, Collection, ProgressHandler)}.
	 * Note that currently group merging simply collects the meta-data (other
	 * than the external identifiers) from the preferred activity, which is used
	 * in the quality assessment.
	 *

	 *
	 * @see #importFundings(ORCIDClient, List, Collection, ProgressHandler)
	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local funding activities
	 * @param types
	 *            the types of ORCID funding activities that should be
	 *            considered (others are simply ignored)
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the list of new invalid funding activities found in the ORCID
	 *         profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws InterruptedException
	 *             if the asynchronous GET process is interrupted
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static Map<Funding, Set<String>> importInvalidFundings(
			ORCIDClient client, List<Funding> locals,
			Collection<FundingType> types, ProgressHandler handler)
			throws OrcidClientException, InterruptedException, IllegalArgumentException {
		return importInvalidBase(new ORCIDFundingHelper(client), locals, types,
				handler);
	}

	/**
	 *

	 * Discovers new invalid activities (that do not pass the quality criteria,
	 * see {@link ORCIDHelper#testMinimalQuality(ElementSummary)}) in an ORCID
	 * profile given a set of known local CRIS entries, as well as the causes
	 * for invalidity (defined at {@link ORCIDHelper}). Other than the criteria,
	 * the behavior is similar to that of
	 * {@link #importBase(ORCIDHelper, List, Collection, ProgressHandler)}. Note
	 * that currently group merging simply collects the meta-data (other than
	 * the external identifiers) from the preferred activity, which is used in
	 * the quality assessment.
	 *

	 *
	 *

	 * This procedure performs a GET call to the API to obtain the summaries and
	 * an additional GET call for each activity identified as invalid. Bulk GET
	 * requests are performed when supported. The procedure only fails if the
	 * initial GET fails. Asynchronous workers are used for getting the full
	 * activities.
	 *

	 *
	 * @see #importBase(ORCIDHelper, List, Collection, ProgressHandler)
	 *
	 * @param helper
	 *            helper that encapsulates the ORCID client defining the CRIS
	 *            Member API and user the profile to be managed
	 * @param locals
	 *            the full list of local activities
	 * @param types
	 *            the types of ORCID activities that should be considered
	 *            (others are simply ignored)
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the list of new invalid activities found in the ORCID profile
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws InterruptedException
	 *             if the asynchronous GET process is interrupted
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	private static <E extends ElementSummary, S extends ElementSummary, G, T extends Enum<T>> Map<E, Set<String>> importInvalidBase(
			ORCIDHelper<E, S, G, T> helper, List<E> locals,
			Collection<T> types, ProgressHandler handler)
			throws OrcidClientException, InterruptedException, IllegalArgumentException {

		if (helper == null || locals == null || handler == null)
			throw new IllegalArgumentException("Null arguments.");

		if (types == null)
			types = new HashSet<T>();

		handler.setCurrentStatus("ORCID_SYNC_IMPORT_INVALID_STARTED");

		List<S> orcids = helper.getAllTypedSummaries(types);

		Map<BigInteger, Set<String>> invalidsToImport = new HashMap<BigInteger, Set<String>>();
		Map<BigInteger, PTCRISyncResult<E>> toImport = new HashMap<BigInteger, PTCRISyncResult<E>>();

		// filter invalid works only
		List<S> temp = new ArrayList<S>();
		handler.setCurrentStatus("ORCID_SYNC_IMPORT_INVALID_ITERATION",orcids.size());
		for (int c = 0; c != orcids.size(); c++) {
			S mergedOrcidWork = orcids.get(c);
			Map<E, ExternalIdsDiff> matchingWorks = helper.getSelfExternalIdsDiffS(mergedOrcidWork, locals);
			Set<String> invalids = helper.testMinimalQuality(mergedOrcidWork);
			invalidsToImport.put(mergedOrcidWork.getPutCode(), invalids);
			if (matchingWorks.isEmpty() && !invalids.isEmpty()) {
				temp.add(mergedOrcidWork);
			}
			handler.step();
		}

		handler.setCurrentStatus("ORCID_SYNC_IMPORT_INVALID_GETTING",temp.size());
		helper.getFulls(temp, toImport, handler);

		Map<E, Set<String>> results = new HashMap<E, Set<String>>();
		for (BigInteger i : toImport.keySet())
			if (toImport.get(i).act != null)
				results.put(toImport.get(i).act, invalidsToImport.get(i));
			else {
				// TODO: r instanceof OrcidClientException
				// meaning that the GET of a particular work failed
			}

		handler.done();
		return results;
	}

	/**
	 *

	 * Discovers updates to existing local CRIS productions in an ORCID
	 * profile. For each work group at ORCID (merged into as a
	 * single activity by the {@link ORCIDWorkHelper helper}), finds matching
	 * local entries (i.e., those with shared {@link ExternalId external
	 * identifiers}) and creates update notifications if not already up to date.
	 * To import works without shared external identifiers,
	 * {@link #importWorks(ORCIDClient, List, ProgressHandler)}
	 * should be used instead.
	 *

	 *
	 *

	 * These update notifications simply take the shape of ORCID activities
	 * themselves (representing a matching activity group). These works contain
	 * only the meta-data that needs to be updated locally. Currently, only the
	 * introduction of newly found external identifiers is considered (i.e.,
	 * those that were already present in the local entry that is being updated
	 * are removed from the returned update). Thus, the remainder fields are
	 * returned null. Since only external identifiers are considered the quality
	 * criteria is not enforced on the remote ORCID activities.
	 *

	 *
	 *

	 * The local entries are tested to be up-to-date by simply checking whether
	 * they contain every external identifiers in the ORCID group (see
	 * {@link ORCIDHelper#hasNewSelfIDs(ElementSummary, ElementSummary)}. Thus
	 * the remainder meta-data of the local entries can be currently left null.
	 *

	 *
	 *

	 * The put-code attribute is used as a local key of each CRIS production.
	 * This means that the returned activities representing the updates have the
	 * put-code of the local entry that is to be updated (and not the put-code
	 * of the ORCID activity that gave origin to it).
	 *

	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local productions
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the list of work updates found in the ORCID profile, pointing
	 *         to the respective local activity
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static List<Work> importWorkUpdates(ORCIDClient client, List<Work> locals, ProgressHandler handler, List<Work> orcids)
			throws OrcidClientException, IllegalArgumentException {
		return importUpdatesBase(new ORCIDWorkHelper(client), locals, Arrays.asList(WorkType.values()), handler, orcids);
	}

	public static List<Work> importWorkUpdates(ORCIDClient client, List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return importUpdatesBase(new ORCIDWorkHelper(client), locals, Arrays.asList(WorkType.values()), handler, new ArrayList<>());
	}

	/**
	 * @deprecated Replaced by {@link #importWorkUpdates(ORCIDClient, List, ProgressHandler)}
	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local productions
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the list of work updates found in the ORCID profile, pointing
	 *         to the respective local activity
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	@Deprecated
	public static List<Work> importUpdates(ORCIDClient client, List<Work> locals, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return importWorkUpdates(client, locals, handler, new ArrayList<>());
	}

	/**
	 *

	 * Discovers updates to existing local CRIS funding activities in an ORCID
	 * profile. For each funding activity group at ORCID (merged into as a
	 * single activity by the {@link ORCIDFundingHelper helper}), finds matching
	 * local entries (i.e., those with shared {@link ExternalId external
	 * identifiers}) and creates update notifications if not already up to date.
	 * To import funding activities without shared external identifiers,
	 * {@link #importFundings(ORCIDClient, List, Collection, ProgressHandler)}
	 * should be used instead.
	 *

	 *
	 *

	 * These update notifications simply take the shape of ORCID activities
	 * themselves (representing a matching activity group). These works contain
	 * only the meta-data that needs to be updated locally. Currently, only the
	 * introduction of newly found external identifiers is considered (i.e.,
	 * those that were already present in the local entry that is being updated
	 * are removed from the returned update). Thus, the remainder fields are
	 * returned null. Since only external identifiers are considered the quality
	 * criteria is not enforced on the remote ORCID activities.
	 *

	 *
	 *

	 * The local entries are tested to be up-to-date by simply checking whether
	 * they contain every external identifiers in the ORCID group (see
	 * {@link ORCIDHelper#hasNewSelfIDs(ElementSummary, ElementSummary)}. Thus
	 * the remainder meta-data of the local entries can be currently left null.
	 *

	 *
	 *

	 * A set of activity types can be provided to allow the independent
	 * synchronization of different types of entries. Local and remote
	 * activities outside the provided types are simply ignored (they are not
	 * considered invalid).
	 *

	 *
	 *

	 * The put-code attribute is used as a local key of each CRIS funding entry.
	 * This means that the returned activities representing the updates have the
	 * put-code of the local entry that is to be updated (and not the put-code
	 * of the ORCID activity that gave origin to it).
	 *

	 *
	 * @param client
	 *            the ORCID client defining the CRIS Member API and user the
	 *            profile to be managed
	 * @param locals
	 *            the full list of local funding activities
	 * @param types
	 *            the types of ORCID funding activities that should be
	 *            considered (others are simply ignored)
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the list of funding updates found in the ORCID profile, pointing
	 *         to the respective local activity
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	public static List<Funding> importFundingUpdates(ORCIDClient client, List<Funding> locals, Collection<FundingType> types, ProgressHandler handler)
			throws OrcidClientException, IllegalArgumentException {
		return importUpdatesBase(new ORCIDFundingHelper(client), locals, types, handler, new ArrayList<>());
	}

	/**
	 *

	 * Discovers updates to existing local CRIS activities in an ORCID profile.
	 * For each activity group at ORCID (merged into as a single activity by the
	 * {@link ORCIDHelper helper}), finds matching local entries (i.e., those
	 * with shared {@link ExternalId external identifiers}) and creates update
	 * notifications if not already up to date. To import activities without
	 * shared external identifiers,
	 * {@link #importBase(ORCIDHelper, List, Collection, ProgressHandler)}
	 * should be used instead.
	 *

	 *
	 *

	 * These update notifications simply take the shape of ORCID activities
	 * themselves (representing a matching activity group). These works contain
	 * only the meta-data that needs to be updated locally, and the remainder
	 * fields are returned null.
	 *

	 *
	 *

	 * The local entries are tested to be up-to-date by simply checking whether
	 * they contain every external identifiers in the ORCID group (see
	 * {@link ORCIDHelper#hasNewSelfIDs(ElementSummary, ElementSummary)}. Thus
	 * the remainder meta-data of the local entries can be currently left null.
	 *

	 *
	 *

	 * A set of activity types can be provided to allow the independent
	 * synchronization of different types of entries. Local and remote
	 * activities outside the provided types are simply ignored (they are not
	 * considered invalid).
	 *

	 *
	 *

	 * The put-code attribute is used as a local key of each CRIS entry. This
	 * means that the returned activities representing the updates have the
	 * put-code of the local entry that is to be updated (and not the put-code
	 * of the ORCID activity that gave origin to it).
	 *

	 *
	 *

	 * This procedure simply performs a GET call to the API to obtain the
	 * summaries, since the remainder meta-data is irrelevant.
	 *

	 *
	 * @param helper
	 *            helper that encapsulates the ORCID client defining the CRIS
	 *            Member API and user the profile to be managed
	 * @param locals
	 *            the full list of local activities
	 * @param types
	 *            the types of ORCID activities that should be considered
	 *            (others are simply ignored)
	 * @param handler
	 *            the progress handler responsible for receiving progress
	 *            updates
	 * @return the list of updates found in the ORCID profile, pointing to the
	 *         respective local activity
	 * @throws OrcidClientException
	 *             if the communication with ORCID fails when getting the
	 *             activities summary
	 * @throws IllegalArgumentException
	 *             if null arguments
	 */
	private static <E extends ElementSummary, S extends ElementSummary, G, T extends Enum<T>> List<E> importUpdatesBase(
			ORCIDHelper<E, S, G, T> helper, List<E> locals,
			Collection<T> types, ProgressHandler handler, List<E> toUpdateFundedBy )
			throws OrcidClientException, IllegalArgumentException {

		if (helper == null || locals == null || handler == null)
			throw new IllegalArgumentException("Null arguments.");

		if (types == null)
			types = new HashSet<T>();

		handler.setCurrentStatus("ORCID_SYNC_IMPORT_UPDATES_STARTED");

		List<S> orcids = helper.getAllTypedSummaries(types);

		List<E> toUpdate = new LinkedList<E>();

		// filter already known works only
		handler.setCurrentStatus("ORCID_SYNC_IMPORT_UPDATES_ITERATION",orcids.size());
		for (int c = 0; c != orcids.size(); c++) {

			S orcid = orcids.get(c);
			Map<E, ExternalIdsDiff> matchingLocals = helper.getSelfExternalIdsDiffS(orcid, locals);
			if (!matchingLocals.isEmpty()) {
				for (E mathingLocal : matchingLocals.keySet()) {
					if (!helper.hasNewSelfIDs(mathingLocal, orcid)) {
						toUpdate.add(helper.createUpdate(mathingLocal, matchingLocals.get(mathingLocal)));
					}

					ExternalIdsDiff fundedByIDs = helper.getFundedByExternalIdsDiff(mathingLocal, orcid);
					if (!fundedByIDs.more.isEmpty()) {
						toUpdateFundedBy.add(helper.createUpdate(mathingLocal, fundedByIDs));
					}
				}
			}

			handler.step();
		}

		handler.done();
		return toUpdate;
	}
}


Do you have an older dog? If so, you may have noticed that the behavioral patterns of your dog have changed over the year. Some such changes are obvious and inevitable due to the aging process (e.g. sleeping more, less tolerant of exercise, etc.).
However, many behavioral problems stem from health issues in aging dogs.
Dogs are very much "creatures of habit," and even slight variations from their normal behavior can indicate health issues.
For example, changes in movement behavior may indicate joint problems, circulatory, ear or eye issues; changes in elimination patterns often indicate kidney, blood sugar, digestive, hormonal or metabolic issues.
If your old dog is suddenly showing signs of aggression, check first to see if he is in pain. See if you can locate the source that causes pain. Also, check to see if your dog is losing his hearing or vision. If you can't find anything out of the ordinary, take him to the vet to find out the underlying cause.
Some older dogs may show typical signs of separation anxiety (e.g. barking, chewing, eliminating in inappropriate places, etc.) when they are left alone.
Older dogs (as in older people!) tend to be more "set in their ways" and have a decreased ability to cope with changes.
Older dogs may have hearing or vision loss. As such, they may feel insecure and unsure of his surroundings.
Separation anxiety in older dogs may be triggered by aging-related health problems. When dogs experience pain or physical discomfort, they tend to become more clingy.
Again, check for any physical conditions (e.g. pain, hearing/vision loss) that may have caused the anxiety to develop. A visit to the vet is necessary if you can't find anything unusual.
In the meantime, try using some natural remedies to calm your anxious old dog.
Just like people, some aging dogs tend to wake up in the middle of the night and cannot go back to sleep! Instead, they may whine to get attention, or pace through the house.
the need to relieve himself more often.
Herbs such as valerian, chamomile, and passionflower can be used to get your dog to sleep deeper. See this page for more information.
Sometimes a dog that has been properly house-trained will start soiling the house here and there when he gets older.
Physical diseases (such as chronic diarrhea, inflammatory bowel disease, diabetes, urinary incontinence, urinary tract infections, bladder stones, bladder infections, kidney problems, or liver disease) can cause a dog to lose control of his bladder or bowel.
Curing or managing the physical disease can solve the house-soiling problem. If you suspect that your aging dog's "accidents" are caused by a physical disease, take him to the vet for a check-up.
Physical pain such as arthritis or loss of vision may hinder the dog from getting up and going outside to relieve himself.
If arthritis or difficult movement is stopping your dog to go outside to relieve himself, consider training him to use an indoor "toilet".
Cognitive problem may also cause house-soiling in older dogs - They simply may not realize what they are doing.
Again, treating and managing the underlying physical ailment can solve this problem, so work together with your vet if your aging dog starts having "accidents" around the house.
Sometimes an aging dog that shows some of the behavioral changes mentioned above does not have any other health problems (such as arthritis or hearing loss).
The dog may just be suffering from a disorder known as canine cognitive dysfunction (doggie dementia). According to a study, around 60% of dogs 10 years and older has this disorder.
Confusion or disorientation (e.g. The dog may not be able to find his way home from his own back yard).
Aggression because the dog cannot recognize his friends or family members.
Restlessness, circling, stiffness or weakness.
Sleeplessness or a change in sleeping patterns.
Visit this page for more information on this topic.
As you can see, many older dogs change their behaviors due to physical problems. It is important that we take our older dog to be examined by a veterinarian if he shows some of the above behavioral changes.
Older dogs tend to get stressed out more easily, so try to eliminate as many stress-causing factors as possible around the house.
Keep to a daily routine and avoid irregular lifestyle. Older dogs feel less anxious if they know what to expect.
As older dogs may have hearing or vision loss, do not move too quickly into their space or make sudden movements or loud noise that might startle them.
Never get angry or punish an older dog for accidentally soiling the house.
Be observant and watch your dog closely. Note on a calendar any changes in behavior that deviate from the norm.
By noting any behavioral changes of your aging dog, you can greatly help your vet determine whether your dog has any health issues, and if so, which body organ or system may be compromised.
Finally, be very patient, understanding, and loving to your older dog!


A Product is a financial instrument or investment.
The Service is what we do with those products.
When you set out to build a custom home, your builder does not randomly go out and start buying various building products (lumber, brick, concrete, windows, etc ...) and start assembling them. If your home is built this way it would not withstand the strong winds, heavy downpours and cold weather that life throws your way. Your builder requires a Blue Print, a detailed plan that determines the best building block components and shows exactly how they all come together to create a strong stable structure that will protect and provide for you and your family for a lifetime.
The same is true when building your financial house. There are thousands of financial products available but without a "blue print", or what we refer to as Financial Plan, you are likely to build something that will not withstand all the storms and demands that life brings your way.
We custom build your Financial Plan to pursue the goals that are most important to you. We find financial products best suited for you based on your goals and objectives to build your plan, manage the implementation and assembly for your benefit. With you, we review it on a regular basis to make sure there are no cracks in the foundation or leaks in the roof and if we see a big storm coming then we prepare accordingly to ride it out. Your Financial Plan is a living document that needs to adapt to life's changes and surprises and we walk with you every step of the way.


If we need ship time, will there be a dedicated vessel in the Gulf for the purposes of this research, or do we need to negotiate with individual ship operators to ascertain availability?
You need to negotiate with individual ship operators and provide the information and costs in your Consortium proposal and budget. At the time of Consortia selection and execution of grants, the Research Board may facilitate coordination of ship use to maximize effectiveness for research and simultaneously reduce costs to the extent practicable (without jeopardizing achieving the objectives of the funded research).


And Terpenes Are In the Air!
Aloha friends! Long time no blog. We apologize for the unexpected lack of a post last week. Fortunately, I can assure you we put that energy into upgrades and preparations as we ramp up for the first Alaska summer with legal cannabis! As spring time fast approaches in Fairbanks you can always feel the resulting spring in the people's step. That spring is approximately 50% relief that the 6 months of cold and darkness is finally over and 50% anticipation of the amazing summers we are blessed with every year as residents of Alaska. I feel like there is an extra boost of eagerness this year and spring hasn't even really started yet. My guess is that it has something to do with a new industry that generates an easily measurable degree of interest and excitement (and tax dollars to help our city and state). Summer will ignite that industry with a dab torch! We will start to see the full potential of what legal cannabis has to offer and the positive effects it can have on so many different levels such as generating tax revenue for our City and State and driving tourism to boost the local economy. From the recreational perspective, we will start to see higher quality bud and new types of products in the retail shops such as ours. There will be more events such as the Cannabis Classic (we'll get to this early next week right here on the PakaBlog) that support the growth of the industry. C'mon summer hurry it up already!
"Terpenes interact with the endocannabinoid system in a similar way to cannabinoids. When inhaled or ingested, the terpenes act as an assistant to cannabinoids as they work to penetrate the blood-brain barrier. Myrcene, for example, is known to increase cell permeability allowing for faster absorption of THC and other cannabinoids.
Smell: Musky, cloves, earthy, herbal with notes of citrus and tropical fruit.
Associated effects in body: Antioxidant, anti-carcinogenic; good for muscle tension, pain, insomnia, depression.
Also Found In: Mango, lemongrass, thyme, hops.
That's all we got for you PakaBloggers today. We are working on adding a section to our website to include recent terpene profiles of our strains when the rest of the results come back from testing soon. Next week we will have some new product reveals that we are anxious to share with you. We will also be discussing the Cannabis Classic and how to nominate/vote on your favorite cannabis retail related awards so check back soon. We hope you made it into Pakalolo this weekend to get your hands on some of the latest "Pakalolo Grown" harvest while it lasts. See you next time, mahalo!
Next Next post: Strain Drop Saturday!


The Spireites headed to Boundary Park knowing that today's result could confirm their top six finish – a potentially remarkable achievement for a club who were only promoted to the third tier last season.
They were looking to continue an incredible run that had seen then earn seven wins and a draw in the last eight games. Victory this afternoon, along with a Rochdale defeat at Gillingham, would see the play offs secured.
This afternoon's hosts Oldham Athletic had little to play for other than pride as a disappointing season came to a conclusion. The Latics sat in 14th place and were without a victory in five.
It was Chesterfield, in their white away strip, who got my first ever match at Boundary Park underway.
The sun was shining in Lancashire. One side of the ground being closed due to the building of a new stand meant the atmosphere lacked a little at times, and this wasn't helped by a drab first half of football that offered little to shout about for either set of supporters.
Oldham were the first to force a goalkeeper into action when Connor Brown fired towards to bottom corner, but Tommy Lee always looked comfortable in keeping it out.
Rhys Murphy then had a decent chance for the Latics as he picked up a botched Tendayi Darikwa clearance in front of goal. The striker's first effort was blocked by Ian Evatt, but on the rebound he connected with a bicycle-kick attempt that made the goalkeeper work.
After a slow start for the Spireites, manager Paul Cook decided to make a tactical switch, replacing Dan Gardner with target man forward Armand Gnanduillet.
But the 6ft4 Frenchman struggled to make a real impact – a couple of weak efforts as much as he could muster up in the first 45 minutes.
The second half seemed to continue in a similar vain as neither side was able to create many clear-cut opportunities.
The news of Gillingham taking the lead against Rochdale brought a cheer from the away fans, who knew that a single goal for their side would now do it!
Chesterfield responded to the crowds roars by bombarding the Latics area with corners. Evatt came close to scoring when he connected with Roberts' driven ball, but Joel Coleman got down well to keep it out.
Then, with less than 10 minutes to go, the Spireites were gifted a golden opportunity.
Roberts' cross was flicked on by Sam Clucas and smashed off the post. With the keeper in no man's land, the ball fell to Gnanduillet, whose task looked simple. However, the forward could only rifle his effort over the bar to th dismay of the supporters.
While the result meant the play offs were not yet secure, it was still a major step towards this feat. An eight-point gap now appeared between Chesterfield and Rochdale, with the Spireites only having two games to play. If Rochdale fail to beat Leyton Orient in their game in hand on Tuesday night, then a top six spot will be secured!


text:
Made in Cro
Daily Travel Updates
Click for latest flights, border, corona news
CROMADS
Authentic Croatian experiences, 365 days a year
Total Croatia Tourism Portal
All your travel info in one place
From Two Swimming Pools to 156, is Imotski Becoming the Croatian Tuscany?
By Daniela Rogulj 31 July 2017
In 2007, there were five or six holiday homes and two swimming pools in the Imotski region. Today, there are 156 holiday homes and swimming pools.
In the mid-90s, Imotski construction entrepreneur Šime Medvidović would look at his deserted, abandoned, and neglected hometown on the northwestern edge of the town of Imotski. After setting focus on a native stone house that was covered in brambles and blackberry, an idea would spark that would transform Imotski 20 years later, reports Jutarnji List on July 30, 2017.
Not only did Medvidović thoroughly renovate the house and garden in Imotski, but he also built a swimming pool, right there, in the middle of the karst, in a village that was abandoned and had no water. Though his neighbors, friends, and tourists thought his plan was completely absurd, Medvidović was determined to explain, at least to those that wanted to listen, the many advantages of these old abandoned villages.
"You will see that one-day Imotski and Inland Dalmatia will flourish and that rural tourism will be the primary driver of the development of the Imotski region. This is the place for guests looking for peace, clean air, healthy food, relaxation, walking, cycling and hiking trails. After all, in these old stone houses, it is necessary to set up all the facilities that people from western countries are accustomed to. Therefore, there will be jacuzzis, wine cellars, gyms, and, of course, swimming pools. This is the most important object," Šime said.
More than 20 years after the construction of the first swimming pool, Imotski, from Biorina in the west to Slivna in the east, was invaded by blue rectangles - swimming pools. Many old houses have been renovated and many new holiday homes have been built. Specifically, more than 160 of them, in rural areas, in the town of Imotski. And, as expected, almost all of these facilities have pools. The people of Imotski took out loans, dug into their family safes, borrowed money, and some even used state support for construction.
In 2007, there were five or six holiday homes and two swimming pools in the Imotski region, with only 2,600 overnights achieved that year. Last year, there were 47,100 overnight stays and 130 holiday homes and 124 swimming pools built.
This year, there are 156 holiday homes, with approximately just as many swimming pools. Forecasts firmly suggest that this year, the number of overnight stays in the area could exceed 70,000, and by 2018 the number should reach 100,000, with the addition of some twenty new pools next to renovated or newly built homes.
"The expansion of swimming pool construction is something new in Imotski, but it is certainly worth it," said the director of the Tourist Board of Imotski, Luka Kolovrat. People realized that by building the tunnel of Sv. Ilija through Biokovo, guests from any corner of Imotski could reach the sea at the Makarska Riviera in less than twenty minutes - and that's when tourism finally happened.
"You know, I was building a pool next to my house, advertised it through an agency, and then something incredible happened," said Marko Mendeš, a renter from Imotski. "Foreign guests, especially those from Western European countries, were delighted. They simply have no interest in going to the sea and that 20 minutes of driving. They enjoy the peace that is guaranteed here, the beautiful nature. They walk around the surrounding hills all day, bathe in the pool and they are happy. Although it's not in the description of their stay program, we serve them domestic meals. They are delighted. This year I will be full for a dozen weeks and I will earn enough to properly repay the home renovation loan and build a pool, settle down, and still have something left. I think that Imotski and Inland Dalmatia, in general, has an incredible chance in this tourist offer."
Most holiday renters have had similar experiences. "My guests were from Poland and when they rated the quality, cleanliness, comfort, location, amenities, staff, value for their money, and pool, my holiday home got all 10/10," said Ivana Bikić from the village of Bikić in the municipality of Zagvozd.
Imotski is experiencing a tourist boom. This is not only visible from the number of overnight stays and reservations for the following season, but from the reactions of the holiday guests.
"This is my first time in Croatia. We chose Imotski because we went through the details of what it was like, we looked at the house for rent, and we decided to come," explains a French tourist who was with six other family members on vacation in Cista Velika.
"My whole family is fascinated by what we have experienced. Listen, we come from Lyon, from central France, and we know what the interior is like. But here you have everything that characterizes the space away from the sea, and yet everything is so close. What is particularly delightful about it is the nature and peace, the silence to rest your eyes and soul. We swim in the pool and walk for hours. If there were more restaurants to try, that would make it even better. We can't even spend the money we had planned for the vacation," they added.
In Imotski, tourism simply happened - it did not grow organically. Apart from fantastic facilities, pools, gymnasiums, trails, and good food, the off-season offer is at zero. There are no domestic and small taverns; there are no restaurants, diners, souvenir shops, and no cultural and sporting events. Guests who actually want to spend money have no place to do it.
Apart from excellent results in the summer season and announcements for even better years to come, the hospitality industry remains stagnant. Homes and pools, however many, will have to support the enogastronomic offer. While this is an ideal opportunity to connect with small family OPGs that produce healthy and fresh food, what are the other plans, if any, to make the most out of the tourism offer?
What will happen next? Only time will tell.
Translated from Jutarnji List
Tagged under: inland dalmatia imotski swimming pools imotski luka kolovrat
2021 Sinj Advent Program is Here!
Alka Knights Society Invited to Macron Meeting at in Zagreb!
Inland Sinj to Island Hvar - Collaboratively Celebrating Croatia's Cultural Riches and Natural Diversity
Croatian Ecological Awareness has Highest Growth in Central Europe
Croatian Taxi Market to be Regulated by Constitutional Court
Croatian Youth Leaving Country Because They Can't Leave Parental Home?
Ex IT Wizz Zeljko Brigljevic Creates Furnace That Breaks Down Plastic
Total Financial Assets of Croatian Households Reach €77 Billion
ZSE Indices Continue Moving Upward, Hit New Records
Water Polo World League: Croatia Tops Greece 12:11
Finance Ministry Issues HRK 1.7bn in Treasury Bills
Croatia logs 7,548 new COVID cases, 55 deaths
Real Estate Prices Continue to Rise in Croatia
Azil Dumovec: Where Zagreb Bus Drivers Take Their Injured Owls
International Food in Zagreb: Fuego Fresh Latin Food
© 2020 Total Croatia News. All Rights Reserved.Development by Exabyte

redpajama_set_name: RedPajamaCommonCrawl


Needless to say the bond shared between a brother and sister is as close as it can get. So much that you share everything from food, music and movies to clothes and pillows. When you're young and have something too personal to discuss, your sibling takes precedence over parents or friends. But life is not always the way it ought to be. Distance changes the equation often. Marriage and career drift you away from your responsibilities as a brother or sister. Rakhi is the time to make amends. It is the time to relive old memories, of you growing up together, of the two of you sharing your lives such that you were meant to inseparable. Let distance not hinder your Rakhi celebrations – while you know your brother best, we know the market trends best.
Let us together work out the best gift for your sibling.
A Rakhi is a quintessential gift to have as part of your celebrations. It is a sacred thread that is tied by a sister on her brother's wrist. Our collection comprises of diamond pendant rakhis – with the diamond signifying a letter, preferably one that your brother's name starts with. It adds a personal touch to the message that a Rakhi sends out. Besides that we have some beautifully ornamented Rakhis with pearls, beads and flower designs. Most of our Rakhis come with coconut, rice & kumkum and packed in attractive boxes.
Rakhi Thaalis, being the most popular gifts, are well-liked by customers. Our thaalis come in bright colours and are decorated in many different ways – sometimes with pearls and golden lace borders, at other times with red & yellow flowers. Our thaali collection is extremely popular with our customers abroad and have always been an instant hit with sisters who would like to gift their brothers in a traditional way. Sometimes when you're living very far away from your brother and would like to complete all rituals in a conventional manner, a Rakhi Thaali is the best gift you can gift as it contains roli and chawal along with a wonderfully decorated rakhi platter.
When you have a message to send to your sibling alongside your Rakhi gift or a favourite picture to print on a memorabilia, you should definitely check out our personalized gifts section. Cherish memories of the past by embedding your personalized picture on a fridge magnet, keychain, mug or calendar. Personalized gifts ooze warmth and affection that surpasses no other gift.
Men are more fascinated by fashion accessories and grooming items. Our Rakhi thaali and sweets collection has been carefully chosen to meet demands of our customers looking for gifts for their brothers. If your brother has a sweet tooth, you could try amongst our Bikanervala or Halidram sweet packs. Also popular is Kaleva's mithai packs, with kaju barfi dominating most. Whether you're looking to send wallets, belts or perfumes to your brother – we've got an exclusive gift collection only for him.
Sisters love to be pampered. Rakhi is the best time of the year to make your sister feel special. With Raksha Bandhan comes the big responsibility to understand what gifts your sister loves most. Our vast experience in selecting gift items for Rakhi explains that women typically love to receive apparel, chocolates, perfumes and handbags as gifts. During Rakhi when expectations are higher, you have to be your best for your sister. Buy her a leather handbag or spoil your sister with a sweet perfume, but most importantly let her know that you love her with a gift. It is important to gift at the right time, and if your sister is punctual – how about just gifting her an elegant watch during Rakhi. After all, nothing is more important than time-management.


Though out the project the students worked closely with the departments. They held interviews with the employees and had a brainstorm session in the Safari Park.
And yesterday, the 21st of June, in the Africa Club located in the Holiday Park with a beautiful lake side view it was finally time to present the findings.
All groups presented their findings which sometimes led to interesting discussions with the managers of the several departments. But these discussions showed that the students knew what they were talking about.
We are glad that we got the opportunity to work on this project. And this project was the last Attractions and Theme Parks Management project of the current third year students. In september they will start with their minor. But, as always, we will keep you updated!


text:
pCloudy attains Leadership in Global Mobile App Testing Space
It has become increasingly important for companies to ensure that applications are tested for quality, performance, compatibility
Photo Credit : Reuters,
pCloudy First Indian Company to Establish Data Centre in Australia
UST Global partners with mobile app testing platform pCloudy
Growing exponentially over the last decade, the mobile app testing market has been driven by highest standards of mobile apps in terms of both quality and deployment speeds. To meet the futuristic demands of dynamic technology changes, it has become increasingly important for companies to ensure that applications are tested for quality, performance, compatibility and other characteristics.
Leading such disruption in the global app testing market, pCloudy has been extending test and automation coverage over multiple real devices to its customers on different parameters. Taking a leap forward, pCloudy, the largest cloud platform to test mobile apps on real devices, has crossed a milestone of 50,000 users on its platform in just two years and is growing further at an aggressive rate. The company is poised towards achieving industry leadership in the years to come.
Avinash Tiwari, co-founder and director, pCloudy, said: "At pCloudy, we have disrupted the mobile app testing space in many major markets including US, Australia, India and few European countries. We have been helping large enterprises to reduce cycle times, improve the quality of apps and get the mobile app testing framework right. Reaching a global customer base of 50,000 over the last two years is a testimony to our customers' trust in our app testing solutions.
"Multiple factors, which have attributed to our success, include investment in deep technology like AI in the early part of our product journey, building a 24/7 customer support and working extensively with our customers during their evaluation and onboarding stages."
pCloudy Global Mobile App Testing Space


text:
William McGee Works 1954-1977
April 21st, 2013	| Published in April 2013 | 3 Comments
By Emil Robinson
William McGee Works 1954-1977 just closed at the University of Cincinnati's Reed Gallery. The show gave a wonderful introduction to a talented artist who had the good and bad fortune to be making work alongside some of the most important American painters in history. McGee was a painter of courageous ability and range. The show at UC featured everything from calligraphic paintings from the 1950s reminiscent of Franz Kline, to Gorky and Dibenkorn like abstractions of the 1960s, and finally large scale minimal works that nod to Barnett Newman and Mark Rothko. The work is all better than competent. McGee was a prominent figure in his time, showing alongside his more illustrious colleagues at commercial galleries and serious museums. How fortunate to have a local collector in Larry Huston who purchased a large chunk of the estate of this underappreciated artist.
Earlier works such as this untitled acrylic painting from 1954 show McGee making quick intuitive moves. His comfort and freedom are clear in the variety and naturalism of his decisions. Take the thin slice of paint that arcs in from the left to serve as a fulcrum for the denser shingle like marks underneath. This design has the inevitable feeling that is the result of an open mind and probing eye.
William McGee – Untitled 1954
In contrast to the earlier "action" based abstracts McGee was under deep control and reserve in his large color field works. The best of these works have the unmoored spatial sensation that can accompany minimal paintings of this large scale. We are immediately involved with works of this size as we find ourselves trying on the space like a new room in our house. In works such as Victoria from 1970, the architectural certainty of vertical elements give our psyches a symbolic boundary, yet in this work the majority of the canvas is an open field: an open window? A void? The two far edges of the canvas are reasserted with two handsome wobbly verticals. We want something to hold onto spatially but we are left to drift in the vacuum created by the overwhelming field of blue. The feeling is one of air rushing past us towards the opening to fill it.
William McGee "Victoria" 1970 72″x91″
It was a great decision on the part of curators Aaron Cowan and Vincent Sansalone to put this show together because of its educational value. For the general public, this show provided an art history lesson as we saw McGee working out the picture making problems that captivated the art world for some 40 years. For the art historian, painter or connoisseur, this show provided an opportunity to learn a new name through a powerful body of work. It is seldom that we see such a complete survey of an artist that is little known today. It is refreshing to see works that are of such a high quality, yet on the verge of being relegated to the dustbin of history. More galleries and museums should expand our family of great artists instead of contributing to the same incestuous line-up of household names.
Larry Huston says:
April 23rd, 2013at 8:41 am(#)
Emil, you "get it". Very thoughtful review. Thank you for your insights. It "expanded my view" of this work as well.
Daniel Brown says:
April 23rd, 2013at 12:09 pm(#)
Editor's note: the author and his brother are the owners of the paintings, which they lent for this show.
Jesse McGee says:
April 26th, 2013at 9:28 pm(#)
Every word perfect.


Chapelton it is to stock and distribute International Paper's Speed-E offset printing paper product into the UK market.
With its renowned sheet quality, the Speed-E offset range is designed for high quality printing applications and various types of high volume converting jobs.
Speed-E offset is also said to provide very good colour print reproduction, especially in high volume print work.
Whilst it is suitable for all types of converting work, typical end use applications for Speed-E offset are; Promotional materials and inserts, reports, catalogues, posters, transactional & transpromotional printing, training materials, newsletters, leaflets, manuals and forms.
Manufactured at International Paper's Kwidzyn mill in Poland, Speed-E offset also boasts high environmental qualities, being both Forest Stewardship Council (FSC) accredited and EU Ecolabel certified, due to the sourcing of the material used in its production originating from sustainably managed sources.
Speed-E will be available from the Kent-based speciality paper and cartonboard supplier in reels, and in four grammage weights, ranging from; 70, 75, 80 to 90gsm.
Chapelton were confirmed as a distributor for International Paper in 2014, following International Paper's completion of its $60m modernisation project at the Kwidzyn mill, where the Speed-E product is produced.


This is to notify that the entrance exam of Ph. D. candidates for the academic year 2075 will be held on Bhadra 18, 2075 at 11:00 am in ICTC Building at IOE.
For the detail information, you can visit IOE Planning Division or can contact at 977-1-5522292 from 10:00 am to 5:00 pm.


text:
High-Res Photo
Amy represents the 48th Legislative District, which includes parts of Bellevue, Redmond, Kirkland and all of Clyde Hill, Medina, Yarrow Point and Hunts Point. Prior to coming to the Legislature in 2019, Amy served on the Kirkland City Council from 2009 – 2014, until she was selected by her colleagues to serve as Mayor of Kirkland from 2014 – 2019.
As mayor, Amy raised Kirkland's profile in local, regional and statewide initiatives. Her leadership includes transportation infrastructure and strategic economic development projects which resulted in the revitalization of the Totem Lake Business District. She championed mandatory inclusion of affordable housing in residential developments and enacted an ordinance against source of income-based discrimination for families in Section 8 housing programs.
Her additional accomplishments at the City of Kirkland include gun safety reforms, environmental protections, developing the Cross Kirkland Corridor, and proclaiming Kirkland's commitment as a welcoming, safe, and inclusive community for all.
Amy was born in Oregon and studied and practiced law in Australia before moving to Kirkland in 2005 with her husband, Jim. Together they own and operate a successful local auto business. She has a consistent record of successfully leading complex organizations through change, including serving as chief financial officer for companies with annual revenues exceeding $150 million for nearly 20 years.
As a cancer survivor and someone who received help during difficult times in her life, Amy is committed to giving back. Amy served as the president of the Sound Cities Association (SCA) in 2018. She received the Advocacy All-Star Award from the Association of Washington Cities (AWC) in 2015 and was awarded Elected Official of the Year from the Alliance of Eastside Agencies in 2013.
Amy lives in Kirkland with her husband. She is a proud stepmother of three and legal guardian to her nephew.