private <F extends ObjectType> void recordValidityDelta(
      LensFocusContext<F> focusContext,
      TimeIntervalStatusType validityStatusNew,
      XMLGregorianCalendar now)
      throws SchemaException {
    PrismContainerDefinition<ActivationType> activationDefinition = getActivationDefinition();

    PrismPropertyDefinition<TimeIntervalStatusType> validityStatusDef =
        activationDefinition.findPropertyDefinition(ActivationType.F_VALIDITY_STATUS);
    PropertyDelta<TimeIntervalStatusType> validityStatusDelta =
        validityStatusDef.createEmptyDelta(
            new ItemPath(UserType.F_ACTIVATION, ActivationType.F_VALIDITY_STATUS));
    if (validityStatusNew == null) {
      validityStatusDelta.setValueToReplace();
    } else {
      validityStatusDelta.setValueToReplace(
          new PrismPropertyValue<TimeIntervalStatusType>(
              validityStatusNew, OriginType.USER_POLICY, null));
    }
    focusContext.swallowToProjectionWaveSecondaryDelta(validityStatusDelta);

    PrismPropertyDefinition<XMLGregorianCalendar> validityChangeTimestampDef =
        activationDefinition.findPropertyDefinition(ActivationType.F_VALIDITY_CHANGE_TIMESTAMP);
    PropertyDelta<XMLGregorianCalendar> validityChangeTimestampDelta =
        validityChangeTimestampDef.createEmptyDelta(
            new ItemPath(UserType.F_ACTIVATION, ActivationType.F_VALIDITY_CHANGE_TIMESTAMP));
    validityChangeTimestampDelta.setValueToReplace(
        new PrismPropertyValue<XMLGregorianCalendar>(now, OriginType.USER_POLICY, null));
    focusContext.swallowToProjectionWaveSecondaryDelta(validityChangeTimestampDelta);
  }
 public <P extends PrismProperty> P instantiateEmptyProperty() {
   PrismPropertyDefinition propertyDefinition = getPropertyDefinition();
   if (propertyDefinition == null) {
     throw new IllegalArgumentException(
         "Cannot instantiate property "
             + getElementName()
             + " from delta "
             + this
             + ": no definition");
   }
   return (P) propertyDefinition.instantiate(getElementName());
 }
