ISIS-1359: enables autocomplete methods to be annotated as @Programmatic. This is done by working directly with the Java reflection API, rather than through the Isis metamodel.
In addition: - adds metamodel validation to ensure that the specified repository and method exist. - updates documentation. Project: http://git-wip-us.apache.org/repos/asf/isis/repo Commit: http://git-wip-us.apache.org/repos/asf/isis/commit/fbf5a459 Tree: http://git-wip-us.apache.org/repos/asf/isis/tree/fbf5a459 Diff: http://git-wip-us.apache.org/repos/asf/isis/diff/fbf5a459 Branch: refs/heads/master Commit: fbf5a459da5dddebbe49bd33093ab120cfa6c2d5 Parents: f58e72e Author: Dan Haywood <d...@haywood-associates.co.uk> Authored: Thu Jun 23 15:00:04 2016 +0100 Committer: Dan Haywood <d...@haywood-associates.co.uk> Committed: Thu Jun 23 15:00:04 2016 +0100 ---------------------------------------------------------------------- ...ant-DomainObject_autoCompleteRepository.adoc | 22 +++- .../autocomplete/AutoCompleteFacetAbstract.java | 116 ++++--------------- .../DomainObjectAnnotationFacetFactory.java | 100 ++++++++++++++-- ...oCompleteFacetForAutoCompleteAnnotation.java | 32 +---- ...oCompleteFacetForDomainObjectAnnotation.java | 38 ++---- .../scalars/reference/ReferencePanel.java | 29 +++-- 6 files changed, 163 insertions(+), 174 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/isis/blob/fbf5a459/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject_autoCompleteRepository.adoc ---------------------------------------------------------------------- diff --git a/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject_autoCompleteRepository.adoc b/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject_autoCompleteRepository.adoc index 54d035c..850d0c8 100644 --- a/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject_autoCompleteRepository.adoc +++ b/adocs/documentation/src/main/asciidoc/guides/_rgant-DomainObject_autoCompleteRepository.adoc @@ -6,7 +6,8 @@ -The `autoCompleteRepository()` attribute nominates a single method on a domain service as the fallback means for lookuping up instances of the domain object using a simple string. +The `autoCompleteRepository()` attribute nominates a single method on a domain service as the fallback means for +looking up instances of the domain object using a simple string. For example, this might search for a customer by their name or number. Or it could search for a country based on its ISO-3 code or user-friendly name. @@ -68,11 +69,28 @@ where in this case `findByName` might be an existing action already defined: @DomainService(natureOfService=VIEW_MENU_ONLY) public class Customers { @Action(semantics=SemanticsOf.SAFE) - List<Customer> findByName(@ParameterLayout(named="name") String name); + public List<Customer> findByName( + @Parameter(minLength=3) // <1> + @ParameterLayout(named="name") + String name); ... } ---- +<1> end-user must enter minimum number of characters to trigger the query +(As of `1.13.0-SNAPSHOT`), the autocomplete action can also be a regular method, annotated using xref:rgant.adoc#_rgant_Programmatic[`@Programmatic`]: + +[source,java] +---- +@DomainService(natureOfService=VIEW_MENU_ONLY) +public class Customers { + @Programmatic + public List<Customer> findByName( + @Parameter(minLength=3) + String name); + ... +} +---- [IMPORTANT] http://git-wip-us.apache.org/repos/asf/isis/blob/fbf5a459/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/autocomplete/AutoCompleteFacetAbstract.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/autocomplete/AutoCompleteFacetAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/autocomplete/AutoCompleteFacetAbstract.java index dd0bfef..3e9bc47 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/autocomplete/AutoCompleteFacetAbstract.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/autocomplete/AutoCompleteFacetAbstract.java @@ -19,6 +19,7 @@ package org.apache.isis.core.metamodel.facets.object.autocomplete; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collections; import java.util.List; @@ -32,58 +33,40 @@ import org.apache.isis.core.metamodel.deployment.DeploymentCategory; import org.apache.isis.core.metamodel.facetapi.Facet; import org.apache.isis.core.metamodel.facetapi.FacetAbstract; import org.apache.isis.core.metamodel.facetapi.FacetHolder; -import org.apache.isis.core.metamodel.facets.ImperativeFacet; -import org.apache.isis.core.metamodel.facets.actions.action.invocation.ActionInvocationFacet; import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet; import org.apache.isis.core.metamodel.facets.param.autocomplete.MinLengthUtil; import org.apache.isis.core.metamodel.services.ServicesInjector; import org.apache.isis.core.metamodel.services.publishing.PublishingServiceInternal; -import org.apache.isis.core.metamodel.spec.ActionType; -import org.apache.isis.core.metamodel.spec.ObjectSpecification; -import org.apache.isis.core.metamodel.spec.feature.Contributed; -import org.apache.isis.core.metamodel.spec.feature.ObjectAction; -import org.apache.isis.core.metamodel.specloader.SpecificationLoader; public abstract class AutoCompleteFacetAbstract extends FacetAbstract implements AutoCompleteFacet { - public static Class<? extends Facet> type() { return AutoCompleteFacet.class; } - private final Class<?> repositoryClass; - private final String actionName; - private final DeploymentCategory deploymentCategory; - private final SpecificationLoader specificationLoader; private final AuthenticationSessionProvider authenticationSessionProvider; private final AdapterManager adapterManager; private final ServicesInjector servicesInjector; + private final Class<?> repositoryClass; + private final Method repositoryMethod; /** * lazily populated */ private Integer minLength; - /** - * cached once searched for - */ - private ObjectAction repositoryAction; - private boolean cachedRepositoryAction = false; - - private boolean cachedRepositoryObject = false; - private Object repository; - public AutoCompleteFacetAbstract( final FacetHolder holder, final Class<?> repositoryClass, - final String actionName, + final Method repositoryMethod, final ServicesInjector servicesInjector) { super(type(), holder, Derivation.NOT_DERIVED); + this.repositoryClass = repositoryClass; - this.actionName = actionName; + this.repositoryMethod = repositoryMethod; + this.deploymentCategory = servicesInjector.getDeploymentCategoryProvider().getDeploymentCategory(); - this.specificationLoader = servicesInjector.getSpecificationLoader(); this.adapterManager = servicesInjector.getPersistenceSessionServiceInternal(); this.servicesInjector = servicesInjector; this.authenticationSessionProvider = servicesInjector.getAuthenticationSessionProvider(); @@ -94,20 +77,20 @@ public abstract class AutoCompleteFacetAbstract extends FacetAbstract implements final String search, final InteractionInitiatedBy interactionInitiatedBy) { - cacheRepositoryAndRepositoryActionIfRequired(); - if(repositoryAction == null || repository == null) { - return Collections.emptyList(); - } - - final ObjectAdapter repositoryAdapter = adapterManager.getAdapterFor(repository); - final ObjectAdapter searchAdapter = adapterManager.adapterFor(search); - final ObjectAdapter resultAdapter = getPublishingServiceInternal().withPublishingSuppressed(new PublishingServiceInternal.Block<ObjectAdapter>() { @Override public ObjectAdapter exec() { - return repositoryAction.execute(repositoryAdapter, null, new ObjectAdapter[] { searchAdapter}, - interactionInitiatedBy); + final Object list = invoke(); + return adapterManager.adapterFor(list); + } + + private Object invoke() { + try { + return repositoryMethod.invoke(getRepository(), search); + } catch (IllegalAccessException | InvocationTargetException e) { + return Collections.emptyList(); + } } }); @@ -119,8 +102,11 @@ public abstract class AutoCompleteFacetAbstract extends FacetAbstract implements final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(resultAdapter); final Iterable<ObjectAdapter> adapterList = facet.iterable(resultAdapter); - return ObjectAdapter.Util.visibleAdapters( - adapterList, interactionInitiatedBy); + return ObjectAdapter.Util.visibleAdapters(adapterList, interactionInitiatedBy); + } + + private Object getRepository() { + return servicesInjector.lookupService(repositoryClass); } private PublishingServiceInternal getPublishingServiceInternal() { @@ -128,70 +114,14 @@ public abstract class AutoCompleteFacetAbstract extends FacetAbstract implements } - private void cacheRepositoryAndRepositoryActionIfRequired() { - if(!cachedRepositoryAction) { - cacheRepositoryAction(); - } - if(!cachedRepositoryObject) { - cacheRepositoryObject(); - } - } - @Override public int getMinLength() { if(minLength == null) { - final Method method = findMethod(); - minLength = MinLengthUtil.determineMinLength(method); + minLength = MinLengthUtil.determineMinLength(repositoryMethod); } return minLength; } - private Method findMethod() { - if(!cachedRepositoryAction) { - cacheRepositoryAction(); - } - - final ActionInvocationFacet invocationFacet = repositoryAction.getFacet(ActionInvocationFacet.class); - if(invocationFacet instanceof ImperativeFacet) { - return findMethod((ImperativeFacet) invocationFacet); - } - final Facet underlyingFacet = invocationFacet.getUnderlyingFacet(); - if(underlyingFacet instanceof ImperativeFacet) { - return findMethod((ImperativeFacet) underlyingFacet); - } - return null; - } - - private Method findMethod(final ImperativeFacet invocationFacet) { - final ImperativeFacet facet = invocationFacet; - final List<Method> methods = facet.getMethods(); - for (Method method : methods) { - final ImperativeFacet.Intent intent = facet.getIntent(method); - if(intent == ImperativeFacet.Intent.EXECUTE) { - return method; - } - } - return null; - } - - private void cacheRepositoryAction() { - try { - final ObjectSpecification repositorySpec = specificationLoader.loadSpecification(repositoryClass); - final List<ObjectAction> objectActions = - repositorySpec.getObjectActions( - ActionType.USER, Contributed.EXCLUDED, ObjectAction.Filters.withId(actionName)); - - repositoryAction = objectActions.size() == 1? objectActions.get(0): null; - } finally { - cachedRepositoryAction = true; - } - } - - private void cacheRepositoryObject() { - repository = servicesInjector.lookupService(repositoryClass); - cachedRepositoryObject = true; - } - protected DeploymentCategory getDeploymentCategory() { return deploymentCategory; } http://git-wip-us.apache.org/repos/asf/isis/blob/fbf5a459/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java index 9ff076e..d35a85a 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/DomainObjectAnnotationFacetFactory.java @@ -53,6 +53,7 @@ import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract; import org.apache.isis.core.metamodel.facets.MethodFinderUtils; import org.apache.isis.core.metamodel.facets.PostConstructMethodCache; import org.apache.isis.core.metamodel.facets.object.audit.AuditableFacet; +import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet; import org.apache.isis.core.metamodel.facets.object.callbacks.CreatedLifecycleEventFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.callbacks.LoadedLifecycleEventFacetForDomainObjectAnnotation; import org.apache.isis.core.metamodel.facets.object.callbacks.PersistedLifecycleEventFacetForDomainObjectAnnotation; @@ -85,6 +86,7 @@ import org.apache.isis.core.metamodel.spec.ObjectSpecId; import org.apache.isis.core.metamodel.spec.ObjectSpecification; import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorComposite; import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorForDeprecatedAnnotation; +import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorForValidationFailures; import org.apache.isis.core.metamodel.specloader.validator.MetaModelValidatorVisiting; import org.apache.isis.core.metamodel.specloader.validator.ValidationFailures; import org.apache.isis.core.metamodel.util.EventUtil; @@ -100,6 +102,7 @@ public class DomainObjectAnnotationFacetFactory extends FacetFactoryAbstract private final MetaModelValidatorForDeprecatedAnnotation boundedValidator = new MetaModelValidatorForDeprecatedAnnotation(Bounded.class); private final MetaModelValidatorForDeprecatedAnnotation immutableValidator = new MetaModelValidatorForDeprecatedAnnotation(Immutable.class); private final MetaModelValidatorForDeprecatedAnnotation objectTypeValidator = new MetaModelValidatorForDeprecatedAnnotation(ObjectType.class); + private final MetaModelValidatorForValidationFailures autoCompleteInvalid = new MetaModelValidatorForValidationFailures(); @@ -189,28 +192,103 @@ public class DomainObjectAnnotationFacetFactory extends FacetFactoryAbstract void processAutoComplete(final ProcessClassContext processClassContext) { final Class<?> cls = processClassContext.getCls(); - final DomainObject domainObject = Annotations.getAnnotation(cls, DomainObject.class); final FacetHolder facetHolder = processClassContext.getFacetHolder(); // check for the deprecated @AutoComplete annotation first - final AutoComplete annotation = Annotations.getAnnotation(processClassContext.getCls(), AutoComplete.class); - Facet facet = autoCompleteValidator.flagIfPresent( - AutoCompleteFacetForAutoCompleteAnnotation.create(annotation, facetHolder, - servicesInjector - )); + final AutoComplete autoCompleteAnnot = Annotations.getAnnotation(cls, AutoComplete.class); + Facet facet = autoCompleteValidator.flagIfPresent(createFor(facetHolder, autoCompleteAnnot, cls)); // else check from @DomainObject(auditing=...) if(facet == null) { - facet = AutoCompleteFacetForDomainObjectAnnotation.create( - domainObject, facetHolder, - servicesInjector - ); + final DomainObject domainObjectAnnot = Annotations.getAnnotation(cls, DomainObject.class); + facet = createFor(domainObjectAnnot, facetHolder, cls); } // then add FacetUtil.addFacet(facet); } + private AutoCompleteFacet createFor( + final FacetHolder facetHolder, + final AutoComplete annotation, + final Class<?> cls) { + if(annotation == null) { + return null; + } + + final Class<?> repositoryClass = annotation.repository(); + final String actionName = annotation.action(); + + if(!isServiceType(cls, "@AutoComplete", repositoryClass)) { + return null; + } + final Method repositoryMethod = findRepositoryMethod(cls, "@AutoComplete", repositoryClass, actionName); + if(repositoryMethod == null) { + return null; + } + return new AutoCompleteFacetForAutoCompleteAnnotation( + facetHolder, repositoryClass, repositoryMethod, servicesInjector); + } + + private AutoCompleteFacet createFor( + final DomainObject domainObject, + final FacetHolder facetHolder, + final Class<?> cls) { + if(domainObject == null) { + return null; + } + + final Class<?> repositoryClass = domainObject.autoCompleteRepository(); + if(repositoryClass == null || repositoryClass == Object.class) { + return null; + } + final String actionName = domainObject.autoCompleteAction(); + + if(!isServiceType(cls, "@DomainObject", repositoryClass)) { + return null; + } + final Method repositoryMethod = findRepositoryMethod(cls, "@DomainObject", repositoryClass, actionName); + if(repositoryMethod == null) { + return null; + } + + return new AutoCompleteFacetForDomainObjectAnnotation( + facetHolder, repositoryClass, repositoryMethod, servicesInjector); + } + + private boolean isServiceType( + final Class<?> cls, + final String annotationName, + final Class<?> repositoryClass) { + final boolean isRegistered = servicesInjector.isRegisteredService(repositoryClass); + if(!isRegistered) { + autoCompleteInvalid.addFailure( + "%s annotation on %s specifies unknown repository '%s'", + annotationName, cls.getName(), repositoryClass.getName()); + } + return isRegistered; + } + + private Method findRepositoryMethod( + final Class<?> cls, + final String annotationName, + final Class<?> repositoryClass, + final String methodName) { + final Method[] methods = repositoryClass.getMethods(); + for (Method method : methods) { + if(method.getName().equals(methodName)) { + final Class<?>[] parameterTypes = method.getParameterTypes(); + if(parameterTypes.length == 1 && parameterTypes[0].equals(String.class)) { + return method; + } + } + } + autoCompleteInvalid.addFailure( + "%s annotation on %s specifies action '%s' that does not exist in repository '%s'", + annotationName, cls.getName(), methodName, repositoryClass.getName()); + return null; + } + void processBounded(final ProcessClassContext processClassContext) { final Class<?> cls = processClassContext.getCls(); final DomainObject domainObject = Annotations.getAnnotation(cls, DomainObject.class); @@ -476,6 +554,8 @@ public class DomainObjectAnnotationFacetFactory extends FacetFactoryAbstract metaModelValidator.add(boundedValidator); metaModelValidator.add(immutableValidator); metaModelValidator.add(objectTypeValidator); + + metaModelValidator.add(autoCompleteInvalid); } // ////////////////////////////////////// http://git-wip-us.apache.org/repos/asf/isis/blob/fbf5a459/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/autocomplete/AutoCompleteFacetForAutoCompleteAnnotation.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/autocomplete/AutoCompleteFacetForAutoCompleteAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/autocomplete/AutoCompleteFacetForAutoCompleteAnnotation.java index df7b64a..fc9371d 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/autocomplete/AutoCompleteFacetForAutoCompleteAnnotation.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/autocomplete/AutoCompleteFacetForAutoCompleteAnnotation.java @@ -19,14 +19,12 @@ package org.apache.isis.core.metamodel.facets.object.domainobject.autocomplete; -import org.apache.isis.applib.annotation.AutoComplete; -import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager; -import org.apache.isis.core.metamodel.deployment.DeploymentCategory; +import java.lang.reflect.Method; + import org.apache.isis.core.metamodel.facetapi.FacetHolder; -import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet; import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacetAbstract; import org.apache.isis.core.metamodel.services.ServicesInjector; -import org.apache.isis.core.metamodel.specloader.SpecificationLoader; +import org.apache.isis.core.metamodel.spec.feature.ObjectAction; /** * @deprecated @@ -34,30 +32,12 @@ import org.apache.isis.core.metamodel.specloader.SpecificationLoader; @Deprecated public class AutoCompleteFacetForAutoCompleteAnnotation extends AutoCompleteFacetAbstract { - public static AutoCompleteFacet create( - final AutoComplete annotation, - final FacetHolder holder, - final ServicesInjector servicesInjector) { - - if(annotation == null) { - return null; - } - - final Class<?> repositoryClass = annotation.repository(); - final String actionName = annotation.action(); - - return new AutoCompleteFacetForAutoCompleteAnnotation(holder, repositoryClass, actionName, - servicesInjector - ); - } - - private AutoCompleteFacetForAutoCompleteAnnotation( + public AutoCompleteFacetForAutoCompleteAnnotation( final FacetHolder holder, final Class<?> repositoryClass, - final String actionName, + final Method actionName, final ServicesInjector servicesInjector) { - super(holder, repositoryClass, actionName, servicesInjector - ); + super(holder, repositoryClass, actionName, servicesInjector); } http://git-wip-us.apache.org/repos/asf/isis/blob/fbf5a459/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/autocomplete/AutoCompleteFacetForDomainObjectAnnotation.java ---------------------------------------------------------------------- diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/autocomplete/AutoCompleteFacetForDomainObjectAnnotation.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/autocomplete/AutoCompleteFacetForDomainObjectAnnotation.java index 7c52c11..2478300 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/autocomplete/AutoCompleteFacetForDomainObjectAnnotation.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/domainobject/autocomplete/AutoCompleteFacetForDomainObjectAnnotation.java @@ -19,51 +19,27 @@ package org.apache.isis.core.metamodel.facets.object.domainobject.autocomplete; -import org.apache.isis.applib.annotation.DomainObject; -import org.apache.isis.core.commons.authentication.AuthenticationSessionProvider; -import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager; -import org.apache.isis.core.metamodel.deployment.DeploymentCategory; +import java.lang.reflect.Method; + import org.apache.isis.core.metamodel.facetapi.FacetHolder; -import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacet; import org.apache.isis.core.metamodel.facets.object.autocomplete.AutoCompleteFacetAbstract; import org.apache.isis.core.metamodel.services.ServicesInjector; -import org.apache.isis.core.metamodel.specloader.SpecificationLoader; public class AutoCompleteFacetForDomainObjectAnnotation extends AutoCompleteFacetAbstract { private final Class<?> repositoryClass; private final String actionName; - public static AutoCompleteFacet create( - final DomainObject domainObject, - final FacetHolder holder, - final ServicesInjector servicesInjector) { - - if(domainObject == null) { - return null; - } - - final Class<?> autoCompleteRepository = domainObject.autoCompleteRepository(); - if(autoCompleteRepository == null || autoCompleteRepository == Object.class) { - return null; - } - final String autoCompleteAction = domainObject.autoCompleteAction(); - return new AutoCompleteFacetForDomainObjectAnnotation(holder, autoCompleteRepository, autoCompleteAction, servicesInjector - ); - } - - private AutoCompleteFacetForDomainObjectAnnotation( - final FacetHolder holder, + public AutoCompleteFacetForDomainObjectAnnotation( + final FacetHolder facetHolder, final Class<?> repositoryClass, - final String actionName, + final Method repositoryMethod, final ServicesInjector servicesInjector) { - super(holder, repositoryClass, actionName, servicesInjector - ); + super(facetHolder, repositoryClass, repositoryMethod, servicesInjector); this.repositoryClass = repositoryClass; - this.actionName = actionName; + this.actionName = repositoryMethod.getName(); } - /** * Introduced for testing only. */ http://git-wip-us.apache.org/repos/asf/isis/blob/fbf5a459/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java ---------------------------------------------------------------------- diff --git a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java index 0d65bc8..0039bf6 100644 --- a/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java +++ b/core/viewer-wicket-ui/src/main/java/org/apache/isis/viewer/wicket/ui/components/scalars/reference/ReferencePanel.java @@ -265,20 +265,30 @@ public class ReferencePanel extends ScalarPanelAbstract { entityLink.setRequired(getModel().isRequired()); select2Field = Select2ChoiceUtil.newSelect2Choice(ID_AUTO_COMPLETE, model, getModel()); setProviderAndCurrAndPending(select2Field, getModel().getActionArgsHint()); - if(!getModel().hasChoices()) { - final Settings settings = select2Field.getSettings(); + + final Settings settings = select2Field.getSettings(); + + // one of these three case should be true + // (as per the isEditableWithEitherAutoCompleteOrChoices() guard above) + if(getModel().hasChoices()) { + + settings.setPlaceholder(getModel().getName()); + + } else if(getModel().hasAutoComplete()) { + final int minLength = getModel().getAutoCompleteMinLength(); settings.setMinimumInputLength(minLength); settings.setPlaceholder(getModel().getName()); - } - if(hasObjectAutoComplete()) { + + } else if(hasObjectAutoComplete()) { final ObjectSpecification typeOfSpecification = getModel().getTypeOfSpecification(); final AutoCompleteFacet autoCompleteFacet = typeOfSpecification.getFacet(AutoCompleteFacet.class); - final Settings settings = select2Field.getSettings(); final int minLength = autoCompleteFacet.getMinLength(); settings.setMinimumInputLength(minLength); } + entityLink.addOrReplace(select2Field); + } else { // // the select2Field already exists, so the widget has been rendered before. If it is @@ -340,7 +350,7 @@ public class ReferencePanel extends ScalarPanelAbstract { resetIfCurrentNotInChoices(select2Field, choiceMementos); - } else if(hasParamOrPropertyAutoComplete()) { + } else if(getModel().hasAutoComplete()) { select2Field.setProvider(providerForParamOrPropertyAutoComplete()); getModel().clearPending(); } else { @@ -508,12 +518,7 @@ public class ReferencePanel extends ScalarPanelAbstract { if(getModel().isViewMode()) { return false; } - return getModel().hasChoices() || hasParamOrPropertyAutoComplete() || hasObjectAutoComplete(); - } - - // called by isEditableWithEitherAutoCompleteOrChoices, also syncProviderAndCurrAndPending - private boolean hasParamOrPropertyAutoComplete() { - return getModel().hasAutoComplete(); + return getModel().hasChoices() || getModel().hasAutoComplete() || hasObjectAutoComplete(); } // called by isEditableWithEitherAutoCompleteOrChoices