All Downloads are FREE. Search and download functionalities are using the official Maven repository.

xy.reflect.ui.control.swing.editor.AbstractEditFormBuilder Maven / Gradle / Ivy

package xy.reflect.ui.control.swing.editor;

import java.util.HashMap;
import java.util.Map;

import javax.swing.JPanel;

import xy.reflect.ui.control.IContext;
import xy.reflect.ui.control.swing.renderer.SwingRenderer;
import xy.reflect.ui.info.IInfo;
import xy.reflect.ui.info.ValueReturnMode;
import xy.reflect.ui.info.field.IFieldInfo;
import xy.reflect.ui.info.filter.IInfoFilter;
import xy.reflect.ui.info.type.ITypeInfo;
import xy.reflect.ui.info.type.factory.EncapsulatedObjectFactory;
import xy.reflect.ui.info.type.source.JavaTypeInfoSource;
import xy.reflect.ui.undo.AbstractSimpleModificationListener;
import xy.reflect.ui.undo.ForwardingModificationStack;
import xy.reflect.ui.undo.IModification;
import xy.reflect.ui.undo.ModificationStack;
import xy.reflect.ui.util.Accessor;
import xy.reflect.ui.util.ReflectionUIError;
import xy.reflect.ui.util.ReflectionUIUtils;
import xy.reflect.ui.util.SwingRendererUtils;

public abstract class AbstractEditFormBuilder {

	protected Object initialObjectValue;
	protected boolean objectValueInitialized = false;
	protected boolean objectValueReplaced = false;
	protected Accessor encapsulatedObjectValueAccessor;

	public abstract SwingRenderer getSwingRenderer();

	public abstract ModificationStack getParentObjectModificationStack();

	public abstract IInfo getCumulatedModificationsTarget();

	public abstract String getCumulatedModificationsTitle();

	public abstract boolean canCommit();

	public abstract IModification createCommitModification(Object newObjectValue);

	public abstract ITypeInfo getObjectDeclaredType();

	public abstract ValueReturnMode getObjectValueReturnMode();

	public abstract boolean isObjectNullValueDistinct();

	public abstract Object getInitialObjectValue();

	public abstract IInfoFilter getObjectFormFilter();

	public abstract boolean isObjectFormExpanded();

	public abstract IContext getContext();

	public abstract IContext getSubContext();

	protected void ensureObjectValueIsInitialized() {
		if (objectValueInitialized) {
			return;
		}
		encapsulatedObjectValueAccessor = new Accessor() {

			Object object = initialObjectValue = getInitialObjectValue();

			@Override
			public Object get() {
				return object;
			}

			@Override
			public void set(Object t) {
				object = t;
				objectValueReplaced = true;
			}

		};
		objectValueInitialized = true;
	}

	public boolean isObjectValueInitialized() {
		return objectValueInitialized;
	}

	public boolean isObjectValueReplaced() {
		return objectValueReplaced;
	}

	public Object getCurrentObjectValue() {
		ensureObjectValueIsInitialized();
		return encapsulatedObjectValueAccessor.get();
	}

	public Object getEncapsulatedObject() {
		ensureObjectValueIsInitialized();
		return getEncapsulation().getInstance(encapsulatedObjectValueAccessor);
	}

	public boolean canReplaceObjectValue() {
		return canCommit();
	}

	protected String getCustomEncapsulationFieldName() {
		return null;
	}

	public String getEncapsulationTypeName() {
		String contextDeclaraion;
		{
			IContext context = getContext();
			if (context == null) {
				contextDeclaraion = "";
			} else {
				contextDeclaraion = "context=" + context.getIdentifier() + ", ";
			}
		}
		String subContextDeclaraion;
		{
			IContext subContext = getSubContext();
			if (subContext == null) {
				subContextDeclaraion = "";
			} else {
				subContextDeclaraion = "subContext=" + subContext.getIdentifier() + ", ";
			}
		}
		return "Encapsulation [" + contextDeclaraion + subContextDeclaraion + "encapsulatedObjectType="
				+ getEncapsulationFieldType().getName() + "]";
	}

	public EncapsulatedObjectFactory getEncapsulation() {
		EncapsulatedObjectFactory result = new EncapsulatedObjectFactory(getSwingRenderer().getReflectionUI(),
				getEncapsulationTypeName(), getEncapsulationFieldType()) {
			@Override
			protected Object[] getFieldValueOptions() {
				return getEncapsulationFieldValueOptions();
			}
		};
		result.setTypeModificationStackAccessible(isEncapsulationTypeModificationStackAccessible());
		result.setTypeCaption(getEncapsulationTypeCaption());
		result.setFieldCaption(getEncapsulatedFieldCaption());
		Map typeSpecificProperties = new HashMap();
		{
			typeSpecificProperties.put(SwingRenderer.CUSTOMIZATIONS_FORBIDDEN_PROPERTY_KEY,
					!isEncapsulationTypeCustomizationAllowed());
			result.setTypeSpecificProperties(typeSpecificProperties);
		}
		String customEncapsulationFieldName = getCustomEncapsulationFieldName();
		{
			if (customEncapsulationFieldName != null) {
				result.setFieldName(customEncapsulationFieldName);
			}
		}
		result.setFieldGetOnly(isEncapsulationFieldGetOnly());
		result.setFieldNullValueDistinct(isObjectNullValueDistinct());
		result.setFieldValueReturnMode(getEncapsulationFieldValueReturnMode());
		result.setFieldFormControlEmbedded(isObjectFormExpanded());
		result.setFieldFormControlFilter(getObjectFormFilter());
		result.setFieldFormControlMandatory(isObjectCustomControlForbidden());

		return result;
	}

	public boolean isObjectCustomControlForbidden() {
		return false;
	}