Exemple #3
0
  /**
   * @return Returns proper {@link PropertyModel} based on different types like {@link
   *     com.evolveum.midpoint.prism.polystring.PolyString} or {@link
   *     com.evolveum.midpoint.xml.ns._public.common.common_2a.ProtectedStringType}
   */
  private IModel createValueModel() {
    FieldToken token = model.getObject().getField().getToken();
    PrismPropertyDefinition definition = token.getDefinition();

    final String baseExpression = "value.value"; // pointing to prism property real value

    if (ProtectedStringType.COMPLEX_TYPE.equals(definition.getTypeName())) {
      return new PropertyModel<String>(model, baseExpression + ".clearValue");
    } else if (SchemaConstants.T_POLY_STRING_TYPE.equals(definition.getTypeName())) {
      return new PropertyModel<String>(model, baseExpression + ".orig");
    }

    return new PropertyModel(model, baseExpression);
  }
 private boolean isEnum(PrismProperty property) {
   PrismPropertyDefinition definition = property.getDefinition();
   ////    	Object realValue = property.getAnyRealValue();
   if (definition == null) {
     return property.getValueClass().isEnum();
   }
   //
   //    	QName defName = definition.getName();
   //    	Class clazz =
   // definition.getPrismContext().getSchemaRegistry().determineCompileTimeClass(defName);
   //
   //    	return ((clazz != null && clazz.isEnum()) ||
   // ActivationType.F_ADMINISTRATIVE_STATUS.equals(definition.getName())
   //    	 || ActivationType.F_LOCKOUT_STATUS.equals(definition.getName()) || );
   return (definition.getAllowedValues() != null && definition.getAllowedValues().size() > 0);
 }
  /**
   * This methods check if we want to show property in form (e.g. failedLogins, fetchResult,
   * lastFailedLoginTimestamp must be invisible)
   *
   * @return
   * @deprecated will be implemented through annotations in schema
   */
  @Deprecated
  private boolean skipProperty(PrismPropertyDefinition def) {
    final List<QName> names = new ArrayList<QName>();
    names.add(PasswordType.F_FAILED_LOGINS);
    names.add(PasswordType.F_LAST_FAILED_LOGIN);
    names.add(PasswordType.F_LAST_SUCCESSFUL_LOGIN);
    names.add(PasswordType.F_PREVIOUS_SUCCESSFUL_LOGIN);
    names.add(ObjectType.F_FETCH_RESULT);
    // activation
    names.add(ActivationType.F_EFFECTIVE_STATUS);
    names.add(ActivationType.F_VALIDITY_STATUS);
    // user
    names.add(UserType.F_RESULT);
    // org and roles
    names.add(OrgType.F_APPROVAL_PROCESS);
    names.add(OrgType.F_APPROVER_EXPRESSION);
    names.add(OrgType.F_AUTOMATICALLY_APPROVED);
    names.add(OrgType.F_CONDITION);

    for (QName name : names) {
      if (name.equals(def.getName())) {
        return true;
      }
    }

    return false;
  }
 // region Serializing properties - specific functionality
 private <T> XNode serializePropertyValue(
     PrismPropertyValue<T> value, PrismPropertyDefinition<T> definition) throws SchemaException {
   QName typeQName = definition.getTypeName();
   T realValue = value.getValue();
   if (realValue instanceof PolyString) {
     return serializePolyString((PolyString) realValue);
   } else if (beanConverter.canProcess(typeQName)) {
     XNode xnode = beanConverter.marshall(realValue);
     if (realValue instanceof ProtectedDataType<?> && definition.isDynamic()) { // why is this?
       xnode.setExplicitTypeDeclaration(true);
       xnode.setTypeQName(definition.getTypeName());
     }
     return xnode;
   } else {
     // primitive value
     return createPrimitiveXNode(realValue, typeQName);
   }
 }
  @Override
  public void setObject(Object object) {
    try {
      PrismProperty property = getPrismObject().findOrCreateProperty(path);

      if (object != null) {
        PrismPropertyDefinition def = property.getDefinition();
        if (PolyString.class.equals(def.getTypeClass())) {
          object = new PolyString((String) object);
        }

        property.setValue(new PrismPropertyValue(object, OriginType.USER_ACTION, null));
      } else {
        PrismContainerValue parent = (PrismContainerValue) property.getParent();
        parent.remove(property);
      }
    } catch (Exception ex) {
      LoggingUtils.logException(LOGGER, "Couldn't update prism property model", ex);
    }
  }
  private boolean hasCapability(PrismPropertyDefinition def) {
    ShadowType shadow = (ShadowType) getObject().getObject().asObjectable();

    ActivationCapabilityType cap =
        ResourceTypeUtil.getEffectiveCapability(
            shadow.getResource(), ActivationCapabilityType.class);

    if (ActivationType.F_VALID_FROM.equals(def.getName()) && cap.getValidFrom() == null) {
      return false;
    }

    if (ActivationType.F_VALID_TO.equals(def.getName()) && cap.getValidTo() == null) {
      return false;
    }

    if (ActivationType.F_ADMINISTRATIVE_STATUS.equals(def.getName()) && cap.getStatus() == null) {
      return false;
    }

    return true;
  }
  private <F extends ObjectType> void recordEffectiveStatusDelta(
      LensFocusContext<F> focusContext,
      ActivationStatusType effectiveStatusNew,
      XMLGregorianCalendar now)
      throws SchemaException {
    PrismContainerDefinition<ActivationType> activationDefinition = getActivationDefinition();

    PrismPropertyDefinition<ActivationStatusType> effectiveStatusDef =
        activationDefinition.findPropertyDefinition(ActivationType.F_EFFECTIVE_STATUS);
    PropertyDelta<ActivationStatusType> effectiveStatusDelta =
        effectiveStatusDef.createEmptyDelta(
            new ItemPath(UserType.F_ACTIVATION, ActivationType.F_EFFECTIVE_STATUS));
    effectiveStatusDelta.setValueToReplace(
        new PrismPropertyValue<ActivationStatusType>(
            effectiveStatusNew, OriginType.USER_POLICY, null));
    focusContext.swallowToProjectionWaveSecondaryDelta(effectiveStatusDelta);

    PropertyDelta<XMLGregorianCalendar> timestampDelta =
        LensUtil.createActivationTimestampDelta(
            effectiveStatusNew, now, activationDefinition, OriginType.USER_POLICY);
    focusContext.swallowToProjectionWaveSecondaryDelta(timestampDelta);
  }
 public static <T> PropertyDelta<T> createModificationDeleteProperty(
     ItemPath propertyPath, PrismPropertyDefinition propertyDefinition, T... propertyValues) {
   PropertyDelta<T> propertyDelta =
       new PropertyDelta<T>(
           propertyPath,
           propertyDefinition,
           propertyDefinition.getPrismContext()); // hoping the prismContext is there
   Collection<PrismPropertyValue<T>> pValues =
       new ArrayList<PrismPropertyValue<T>>(propertyValues.length);
   for (T val : propertyValues) {
     pValues.add(new PrismPropertyValue<T>(val));
   }
   propertyDelta.addValuesToDelete(pValues);
   return propertyDelta;
 }
  public static <T> String serializeValue(
      T value,
      PrismPropertyDefinition def,
      QName itemName,
      PrismContext prismContext,
      String langXml)
      throws SchemaException {
    //		System.out.println("value serialization");
    if (value == null) {
      return null;
    }

    XNodeSerializer serializer = prismContext.getXnodeProcessor().createSerializer();

    if (value instanceof List) {
      List<T> values = (List<T>) value;
      if (values.isEmpty()) {
        return null;
      }

      if (def instanceof PrismPropertyDefinition) {
        PrismProperty prop = (PrismProperty) def.instantiate();
        for (T val : values) {
          PrismPropertyValue<T> pValue = new PrismPropertyValue<T>(val);
          prop.add(pValue);
        }
        XNode node = serializer.serializeItem(prop);
        if (node instanceof ListXNode) {
          ListXNode xList = (ListXNode) node;
          MapXNode xmap = new MapXNode();
          xmap.put(def.getName(), xList);
          String s = prismContext.getParserDom().serializeToString(xmap, def.getName());
          //					System.out.println("serialized: " + s);
          return s;
        }
        String s = prismContext.getParserDom().serializeToString(node, def.getName());
        //				System.out.println("serialized: " + s);
        return s;
      }
    }

    PrismValue pVal = null;

    if (value instanceof Containerable) {
      pVal = ((Containerable) value).asPrismContainerValue();
    } else if (value instanceof Referencable) {
      pVal = ((Referencable) value).asReferenceValue();
    } else {
      PrismProperty pp = def.instantiate();
      pVal = new PrismPropertyValue<T>(value);
      pp.add(pVal);
      XNode xnode = serializer.serializeItemValue(pVal, def);
      if (xnode == null) {
        throw new IllegalArgumentException("null node after serialization");
      }
      MapXNode xmap = null;
      if (xnode instanceof RootXNode) {
        XNode sub = ((RootXNode) xnode).getSubnode();
        if (!(sub instanceof MapXNode)) {
          throw new IllegalArgumentException("not uspported yet");
        }
        xmap = (MapXNode) sub;
      } else if (xnode instanceof MapXNode) {
        xmap = (MapXNode) xnode;
      } else if (xnode instanceof PrimitiveXNode) {
        String s = ((PrimitiveXNode) xnode).getStringValue();
        return s;
        //
      } else {
        throw new IllegalStateException("hmmm");
      }

      XNode node = xmap.get(itemName);
      String s = prismContext.getParserDom().serializeToString(node, itemName);
    }

    XNode node = serializer.serializeItemValue(pVal, def);
    String s = prismContext.getParserDom().serializeToString(node, itemName);
    //		System.out.println("serialized: " + s);
    return s;
    //		throw new UnsupportedOperationException("need to be implemented");

  }
  private <F extends FocusType> void processFocusFocus(
      LensContext<F> context,
      String activityDescription,
      XMLGregorianCalendar now,
      Task task,
      OperationResult result)
      throws ObjectNotFoundException, SchemaException, ExpressionEvaluationException,
          PolicyViolationException, ObjectAlreadyExistsException, CommunicationException,
          ConfigurationException, SecurityViolationException {

    LensFocusContext<F> focusContext = context.getFocusContext();
    ObjectTemplateType objectTemplate = context.getFocusTemplate();

    boolean resetOnRename = true; // This is fixed now. TODO: make it configurable
    int maxIterations = 0;
    IterationSpecificationType iterationSpecificationType = null;
    if (objectTemplate != null) {
      iterationSpecificationType = objectTemplate.getIteration();
      maxIterations = LensUtil.determineMaxIterations(iterationSpecificationType);
    }
    int iteration = focusContext.getIteration();
    String iterationToken = focusContext.getIterationToken();
    boolean wasResetIterationCounter = false;

    PrismObject<F> focusCurrent = focusContext.getObjectCurrent();
    if (focusCurrent != null && iterationToken == null) {
      Integer focusIteration = focusCurrent.asObjectable().getIteration();
      if (focusIteration != null) {
        iteration = focusIteration;
      }
      iterationToken = focusCurrent.asObjectable().getIterationToken();
    }

    while (true) {

      ObjectTypeTemplateType objectPolicyConfigurationType =
          focusContext.getObjectPolicyConfigurationType();
      if (objectPolicyConfigurationType != null
          && BooleanUtils.isTrue(objectPolicyConfigurationType.isOidNameBoundMode())) {
        // Generate the name now - unless it is already present
        PrismObject<F> focusNew = focusContext.getObjectNew();
        if (focusNew != null) {
          PolyStringType focusNewName = focusNew.asObjectable().getName();
          if (focusNewName == null) {
            String newName = focusNew.getOid();
            if (newName == null) {
              newName = OidUtil.generateOid();
            }
            LOGGER.trace("Generating new name (bound to OID): {}", newName);
            PrismObjectDefinition<F> focusDefinition = focusContext.getObjectDefinition();
            PrismPropertyDefinition<PolyString> focusNameDef =
                focusDefinition.findPropertyDefinition(FocusType.F_NAME);
            PropertyDelta<PolyString> nameDelta =
                focusNameDef.createEmptyDelta(new ItemPath(FocusType.F_NAME));
            nameDelta.setValueToReplace(
                new PrismPropertyValue<PolyString>(
                    new PolyString(newName), OriginType.USER_POLICY, null));
            focusContext.swallowToSecondaryDelta(nameDelta);
            focusContext.recompute();
          }
        }
      }

      ExpressionVariables variables =
          Utils.getDefaultExpressionVariables(
              focusContext.getObjectNew(), null, null, null, context.getSystemConfiguration());
      if (iterationToken == null) {
        iterationToken =
            LensUtil.formatIterationToken(
                context,
                focusContext,
                iterationSpecificationType,
                iteration,
                expressionFactory,
                variables,
                task,
                result);
      }

      // We have to remember the token and iteration in the context.
      // The context can be recomputed several times. But we always want
      // to use the same iterationToken if possible. If there is a random
      // part in the iterationToken expression that we need to avoid recomputing
      // the token otherwise the value can change all the time (even for the same inputs).
      // Storing the token in the secondary delta is not enough because secondary deltas can be
      // dropped
      // if the context is re-projected.
      focusContext.setIteration(iteration);
      focusContext.setIterationToken(iterationToken);
      LOGGER.trace(
          "Focus {} processing, iteration {}, token '{}'",
          new Object[] {focusContext.getHumanReadableName(), iteration, iterationToken});

      String conflictMessage;
      if (!LensUtil.evaluateIterationCondition(
          context,
          focusContext,
          iterationSpecificationType,
          iteration,
          iterationToken,
          true,
          expressionFactory,
          variables,
          task,
          result)) {

        conflictMessage = "pre-iteration condition was false";
        LOGGER.debug(
            "Skipping iteration {}, token '{}' for {} because the pre-iteration condition was false",
            new Object[] {iteration, iterationToken, focusContext.getHumanReadableName()});
      } else {

        // INBOUND

        if (consistencyChecks) context.checkConsistence();
        // Loop through the account changes, apply inbound expressions
        inboundProcessor.processInbound(context, now, task, result);
        if (consistencyChecks) context.checkConsistence();
        context.recomputeFocus();
        LensUtil.traceContext(LOGGER, activityDescription, "inbound", false, context, false);
        if (consistencyChecks) context.checkConsistence();

        // ACTIVATION

        processActivation(context, now, result);

        // OBJECT TEMPLATE (before assignments)

        objectTemplateProcessor.processTemplate(
            context,
            ObjectTemplateMappingEvaluationPhaseType.BEFORE_ASSIGNMENTS,
            now,
            task,
            result);

        // ASSIGNMENTS

        assignmentProcessor.processAssignmentsProjections(context, now, task, result);
        assignmentProcessor.processOrgAssignments(context, result);
        context.recompute();

        assignmentProcessor.checkForAssignmentConflicts(context, result);

        // OBJECT TEMPLATE (after assignments)

        objectTemplateProcessor.processTemplate(
            context, ObjectTemplateMappingEvaluationPhaseType.AFTER_ASSIGNMENTS, now, task, result);
        context.recompute();

        // PASSWORD POLICY

        passwordPolicyProcessor.processPasswordPolicy(focusContext, context, result);

        // Processing done, check for success

        if (resetOnRename && !wasResetIterationCounter && willResetIterationCounter(focusContext)) {
          // Make sure this happens only the very first time during the first recompute.
          // Otherwise it will always change the token (especially if the token expression has a
          // random part)
          // hence the focusContext.getIterationToken() == null
          wasResetIterationCounter = true;
          if (iteration != 0) {
            iteration = 0;
            iterationToken = null;
            LOGGER.trace("Resetting iteration counter and token because rename was detected");
            cleanupContext(focusContext);
            continue;
          }
        }

        PrismObject<F> previewObjectNew = focusContext.getObjectNew();
        if (previewObjectNew == null) {
          // this must be delete
        } else {
          // Explicitly check for name. The checker would check for this also. But checking it here
          // will produce better error message
          PolyStringType objectName = previewObjectNew.asObjectable().getName();
          if (objectName == null || objectName.getOrig().isEmpty()) {
            throw new SchemaException(
                "No name in new object "
                    + objectName
                    + " as produced by template "
                    + objectTemplate
                    + " in iteration "
                    + iteration
                    + ", we cannot process an object without a name");
          }
        }

        // Check if iteration constraints are OK
        FocusConstraintsChecker<F> checker = new FocusConstraintsChecker<>();
        checker.setPrismContext(prismContext);
        checker.setContext(context);
        checker.setRepositoryService(cacheRepositoryService);
        checker.check(previewObjectNew, result);
        if (checker.isSatisfiesConstraints()) {
          LOGGER.trace(
              "Current focus satisfies uniqueness constraints. Iteration {}, token '{}'",
              iteration,
              iterationToken);

          if (LensUtil.evaluateIterationCondition(
              context,
              focusContext,
              iterationSpecificationType,
              iteration,
              iterationToken,
              false,
              expressionFactory,
              variables,
              task,
              result)) {
            // stop the iterations
            break;
          } else {
            conflictMessage = "post-iteration condition was false";
            LOGGER.debug(
                "Skipping iteration {}, token '{}' for {} because the post-iteration condition was false",
                new Object[] {iteration, iterationToken, focusContext.getHumanReadableName()});
          }
        } else {
          LOGGER.trace(
              "Current focus does not satisfy constraints. Conflicting object: {}; iteration={}, maxIterations={}",
              new Object[] {checker.getConflictingObject(), iteration, maxIterations});
          conflictMessage = checker.getMessages();
        }

        if (!wasResetIterationCounter) {
          wasResetIterationCounter = true;
          if (iteration != 0) {
            iterationToken = null;
            iteration = 0;
            LOGGER.trace("Resetting iteration counter and token after conflict");
            cleanupContext(focusContext);
            continue;
          }
        }
      }

      // Next iteration
      iteration++;
      iterationToken = null;
      if (iteration > maxIterations) {
        StringBuilder sb = new StringBuilder();
        if (iteration == 1) {
          sb.append("Error processing ");
        } else {
          sb.append("Too many iterations (" + iteration + ") for ");
        }
        sb.append(focusContext.getHumanReadableName());
        if (iteration == 1) {
          sb.append(": constraint violation: ");
        } else {
          sb.append(": cannot determine values that satisfy constraints: ");
        }
        if (conflictMessage != null) {
          sb.append(conflictMessage);
        }
        throw new ObjectAlreadyExistsException(sb.toString());
      }
      cleanupContext(focusContext);
    }

    addIterationTokenDeltas(focusContext, iteration, iterationToken);
    if (consistencyChecks) context.checkConsistence();
  }
  // normally this method returns an InputPanel;
  // however, for some special readonly types (like ObjectDeltaType) it will return a Panel
  private Panel createTypedInputComponent(String id) {
    final Item item = model.getObject().getItem().getItem();

    Panel panel = null;
    if (item instanceof PrismProperty) {
      final PrismProperty property = (PrismProperty) item;
      PrismPropertyDefinition definition = property.getDefinition();
      QName valueType = definition.getTypeName();

      final String baseExpression = "value.value"; // pointing to prism property real value

      ContainerWrapper containerWrapper = model.getObject().getItem().getContainer();
      if (containerWrapper != null && containerWrapper.getPath() != null) {
        if (ShadowType.F_ASSOCIATION.getLocalPart().equals(containerWrapper.getPath().toString())) {
          return new TextDetailsPanel(id, new PropertyModel<String>(model, baseExpression)) {

            @Override
            public String createAssociationTooltip() {
              return createAssociationTooltipText(property);
            }
          };
        }
      }

      // fixing MID-1230, will be improved with some kind of annotation or something like that
      // now it works only in description
      if (ObjectType.F_DESCRIPTION.equals(definition.getName())) {
        return new TextAreaPanel(id, new PropertyModel(model, baseExpression));
      }

      // the same for requester and approver comments in workflows [mederly] - this is really ugly,
      // as it is specific to each approval form
      if (AssignmentCreationApprovalFormType.F_REQUESTER_COMMENT.equals(definition.getName())
          || AssignmentCreationApprovalFormType.F_COMMENT.equals(definition.getName())) {
        return new TextAreaPanel(id, new PropertyModel(model, baseExpression));
      }

      if (ActivationType.F_ADMINISTRATIVE_STATUS.equals(definition.getName())) {
        return WebMiscUtil.createEnumPanel(
            ActivationStatusType.class,
            id,
            new PropertyModel<ActivationStatusType>(model, baseExpression),
            this);
      } else if (ActivationType.F_LOCKOUT_STATUS.equals(definition.getName())) {
        return WebMiscUtil.createEnumPanel(
            LockoutStatusType.class,
            id,
            new PropertyModel<LockoutStatusType>(model, baseExpression),
            this);
      } else {
        // nothing to do
      }

      if (DOMUtil.XSD_DATETIME.equals(valueType)) {
        panel = new DatePanel(id, new PropertyModel<XMLGregorianCalendar>(model, baseExpression));

      } else if (ProtectedStringType.COMPLEX_TYPE.equals(valueType)) {
        panel =
            new PasswordPanel(
                id,
                new PropertyModel<ProtectedStringType>(model, baseExpression),
                model.getObject().isReadonly());

      } else if (DOMUtil.XSD_BOOLEAN.equals(valueType)) {
        panel = new TriStateComboPanel(id, new PropertyModel<Boolean>(model, baseExpression));

      } else if (SchemaConstants.T_POLY_STRING_TYPE.equals(valueType)) {
        InputPanel inputPanel;
        PrismPropertyDefinition def = property.getDefinition();

        if (def.getValueEnumerationRef() != null) {
          PrismReferenceValue valueEnumerationRef = def.getValueEnumerationRef();
          String lookupTableUid = valueEnumerationRef.getOid();
          Task task = pageBase.createSimpleTask("loadLookupTable");
          OperationResult result = task.getResult();

          Collection<SelectorOptions<GetOperationOptions>> options =
              SelectorOptions.createCollection(
                  LookupTableType.F_ROW,
                  GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE));
          final PrismObject<LookupTableType> lookupTable =
              WebModelUtils.loadObject(
                  LookupTableType.class, lookupTableUid, options, pageBase, task, result);

          inputPanel =
              new AutoCompleteTextPanel<String>(
                  id,
                  new LookupPropertyModel<String>(
                      model, baseExpression + ".orig", lookupTable.asObjectable()),
                  String.class) {

                @Override
                public Iterator<String> getIterator(String input) {
                  return prepareAutoCompleteList(input, lookupTable).iterator();
                }
              };

        } else {

          inputPanel =
              new TextPanel<>(
                  id, new PropertyModel<String>(model, baseExpression + ".orig"), String.class);
        }

        if (ObjectType.F_NAME.equals(def.getName()) || UserType.F_FULL_NAME.equals(def.getName())) {
          inputPanel.getBaseFormComponent().setRequired(true);
        }
        panel = inputPanel;

      } else if (DOMUtil.XSD_BASE64BINARY.equals(valueType)) {
        panel =
            new UploadDownloadPanel(id, model.getObject().isReadonly()) {

              @Override
              public InputStream getStream() {
                return new ByteArrayInputStream(
                    (byte[]) ((PrismPropertyValue) model.getObject().getValue()).getValue());
                //                		return super.getStream();
              }

              @Override
              public void updateValue(byte[] file) {
                ((PrismPropertyValue) model.getObject().getValue()).setValue(file);
              }

              @Override
              public void uploadFilePerformed(AjaxRequestTarget target) {
                super.uploadFilePerformed(target);
                target.add(PrismValuePanel.this.get(ID_FEEDBACK));
              }

              @Override
              public void removeFilePerformed(AjaxRequestTarget target) {
                super.removeFilePerformed(target);
                target.add(PrismValuePanel.this.get(ID_FEEDBACK));
              }

              @Override
              public void uploadFileFailed(AjaxRequestTarget target) {
                super.uploadFileFailed(target);
                target.add(PrismValuePanel.this.get(ID_FEEDBACK));
                target.add(((PageBase) getPage()).getFeedbackPanel());
              }
            };

      } else if (ObjectDeltaType.COMPLEX_TYPE.equals(valueType)) {
        panel =
            new ModificationsPanel(
                id,
                new AbstractReadOnlyModel<DeltaDto>() {
                  @Override
                  public DeltaDto getObject() {
                    if (model.getObject() == null
                        || model.getObject().getValue() == null
                        || ((PrismPropertyValue) model.getObject().getValue()).getValue() == null) {
                      return null;
                    }
                    PrismContext prismContext = ((PageBase) getPage()).getPrismContext();
                    ObjectDeltaType objectDeltaType =
                        (ObjectDeltaType)
                            ((PrismPropertyValue) model.getObject().getValue()).getValue();
                    try {
                      ObjectDelta delta =
                          DeltaConvertor.createObjectDelta(objectDeltaType, prismContext);
                      return new DeltaDto(delta);
                    } catch (SchemaException e) {
                      throw new IllegalStateException(
                          "Couldn't convert object delta: " + objectDeltaType);
                    }
                  }
                });
      } else {
        Class type = XsdTypeMapper.getXsdToJavaMapping(valueType);
        if (type != null && type.isPrimitive()) {
          type = ClassUtils.primitiveToWrapper(type);
        }

        if (isEnum(property)) {
          return WebMiscUtil.createEnumPanel(
              definition, id, new PropertyModel<>(model, baseExpression), this);
        }
        //                  // default QName validation is a bit weird, so let's treat QNames as
        // strings [TODO finish this - at the parsing side]
        //                  if (type == QName.class) {
        //                      type = String.class;
        //                  }

        PrismPropertyDefinition def = property.getDefinition();

        if (def.getValueEnumerationRef() != null) {
          PrismReferenceValue valueEnumerationRef = def.getValueEnumerationRef();
          String lookupTableUid = valueEnumerationRef.getOid();
          Task task = pageBase.createSimpleTask("loadLookupTable");
          OperationResult result = task.getResult();

          Collection<SelectorOptions<GetOperationOptions>> options =
              SelectorOptions.createCollection(
                  LookupTableType.F_ROW,
                  GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE));
          final PrismObject<LookupTableType> lookupTable =
              WebModelUtils.loadObject(
                  LookupTableType.class, lookupTableUid, options, pageBase, task, result);

          panel =
              new AutoCompleteTextPanel<String>(
                  id,
                  new LookupPropertyModel<String>(
                      model,
                      baseExpression,
                      lookupTable == null ? null : lookupTable.asObjectable()),
                  type) {

                @Override
                public Iterator<String> getIterator(String input) {
                  return prepareAutoCompleteList(input, lookupTable).iterator();
                }

                @Override
                public void checkInputValue(
                    AutoCompleteTextField input,
                    AjaxRequestTarget target,
                    LookupPropertyModel model) {
                  Iterator<String> lookupTableValuesIterator =
                      prepareAutoCompleteList("", lookupTable).iterator();

                  String value = input.getInput();
                  boolean isValueExist = false;
                  if (value != null) {
                    if (value.trim().equals("")) {
                      isValueExist = true;
                    } else {
                      while (lookupTableValuesIterator.hasNext()) {
                        String lookupTableValue = lookupTableValuesIterator.next();
                        if (value.trim().equals(lookupTableValue)) {
                          isValueExist = true;
                          break;
                        }
                      }
                    }
                  }
                  if (isValueExist) {
                    input.setModelValue(new String[] {value});
                    target.add(PrismValuePanel.this.get(ID_FEEDBACK));
                  } else {
                    input.error(
                        "Entered value doesn't match any of available values and will not be saved.");
                    target.add(PrismValuePanel.this.get(ID_FEEDBACK));
                  }
                }
              };

        } else {
          panel = new TextPanel<>(id, new PropertyModel<String>(model, baseExpression), type);
        }
      }
    } else if (item instanceof PrismReference) {
      //        	((PrismReferenceDefinition) item.getDefinition()).
      Class typeFromName = null;
      PrismContext prismContext = item.getPrismContext();
      if (prismContext == null) {
        prismContext = pageBase.getPrismContext();
      }
      QName targetTypeName = ((PrismReferenceDefinition) item.getDefinition()).getTargetTypeName();
      if (targetTypeName != null && prismContext != null) {
        typeFromName = prismContext.getSchemaRegistry().determineCompileTimeClass(targetTypeName);
      }
      final Class typeClass =
          typeFromName != null
              ? typeFromName
              : (item.getDefinition().getTypeClassIfKnown() != null
                  ? item.getDefinition().getTypeClassIfKnown()
                  : FocusType.class);
      panel =
          new ValueChoosePanel(
              id, new PropertyModel<>(model, "value"), item.getValues(), false, typeClass);
    }

    return panel;
  }
 private boolean isPassword(PrismPropertyDefinition def) {
   // in the future, this option could apply as well
   return CredentialsType.F_PASSWORD.equals(container.getElementName())
       || CredentialsType.F_PASSWORD.equals(def.getName());
 }
  private List<ItemWrapper> createProperties(PageBase pageBase) {
    result = new OperationResult(CREATE_PROPERTIES);

    List<ItemWrapper> properties = new ArrayList<ItemWrapper>();

    PrismContainerDefinition definition = null;
    PrismObject parent = getObject().getObject();
    Class clazz = parent.getCompileTimeClass();
    if (ShadowType.class.isAssignableFrom(clazz)) {
      QName name = containerDefinition.getName();

      if (ShadowType.F_ATTRIBUTES.equals(name)) {
        try {
          definition = objectWrapper.getRefinedAttributeDefinition();

          if (definition == null) {
            PrismReference resourceRef = parent.findReference(ShadowType.F_RESOURCE_REF);
            PrismObject<ResourceType> resource = resourceRef.getValue().getObject();

            definition =
                pageBase
                    .getModelInteractionService()
                    .getEditObjectClassDefinition(
                        (PrismObject<ShadowType>) objectWrapper.getObject(),
                        resource,
                        AuthorizationPhaseType.REQUEST)
                    .toResourceAttributeContainerDefinition();

            if (LOGGER.isTraceEnabled()) {
              LOGGER.trace("Refined account def:\n{}", definition.debugDump());
            }
          }
        } catch (Exception ex) {
          LoggingUtils.logException(
              LOGGER, "Couldn't load definitions from refined schema for shadow", ex);
          result.recordFatalError(
              "Couldn't load definitions from refined schema for shadow, reason: "
                  + ex.getMessage(),
              ex);

          return properties;
        }
      } else {
        definition = containerDefinition;
      }
    } else if (ResourceType.class.isAssignableFrom(clazz)) {
      if (containerDefinition != null) {
        definition = containerDefinition;
      } else {
        definition = container.getDefinition();
      }
    } else {
      definition = containerDefinition;
    }

    if (definition == null) {
      LOGGER.error(
          "Couldn't get property list from null definition {}",
          new Object[] {container.getElementName()});
      return properties;
    }

    // assignments are treated in a special way -- we display names of
    // org.units and roles
    // (but only if ObjectWrapper.isShowAssignments() is true; otherwise
    // they are filtered out by ObjectWrapper)
    if (container.getCompileTimeClass() != null
        && AssignmentType.class.isAssignableFrom(container.getCompileTimeClass())) {

      for (Object o : container.getValues()) {
        PrismContainerValue<AssignmentType> pcv = (PrismContainerValue<AssignmentType>) o;

        AssignmentType assignmentType = pcv.asContainerable();

        if (assignmentType.getTargetRef() == null) {
          continue;
        }

        // hack... we want to create a definition for Name
        // PrismPropertyDefinition def = ((PrismContainerValue)
        // pcv.getContainer().getParent()).getContainer().findProperty(ObjectType.F_NAME).getDefinition();
        PrismPropertyDefinition def =
            new PrismPropertyDefinition(
                ObjectType.F_NAME, DOMUtil.XSD_STRING, pcv.getPrismContext());

        if (OrgType.COMPLEX_TYPE.equals(assignmentType.getTargetRef().getType())) {
          def.setDisplayName("Org.Unit");
          def.setDisplayOrder(100);
        } else if (RoleType.COMPLEX_TYPE.equals(assignmentType.getTargetRef().getType())) {
          def.setDisplayName("Role");
          def.setDisplayOrder(200);
        } else {
          continue;
        }

        PrismProperty<Object> temp = def.instantiate();

        String value = formatAssignmentBrief(assignmentType);

        temp.setValue(new PrismPropertyValue<Object>(value));
        // TODO: do this.isReadOnly() - is that OK? (originally it was the default behavior for all
        // cases)
        properties.add(new PropertyWrapper(this, temp, this.isReadonly(), ValueStatus.NOT_CHANGED));
      }

    } else if (isShadowAssociation()) {
      PrismContext prismContext = objectWrapper.getObject().getPrismContext();
      Map<QName, PrismContainer<ShadowAssociationType>> assocMap = new HashMap<>();
      if (objectWrapper.getAssociations() != null) {
        for (PrismContainerValue<ShadowAssociationType> cval : objectWrapper.getAssociations()) {
          ShadowAssociationType associationType = cval.asContainerable();
          QName assocName = associationType.getName();
          PrismContainer<ShadowAssociationType> fractionalContainer = assocMap.get(assocName);
          if (fractionalContainer == null) {
            fractionalContainer =
                new PrismContainer<>(
                    ShadowType.F_ASSOCIATION, ShadowAssociationType.class, cval.getPrismContext());
            fractionalContainer.setDefinition(cval.getParent().getDefinition());
            // HACK: set the name of the association as the element name so wrapper.getName() will
            // return correct data.
            fractionalContainer.setElementName(assocName);
            assocMap.put(assocName, fractionalContainer);
          }
          try {
            fractionalContainer.add(cval.clone());
          } catch (SchemaException e) {
            // Should not happen
            throw new SystemException("Unexpected error: " + e.getMessage(), e);
          }
        }
      }

      PrismReference resourceRef = parent.findReference(ShadowType.F_RESOURCE_REF);
      PrismObject<ResourceType> resource = resourceRef.getValue().getObject();

      // HACK. The revive should not be here. Revive is no good. The next use of the resource will
      // cause parsing of resource schema. We need some centralized place to maintain live cached
      // copies
      // of resources.
      try {
        resource.revive(prismContext);
      } catch (SchemaException e) {
        throw new SystemException(e.getMessage(), e);
      }
      RefinedResourceSchema refinedSchema;
      CompositeRefinedObjectClassDefinition rOcDef;
      try {
        refinedSchema = RefinedResourceSchema.getRefinedSchema(resource);
        rOcDef = refinedSchema.determineCompositeObjectClassDefinition(parent);
      } catch (SchemaException e) {
        throw new SystemException(e.getMessage(), e);
      }
      // Make sure even empty associations have their wrappers so they can be displayed and edited
      for (RefinedAssociationDefinition assocDef : rOcDef.getAssociations()) {
        QName name = assocDef.getName();
        if (!assocMap.containsKey(name)) {
          PrismContainer<ShadowAssociationType> fractionalContainer =
              new PrismContainer<>(
                  ShadowType.F_ASSOCIATION, ShadowAssociationType.class, prismContext);
          fractionalContainer.setDefinition(getItemDefinition());
          // HACK: set the name of the association as the element name so wrapper.getName() will
          // return correct data.
          fractionalContainer.setElementName(name);
          assocMap.put(name, fractionalContainer);
        }
      }

      for (Entry<QName, PrismContainer<ShadowAssociationType>> assocEntry : assocMap.entrySet()) {
        // HACK HACK HACK, the container wrapper should not parse itself. This code should not be
        // here.
        AssociationWrapper assocWrapper =
            new AssociationWrapper(
                this, assocEntry.getValue(), this.isReadonly(), ValueStatus.NOT_CHANGED);
        properties.add(assocWrapper);
      }

    } else { // if not an assignment

      if ((container.getValues().size() == 1 || container.getValues().isEmpty())
          && (containerDefinition == null || containerDefinition.isSingleValue())) {

        // there's no point in showing properties for non-single-valued
        // parent containers,
        // so we continue only if the parent is single-valued

        Collection<ItemDefinition> propertyDefinitions = definition.getDefinitions();
        for (ItemDefinition itemDef : propertyDefinitions) {
          if (itemDef instanceof PrismPropertyDefinition) {

            PrismPropertyDefinition def = (PrismPropertyDefinition) itemDef;
            if (def.isIgnored() || skipProperty(def)) {
              continue;
            }
            if (!showInheritedObjectAttributes
                && INHERITED_OBJECT_ATTRIBUTES.contains(def.getName())) {
              continue;
            }

            // capability handling for activation properties
            if (isShadowActivation() && !hasCapability(def)) {
              continue;
            }

            if (isShadowAssociation()) {
              continue;
            }

            PrismProperty property = container.findProperty(def.getName());
            boolean propertyIsReadOnly;
            // decision is based on parent object status, not this
            // container's one (because container can be added also
            // to an existing object)
            if (objectWrapper.getStatus() == ContainerStatus.MODIFYING) {

              propertyIsReadOnly = !def.canModify();
            } else {
              propertyIsReadOnly = !def.canAdd();
            }
            if (property == null) {
              properties.add(
                  new PropertyWrapper(
                      this, def.instantiate(), propertyIsReadOnly, ValueStatus.ADDED));
            } else {
              properties.add(
                  new PropertyWrapper(this, property, propertyIsReadOnly, ValueStatus.NOT_CHANGED));
            }
          } else if (itemDef instanceof PrismReferenceDefinition) {
            PrismReferenceDefinition def = (PrismReferenceDefinition) itemDef;

            if (INHERITED_OBJECT_ATTRIBUTES.contains(def.getName())) {
              continue;
            }

            PrismReference reference = container.findReference(def.getName());
            boolean propertyIsReadOnly;
            // decision is based on parent object status, not this
            // container's one (because container can be added also
            // to an existing object)
            if (objectWrapper.getStatus() == ContainerStatus.MODIFYING) {

              propertyIsReadOnly = !def.canModify();
            } else {
              propertyIsReadOnly = !def.canAdd();
            }
            if (reference == null) {
              properties.add(
                  new ReferenceWrapper(
                      this, def.instantiate(), propertyIsReadOnly, ValueStatus.ADDED));
            } else {
              properties.add(
                  new ReferenceWrapper(
                      this, reference, propertyIsReadOnly, ValueStatus.NOT_CHANGED));
            }
          }
        }
      }
    }

    Collections.sort(properties, new ItemWrapperComparator());

    result.recomputeStatus();

    return properties;
  }
