fluid-api/src/main/java/com/fluidbpm/program/api/util/elasticsearch/ESFormFieldMappingUtil.java
public void mergeMappingForIndex(
			String indexParam,
			String parentTypeParam,
			Form fluidFormMappingToUpdateParam
	) {
		if(indexParam == null) {
			throw new FluidElasticSearchException(
					"Index name '"+indexParam+"' is invalid.");
		}

		//The Form mapping to update...
		if(fluidFormMappingToUpdateParam == null) {
			throw new FluidElasticSearchException(
					"Form for mapping not set.");
		}

		//Form Type Id...
		if(fluidFormMappingToUpdateParam.getFormTypeId() == null ||
				fluidFormMappingToUpdateParam.getFormTypeId().longValue() < 1) {
			throw new FluidElasticSearchException(
					"Form 'FormType' not set for mapping.");
		}

		String formTypeString =
				fluidFormMappingToUpdateParam.getFormTypeId().toString();

		JSONObject newContentMappingBuilderFromParam =
				fluidFormMappingToUpdateParam.toJsonMappingForElasticSearch();

		//Retrieve and update...
		GetIndexResponse getExistingIndex = this.getOrCreateIndex(indexParam);
		JSONObject existingPropsToUpdate = null;

		for(ObjectCursor mappingKey : getExistingIndex.getMappings().keys()) {
			//Found index...
			if(!mappingKey.value.toString().equals(indexParam)) {
				continue;
			}

			//Found a match...
			Object obj = getExistingIndex.getMappings().get(mappingKey.value.toString());
			if(obj instanceof ImmutableOpenMap) {
				ImmutableOpenMap casted = (ImmutableOpenMap)obj;

				//Type...
				if(casted.containsKey(formTypeString) &&
						casted.get(formTypeString) instanceof MappingMetaData) {
					MappingMetaData mappingMetaData = (MappingMetaData)casted.get(formTypeString);

					try {
						existingPropsToUpdate = new JSONObject(mappingMetaData.source().string());
						break;
					} catch (IOException eParam) {
						throw new FluidElasticSearchException(
								"Unable to retrieve source from 'Mapping Meta-Data'. "+
										eParam.getMessage(),eParam);
					}
				}
			}
		}

		//No mapping for the type create a new one...
		if(existingPropsToUpdate == null) {
			existingPropsToUpdate = new JSONObject();

			existingPropsToUpdate.put(
					ABaseFluidJSONObject.JSONMapping.Elastic.PROPERTIES,
					newContentMappingBuilderFromParam);

			//Set the additional properties...
			this.setAdditionalProps(
					existingPropsToUpdate, parentTypeParam);

			PutMappingRequestBuilder putMappingRequestBuilder =
					this.client.admin().indices().preparePutMapping(indexParam);

			putMappingRequestBuilder = putMappingRequestBuilder.setType(formTypeString);
			putMappingRequestBuilder = putMappingRequestBuilder.setSource(
					existingPropsToUpdate.toString(), XContentType.JSON);

			PutMappingResponse putMappingResponse = putMappingRequestBuilder.get();

			if(!putMappingResponse.isAcknowledged()) {
				throw new FluidElasticSearchException(
						"Index Update for Creating '"+
								indexParam+"' and type '"+
								formTypeString+"' not acknowledged by ElasticSearch.");
			}

			//Creation done.
			return;
		}

		//Update the existing index...
		JSONObject existingPropertiesUpdated =
				existingPropsToUpdate.getJSONObject(formTypeString).getJSONObject(
						ABaseFluidJSONObject.JSONMapping.Elastic.PROPERTIES);

		//Merge existing with new...
		for(String existingKey : existingPropertiesUpdated.keySet()) {
			newContentMappingBuilderFromParam.put(existingKey,
					existingPropertiesUpdated.get(existingKey));
		}

		//Check to see whether there are any new fields added...
		boolean noChanges = true;
		for(String possibleExistingKey : newContentMappingBuilderFromParam.keySet()) {
			if(!existingPropertiesUpdated.has(possibleExistingKey)) {
				noChanges = false;
				break;
			}
		}

		if(noChanges) {
			return;
		}

		//Update the properties to new values...
		existingPropsToUpdate.put(
				ABaseFluidJSONObject.JSONMapping.Elastic.PROPERTIES,
				newContentMappingBuilderFromParam);

		//Set the additional properties...
		this.setAdditionalProps(
				existingPropsToUpdate,
				parentTypeParam);

		//Push the change...
		PutMappingRequestBuilder putMappingRequestBuilder =
				this.client.admin().indices().preparePutMapping(indexParam);

		putMappingRequestBuilder = putMappingRequestBuilder.setType(formTypeString);
		putMappingRequestBuilder = putMappingRequestBuilder.setSource(
				existingPropsToUpdate.toString(), XContentType.JSON);

		PutMappingResponse putMappingResponse = putMappingRequestBuilder.get();

		if(!putMappingResponse.isAcknowledged()) {
			throw new FluidElasticSearchException(
					"Index Update for '"+
							indexParam+"' and type '"+
							formTypeString+"' not acknowledged by ElasticSearch.");
		}
	}