	protected ValueReturnMode getEncapsulationFieldValueReturnMode() {
		return hasParentObject() ? getObjectValueReturnMode() : ValueReturnMode.DIRECT_OR_PROXY;
	}

	protected Object[] getEncapsulationFieldValueOptions() {
		return null;
	}

	protected boolean isEncapsulationFieldGetOnly() {
		return isInreadOnlyMode() || !canReplaceObjectValue();
	}

	protected boolean isEncapsulationTypeModificationStackAccessible() {
		return !isInreadOnlyMode();
	}

	protected boolean refreshesEditFormOnModification() {
		return isInreadOnlyMode();
	}

	protected boolean isInreadOnlyMode() {
		return hasParentObject() ? !canPotentiallyModifyParentObject() : false;
	}

	protected boolean isEncapsulationTypeCustomizationAllowed() {
		return true;
	}

	public String getEncapsulatedFieldCaption() {
		return "";
	}

	public ITypeInfo getEncapsulationFieldType() {
		ITypeInfo result = getObjectDeclaredType();
		if (result != null) {
			return result;
		}
		ensureObjectValueIsInitialized();
		if (initialObjectValue != null) {
			return getSwingRenderer().getReflectionUI()
					.getTypeInfo(getSwingRenderer().getReflectionUI().getTypeInfoSource(initialObjectValue));
		}
		return getSwingRenderer().getReflectionUI().getTypeInfo(new JavaTypeInfoSource(Object.class));
	}

	public String getEncapsulationTypeCaption() {
		return getEncapsulationFieldType().getCaption();
	}

	public boolean isObjectFormEmpty() {
		Object encapsulatedObject = getEncapsulatedObject();
		ITypeInfo encapsulatedObjectType = getSwingRenderer().getReflectionUI()
				.getTypeInfo(getSwingRenderer().getReflectionUI().getTypeInfoSource(encapsulatedObject));
		IFieldInfo encapsulatedObjectField = encapsulatedObjectType.getFields().get(0);
		if (encapsulatedObjectField.isNullValueDistinct()) {
			return false;
		}
		Object object = getCurrentObjectValue();
		if (object == null) {
			return false;
		}
		ITypeInfo actualObjectType = getSwingRenderer().getReflectionUI()
				.getTypeInfo(getSwingRenderer().getReflectionUI().getTypeInfoSource(object));
		if (!SwingRendererUtils.isFormEmpty(actualObjectType, getObjectFormFilter(), getSwingRenderer())) {
			return false;
		}
		return true;
	}

	public JPanel createForm(boolean realTimeLinkWithParent) {
		Object encapsulated = getEncapsulatedObject();
		JPanel result = getSwingRenderer().createForm(encapsulated);
		if (realTimeLinkWithParent) {
			if (canPotentiallyModifyParentObject()) {
				forwardEditFormModificationsToParentObject(result);
			}
			if (refreshesEditFormOnModification()) {
				refreshEditFormOnModification(result);
			}
		}
		return result;
	}

	protected boolean hasParentObject() {
		return getParentObjectModificationStack() != null;
	}

	public boolean canPotentiallyModifyParentObject() {
		if (!hasParentObject()) {
			return false;
		}
		ensureObjectValueIsInitialized();
		return ReflectionUIUtils.canEditParentObjectValue(
				ReflectionUIUtils.isValueImmutable(getSwingRenderer().getReflectionUI(), initialObjectValue),
				getObjectValueReturnMode(), canCommit());
	}

	protected void refreshEditFormOnModification(final JPanel form) {
		ModificationStack childModificationStack = getSwingRenderer().getModificationStackByForm().get(form);
		childModificationStack.addListener(new AbstractSimpleModificationListener() {
			@Override
			protected void handleAnyEvent(IModification modification) {
				refreshEditForm(form);
			}
		});
	}

	public void refreshEditForm(JPanel form) {
		encapsulatedObjectValueAccessor.set(getInitialObjectValue());
		getSwingRenderer().refreshAllFieldControls(form, false);
	}

	protected boolean shouldAcceptNewObjectValue(Object value) {
		return true;
	}

	protected void forwardEditFormModificationsToParentObject(final JPanel form) {
		Accessor childModifAcceptedGetter = new Accessor() {
			@Override
			public Boolean get() {
				return shouldAcceptNewObjectValue(getCurrentObjectValue());
			}
		};
		Accessor childValueReturnModeGetter = new Accessor() {
			@Override
			public ValueReturnMode get() {
				return getObjectValueReturnMode();
			}
		};
		Accessor childValueReplacedGetter = new Accessor() {
			@Override
			public Boolean get() {
				return (isObjectValueReplaced());
			}
		};
		Accessor commitModifGetter = new Accessor() {
			@Override
			public IModification get() {
				if (!canCommit()) {
					return null;
				}
				return createCommitModification(getCurrentObjectValue());
			}
		};
		Accessor childModifTargetGetter = new Accessor() {
			@Override
			public IInfo get() {
				return getCumulatedModificationsTarget();
			}
		};
		Accessor childModifTitleGetter = new Accessor() {
			@Override
			public String get() {
				return getCumulatedModificationsTitle();
			}
		};
		Accessor parentModifStackGetter = new Accessor() {

			@Override
			public ModificationStack get() {
				ModificationStack result = getParentObjectModificationStack();
				if (result == null) {
					throw new ReflectionUIError();
				}
				return result;
			}
		};
		getSwingRenderer().getModificationStackByForm().put(form,
				new ForwardingModificationStack(getSwingRenderer(), form, childModifAcceptedGetter,
						childValueReturnModeGetter, childValueReplacedGetter, commitModifGetter, childModifTargetGetter,
						childModifTitleGetter, parentModifStackGetter));
	}
}