Exemple #16
0
  // normally this method returns an InputPanel;
  // however, for some special readonly types (like ObjectDeltaType) it will return a Panel
  private Panel createTypedInputComponent(String id) {
    //        ValueWrapper valueWrapper = model.getObject();
    //        ItemWrapper itemWrapper =
    final Item item = valueWrapperModel.getObject().getItem().getItem();

    Panel panel = null;
    if (item instanceof PrismProperty) {
      final PrismProperty property = (PrismProperty) item;
      PrismPropertyDefinition definition = property.getDefinition();
      final QName valueType = definition.getTypeName();

      final String baseExpression = "value.value"; // pointing to prism property real value

      // fixing MID-1230, will be improved with some kind of annotation or something like that
      // now it works only in description
      if (ObjectType.F_DESCRIPTION.equals(definition.getName())) {
        return new TextAreaPanel(id, new PropertyModel(valueWrapperModel, baseExpression), null);
      }

      if (ActivationType.F_ADMINISTRATIVE_STATUS.equals(definition.getName())) {
        return WebComponentUtil.createEnumPanel(
            ActivationStatusType.class,
            id,
            new PropertyModel<ActivationStatusType>(valueWrapperModel, baseExpression),
            this);
      } else if (ActivationType.F_LOCKOUT_STATUS.equals(definition.getName())) {
        return new LockoutStatusPanel(
            id, new PropertyModel<LockoutStatusType>(valueWrapperModel, baseExpression));
      } else {
        // nothing to do
      }

      if (DOMUtil.XSD_DATETIME.equals(valueType)) {
        panel =
            new DatePanel(
                id, new PropertyModel<XMLGregorianCalendar>(valueWrapperModel, baseExpression));

      } else if (ProtectedStringType.COMPLEX_TYPE.equals(valueType)) {
        boolean showRemovePasswordButton = true;
        if (pageBase instanceof PageUser
            && ((PageUser) pageBase).getObjectWrapper().getObject() != null
            && ((PageUser) pageBase).getObjectWrapper().getObject().getOid() != null
            && ((PageUser) pageBase)
                .getObjectWrapper()
                .getObject()
                .getOid()
                .equals(SecurityUtils.getPrincipalUser().getOid())) {
          showRemovePasswordButton = false;
        }
        panel =
            new PasswordPanel(
                id,
                new PropertyModel<ProtectedStringType>(valueWrapperModel, baseExpression),
                valueWrapperModel.getObject().isReadonly(),
                showRemovePasswordButton);
      } else if (DOMUtil.XSD_BOOLEAN.equals(valueType)) {
        panel =
            new TriStateComboPanel(
                id, new PropertyModel<Boolean>(valueWrapperModel, baseExpression));

      } else if (SchemaConstants.T_POLY_STRING_TYPE.equals(valueType)) {
        InputPanel inputPanel;
        PrismPropertyDefinition def = property.getDefinition();

        if (def.getValueEnumerationRef() != null) {
          PrismReferenceValue valueEnumerationRef = def.getValueEnumerationRef();
          String lookupTableUid = valueEnumerationRef.getOid();
          Task task = pageBase.createSimpleTask("loadLookupTable");
          OperationResult result = task.getResult();

          Collection<SelectorOptions<GetOperationOptions>> options =
              SelectorOptions.createCollection(
                  LookupTableType.F_ROW,
                  GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE));
          final PrismObject<LookupTableType> lookupTable =
              WebModelServiceUtils.loadObject(
                  LookupTableType.class, lookupTableUid, options, pageBase, task, result);

          if (lookupTable != null) {

            inputPanel =
                new AutoCompleteTextPanel<String>(
                    id,
                    new LookupPropertyModel<String>(
                        valueWrapperModel, baseExpression + ".orig", lookupTable.asObjectable()),
                    String.class) {

                  @Override
                  public Iterator<String> getIterator(String input) {
                    return prepareAutoCompleteList(input, lookupTable).iterator();
                  }
                };

          } else {
            inputPanel =
                new TextPanel<>(
                    id,
                    new PropertyModel<String>(valueWrapperModel, baseExpression + ".orig"),
                    String.class);
          }

        } else {

          inputPanel =
              new TextPanel<>(
                  id,
                  new PropertyModel<String>(valueWrapperModel, baseExpression + ".orig"),
                  String.class);
        }

        if (ObjectType.F_NAME.equals(def.getName()) || UserType.F_FULL_NAME.equals(def.getName())) {
          inputPanel.getBaseFormComponent().setRequired(true);
        }
        panel = inputPanel;

      } else if (DOMUtil.XSD_BASE64BINARY.equals(valueType)) {
        panel =
            new UploadDownloadPanel(id, valueWrapperModel.getObject().isReadonly()) {

              @Override
              public InputStream getStream() {
                Object object =
                    ((PrismPropertyValue) valueWrapperModel.getObject().getValue()).getValue();
                return object != null
                    ? new ByteArrayInputStream((byte[]) object)
                    : new ByteArrayInputStream(new byte[0]);
                //                		return super.getStream();
              }

              @Override
              public void updateValue(byte[] file) {
                ((PrismPropertyValue) valueWrapperModel.getObject().getValue()).setValue(file);
              }

              @Override
              public void uploadFilePerformed(AjaxRequestTarget target) {
                super.uploadFilePerformed(target);
                target.add(PrismValuePanel.this.get(ID_FEEDBACK));
              }

              @Override
              public void removeFilePerformed(AjaxRequestTarget target) {
                super.removeFilePerformed(target);
                target.add(PrismValuePanel.this.get(ID_FEEDBACK));
              }

              @Override
              public void uploadFileFailed(AjaxRequestTarget target) {
                super.uploadFileFailed(target);
                target.add(PrismValuePanel.this.get(ID_FEEDBACK));
                target.add(((PageBase) getPage()).getFeedbackPanel());
              }
            };

      } else if (ObjectDeltaType.COMPLEX_TYPE.equals(valueType)) {
        panel =
            new ModificationsPanel(
                id,
                new AbstractReadOnlyModel<DeltaDto>() {
                  @Override
                  public DeltaDto getObject() {
                    if (valueWrapperModel.getObject() == null
                        || valueWrapperModel.getObject().getValue() == null
                        || ((PrismPropertyValue) valueWrapperModel.getObject().getValue())
                                .getValue()
                            == null) {
                      return null;
                    }
                    PrismContext prismContext = ((PageBase) getPage()).getPrismContext();
                    ObjectDeltaType objectDeltaType =
                        (ObjectDeltaType)
                            ((PrismPropertyValue) valueWrapperModel.getObject().getValue())
                                .getValue();
                    try {
                      ObjectDelta delta =
                          DeltaConvertor.createObjectDelta(objectDeltaType, prismContext);
                      return new DeltaDto(delta);
                    } catch (SchemaException e) {
                      throw new IllegalStateException(
                          "Couldn't convert object delta: " + objectDeltaType);
                    }
                  }
                });
      } else if (QueryType.COMPLEX_TYPE.equals(valueType)
          || CleanupPoliciesType.COMPLEX_TYPE.equals(valueType)) {
        return new TextAreaPanel(
            id,
            new AbstractReadOnlyModel() {
              @Override
              public Object getObject() {
                if (valueWrapperModel.getObject() == null
                    || valueWrapperModel.getObject().getValue() == null) {
                  return null;
                }
                PrismPropertyValue ppv =
                    (PrismPropertyValue) valueWrapperModel.getObject().getValue();
                if (ppv == null || ppv.getValue() == null) {
                  return null;
                }
                QName name = property.getElementName();
                if (name == null && property.getDefinition() != null) {
                  name = property.getDefinition().getName();
                }
                if (name == null) {
                  name = SchemaConstants.C_VALUE;
                }
                PrismContext prismContext = ((PageBase) getPage()).getPrismContext();
                try {
                  return prismContext.serializeAnyData(ppv.getValue(), name, PrismContext.LANG_XML);
                } catch (SchemaException e) {
                  throw new SystemException(
                      "Couldn't serialize property value of type: "
                          + valueType
                          + ": "
                          + e.getMessage(),
                      e);
                }
              }
            },
            10);
      } else {
        Class type = XsdTypeMapper.getXsdToJavaMapping(valueType);
        if (type != null && type.isPrimitive()) {
          type = ClassUtils.primitiveToWrapper(type);
        }

        if (isEnum(property)) {
          return WebComponentUtil.createEnumPanel(
              definition, id, new PropertyModel<>(valueWrapperModel, baseExpression), this);
        }
        //                  // default QName validation is a bit weird, so let's treat QNames as
        // strings [TODO finish this - at the parsing side]
        //                  if (type == QName.class) {
        //                      type = String.class;
        //                  }

        PrismPropertyDefinition def = property.getDefinition();

        if (def.getValueEnumerationRef() != null) {
          PrismReferenceValue valueEnumerationRef = def.getValueEnumerationRef();
          String lookupTableUid = valueEnumerationRef.getOid();
          Task task = pageBase.createSimpleTask("loadLookupTable");
          OperationResult result = task.getResult();

          Collection<SelectorOptions<GetOperationOptions>> options =
              SelectorOptions.createCollection(
                  LookupTableType.F_ROW,
                  GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE));
          final PrismObject<LookupTableType> lookupTable =
              WebModelServiceUtils.loadObject(
                  LookupTableType.class, lookupTableUid, options, pageBase, task, result);

          if (lookupTable != null) {

            panel =
                new AutoCompleteTextPanel<String>(
                    id,
                    new LookupPropertyModel<String>(
                        valueWrapperModel,
                        baseExpression,
                        lookupTable == null ? null : lookupTable.asObjectable()),
                    type) {

                  @Override
                  public Iterator<String> getIterator(String input) {
                    return prepareAutoCompleteList(input, lookupTable).iterator();
                  }

                  @Override
                  public void checkInputValue(
                      AutoCompleteTextField input,
                      AjaxRequestTarget target,
                      LookupPropertyModel model) {
                    Iterator<String> lookupTableValuesIterator =
                        prepareAutoCompleteList("", lookupTable).iterator();

                    String value = input.getInput();
                    boolean isValueExist = false;
                    if (value != null) {
                      if (value.trim().equals("")) {
                        isValueExist = true;
                      } else {
                        while (lookupTableValuesIterator.hasNext()) {
                          String lookupTableValue = lookupTableValuesIterator.next();
                          if (value.trim().equals(lookupTableValue)) {
                            isValueExist = true;
                            break;
                          }
                        }
                      }
                    }
                    if (isValueExist) {
                      input.setModelValue(new String[] {value});
                      target.add(PrismValuePanel.this.get(ID_FEEDBACK));
                    } else {
                      input.error(
                          "Entered value doesn't match any of available values and will not be saved.");
                      target.add(PrismValuePanel.this.get(ID_FEEDBACK));
                    }
                  }
                };

          } else {

            panel =
                new TextPanel<>(
                    id, new PropertyModel<String>(valueWrapperModel, baseExpression), type);
          }

        } else {
          panel =
              new TextPanel<>(
                  id, new PropertyModel<String>(valueWrapperModel, baseExpression), type);
        }
      }
    } else if (item instanceof PrismReference) {
      PrismContext prismContext = item.getPrismContext();
      if (prismContext == null) {
        prismContext = pageBase.getPrismContext();
      }
      QName targetTypeName = ((PrismReferenceDefinition) item.getDefinition()).getTargetTypeName();
      Class targetClass = null;
      if (targetTypeName != null && prismContext != null) {
        targetClass = prismContext.getSchemaRegistry().determineCompileTimeClass(targetTypeName);
      }
      final Class typeClass =
          targetClass != null
              ? targetClass
              : (item.getDefinition().getTypeClassIfKnown() != null
                  ? item.getDefinition().getTypeClassIfKnown()
                  : FocusType.class);
      Collection typeClasses = new ArrayList();

      // HACK HACK MID-3201 MID-3231
      if (isUserOrgItem(item, typeClass)) {
        typeClasses.add(UserType.class);
        typeClasses.add(OrgType.class);
      } else {
        typeClasses.add(typeClass);
      }

      panel =
          new ValueChoosePanel(
              id,
              new PropertyModel<>(valueWrapperModel, "value"),
              item.getValues(),
              false,
              typeClasses);

    } else if (item instanceof PrismContainer<?>) {
      AssociationWrapper itemWrapper = (AssociationWrapper) valueWrapperModel.getObject().getItem();
      final PrismContainer container = (PrismContainer) item;
      PrismContainerDefinition definition = container.getDefinition();
      QName valueType = definition.getTypeName();

      if (ShadowAssociationType.COMPLEX_TYPE.equals(valueType)) {

        PrismContext prismContext = item.getPrismContext();
        if (prismContext == null) {
          prismContext = pageBase.getPrismContext();
        }

        ShadowType shadowType =
            ((ShadowType) itemWrapper.getContainer().getObject().getObject().asObjectable());
        PrismObject<ResourceType> resource = shadowType.getResource().asPrismObject();
        // HACK. The revive should not be here. Revive is no good. The next use of the resource will
        // cause parsing of resource schema. We need some centralized place to maintain live cached
        // copies
        // of resources.
        try {
          resource.revive(prismContext);
        } catch (SchemaException e) {
          throw new SystemException(e.getMessage(), e);
        }
        RefinedResourceSchema refinedSchema;
        CompositeRefinedObjectClassDefinition rOcDef;
        try {
          refinedSchema = RefinedResourceSchema.getRefinedSchema(resource);
          rOcDef =
              refinedSchema.determineCompositeObjectClassDefinition(shadowType.asPrismObject());
        } catch (SchemaException e) {
          throw new SystemException(e.getMessage(), e);
        }
        RefinedAssociationDefinition assocDef = itemWrapper.getRefinedAssociationDefinition();
        RefinedObjectClassDefinition assocTargetDef = assocDef.getAssociationTarget();

        ObjectQuery query =
            getAssociationsSearchQuery(
                prismContext,
                resource,
                assocTargetDef.getTypeName(),
                assocTargetDef.getKind(),
                assocTargetDef.getIntent());

        List values = item.getValues();
        return new AssociationValueChoicePanel(
            id, valueWrapperModel, values, false, ShadowType.class, query, assocTargetDef);
      }
    }

    return panel;
  }