public void mergeMappingForIndex(
			String indexParam,
			String parentTypeParam,
			Form fluidFormMappingToUpdateParam
	) {
		if(indexParam == null) {
			throw new FluidElasticSearchException(
					"Index name '"+indexParam+"' is invalid.");
		}

		//The Form mapping to update...
		if(fluidFormMappingToUpdateParam == null) {
			throw new FluidElasticSearchException(
					"Form for mapping not set.");
		}

		//Form Type Id...
		if(fluidFormMappingToUpdateParam.getFormTypeId() == null ||
				fluidFormMappingToUpdateParam.getFormTypeId().longValue() < 1) {
			throw new FluidElasticSearchException(
					"Form 'FormType' not set for mapping.");
		}

		String formTypeString =
				fluidFormMappingToUpdateParam.getFormTypeId().toString();

		JSONObject newContentMappingBuilderFromParam =
				fluidFormMappingToUpdateParam.toJsonMappingForElasticSearch();

		//Retrieve and update...
		GetIndexResponse getExistingIndex = this.getOrCreateIndex(indexParam);
		JSONObject existingPropsToUpdate = null;

		for(ObjectCursor mappingKey : getExistingIndex.getMappings().keys()) {
			//Found index...
			if(!mappingKey.value.toString().equals(indexParam)) {
				continue;
			}

			//Found a match...
			Object obj = getExistingIndex.getMappings().get(mappingKey.value.toString());
			if(obj instanceof ImmutableOpenMap) {
				ImmutableOpenMap casted = (ImmutableOpenMap)obj;

				//Type...
				if(casted.containsKey(formTypeString) &&
						casted.get(formTypeString) instanceof MappingMetaData) {
					MappingMetaData mappingMetaData = (MappingMetaData)casted.get(formTypeString);

					try {
						existingPropsToUpdate = new JSONObject(mappingMetaData.source().string());
						break;
					} catch (IOException eParam) {
						throw new FluidElasticSearchException(
								"Unable to retrieve source from 'Mapping Meta-Data'. "+
										eParam.getMessage(),eParam);
					}
				}
			}
		}

		//No mapping for the type create a new one...
		if(existingPropsToUpdate == null) {
			existingPropsToUpdate = new JSONObject();

			existingPropsToUpdate.put(
					ABaseFluidJSONObject.JSONMapping.Elastic.PROPERTIES,
					newContentMappingBuilderFromParam);

			//Set the additional properties...
			this.setAdditionalProps(
					existingPropsToUpdate, parentTypeParam);

			PutMappingRequestBuilder putMappingRequestBuilder =
					this.client.admin().indices().preparePutMapping(indexParam);

			putMappingRequestBuilder = putMappingRequestBuilder.setType(formTypeString);
			putMappingRequestBuilder = putMappingRequestBuilder.setSource(
					existingPropsToUpdate.toString(), XContentType.JSON);

			PutMappingResponse putMappingResponse = putMappingRequestBuilder.get();

			if(!putMappingResponse.isAcknowledged()) {
				throw new FluidElasticSearchException(
						"Index Update for Creating '"+
								indexParam+"' and type '"+
								formTypeString+"' not acknowledged by ElasticSearch.");
			}

			//Creation done.
			return;
		}

		//Update the existing index...
		JSONObject existingPropertiesUpdated =
				existingPropsToUpdate.getJSONObject(formTypeString).getJSONObject(
						ABaseFluidJSONObject.JSONMapping.Elastic.PROPERTIES);

		//Merge existing with new...
		for(String existingKey : existingPropertiesUpdated.keySet()) {
			newContentMappingBuilderFromParam.put(existingKey,
					existingPropertiesUpdated.get(existingKey));
		}

		//Check to see whether there are any new fields added...
		boolean noChanges = true;
		for(String possibleExistingKey : newContentMappingBuilderFromParam.keySet()) {
			if(!existingPropertiesUpdated.has(possibleExistingKey)) {
				noChanges = false;
				break;
			}
		}

		if(noChanges) {
			return;
		}

		//Update the properties to new values...
		existingPropsToUpdate.put(
				ABaseFluidJSONObject.JSONMapping.Elastic.PROPERTIES,
				newContentMappingBuilderFromParam);

		//Set the additional properties...
		this.setAdditionalProps(
				existingPropsToUpdate,
				parentTypeParam);

		//Push the change...
		PutMappingRequestBuilder putMappingRequestBuilder =
				this.client.admin().indices().preparePutMapping(indexParam);

		putMappingRequestBuilder = putMappingRequestBuilder.setType(formTypeString);
		putMappingRequestBuilder = putMappingRequestBuilder.setSource(
				existingPropsToUpdate.toString(), XContentType.JSON);

		PutMappingResponse putMappingResponse = putMappingRequestBuilder.get();

		if(!putMappingResponse.isAcknowledged()) {
			throw new FluidElasticSearchException(
					"Index Update for '"+
							indexParam+"' and type '"+
							formTypeString+"' not acknowledged by ElasticSearch.");
		}
	}
Creates / Updates the index {@code indexParam} with mappings
provided in {@code fluidFormMappingToUpdateParam}.


@param indexParam The ElasticSearch index effected.
@param parentTypeParam The {@code _parent} type to be set.
@param fluidFormMappingToUpdateParam The Fluid {@code Form} to be
update.

@see Form
@throws FluidElasticSearchException If validation or acknowledgement problems occur.