private void resetXsdSimpleTypeUuids(final Resource resource) throws Exception {
    if (resource instanceof XSDResourceImpl) {
      final XSDResourceImpl xsdResource = (XSDResourceImpl) resource;
      final XSDSchema schema = xsdResource.getSchema();
      if (schema != null) {
        for (final Iterator iter = schema.getContents().iterator(); iter.hasNext(); ) {
          EObject eObj = (EObject) iter.next();

          // Only process global simple type definitions ...
          if (eObj instanceof XSDSimpleTypeDefinition) {
            final XSDSimpleTypeDefinition type = (XSDSimpleTypeDefinition) eObj;

            // Get the application information ...
            final XSDAnnotation annotation = type.getAnnotation();

            // If no annotation exists then no UUID attribute exists to reset ...
            if (annotation == null) {
              continue;
            }
            for (final Iterator appInfos = annotation.getApplicationInformation().iterator();
                appInfos.hasNext(); ) {
              final Element appInfo = (Element) appInfos.next();
              String uuid = appInfo.getAttribute(UUID_ATTRIBUTE_NAME);
              if (uuid != null) {
                uuid = IDGenerator.getInstance().create().toString();
                appInfo.setAttribute(UUID_ATTRIBUTE_NAME, uuid);
                uuid = appInfo.getAttribute(UUID_ATTRIBUTE_NAME);
              }
            }
          }
        }
      }
    }
  }
  /**
   * This method gets all relevant facets. It behaves differently from a simple getFacets() call in
   * that enumerations are not congealed.
   */
  public static Set getUsefulFacets(XSDSimpleTypeDefinition type) {
    Set rv = new HashSet();

    Iterator itor = type.getFacets().iterator();
    while (itor.hasNext()) {
      XSDConstrainingFacet facet = (XSDConstrainingFacet) itor.next();
      if (facet instanceof XSDRepeatableFacet && facet.getElement() == null) {
        // this is a fake pattern or enum; get the individual entries:
        if (facet instanceof XSDPatternFacet) {
          XSDPatternFacet pf = (XSDPatternFacet) facet;
          XSDSimpleTypeDefinition realParent = (XSDSimpleTypeDefinition) pf.getContainer();
          // only add patterns if they belong to this type:
          if (realParent == type) {
            rv.addAll(realParent.getPatternFacets());
          } // endif
        } else if (facet instanceof XSDEnumerationFacet) {
          XSDEnumerationFacet ef = (XSDEnumerationFacet) facet;
          XSDSimpleTypeDefinition realParent = (XSDSimpleTypeDefinition) ef.getContainer();
          // only add enums if they belong to this type:
          if (realParent == type) {
            rv.addAll(realParent.getEnumerationFacets());
          } // endif
        } // endif -- which kind of repeatable?
      } else {
        rv.add(facet);
      } // endif -- fake facet
    } // endwhile -- facets

    return rv;
  }
Example #3
0
 /**
  * Return the type definition for the primitive with name xsdName (note, this is not the
  * human-readable name, but the actual XSD type name.) Return null if a type with this name is not
  * in the list of all primitives
  *
  * @param xsdName
  * @return the simple type definition with the given xsdName
  */
 public static XSDSimpleTypeDefinition getPrimitive(String xsdName) {
   for (XSDSimpleTypeDefinition next : getAdvancedPrimitives()) {
     if (next.getName().equals(xsdName)) {
       return next;
     }
   }
   return null;
 }
  public static FacetValue getEnterpriseFacetValue(final XSDSimpleTypeDefinition startingType) {
    FacetValue fv = new FacetValue();

    final XSDSimpleTypeDefinition definingEnterpriseType = getDefiningEnterpriseType(startingType);
    fv.type = startingType;
    EnterpriseDatatypeInfo edi =
        ModelerCore.getWorkspaceDatatypeManager().getEnterpriseDatatypeInfo(definingEnterpriseType);
    fv.value = edi.getRuntimeType();

    if (startingType == definingEnterpriseType) {
      // this "facet" set in the specified type, so it is not default.
      // check parent for real default:
      final XSDSimpleTypeDefinition dftDefiner =
          getDefiningEnterpriseType(definingEnterpriseType.getBaseTypeDefinition());
      EnterpriseDatatypeInfo ediDft =
          ModelerCore.getWorkspaceDatatypeManager().getEnterpriseDatatypeInfo(dftDefiner);
      fv.defaultValue = ediDft.getRuntimeType();
      // set a fake facet to allow inherited checks to work:
      fv.facet =
          new XSDConstrainingFacetImpl() {
            @Override
            public String getFacetName() {
              return "This is not a real facet!"; //$NON-NLS-1$
            }

            @Override
            public XSDConcreteComponent getContainer() {
              return dftDefiner;
            }
          }; // endanon
    } else {
      // facet set by a parent, so it is default:
      fv.defaultValue = fv.value;
      // set a fake facet to allow inherited checks to work:
      fv.facet =
          new XSDConstrainingFacetImpl() {
            @Override
            public String getFacetName() {
              return "This is not a real facet!"; //$NON-NLS-1$
            }

            @Override
            public XSDConcreteComponent getContainer() {
              return definingEnterpriseType;
            }
          }; // endanon
    } // endif

    Boolean rtFixed = edi.getRuntimeTypeFixed();
    if (rtFixed != null) {
      fv.isFixedLocal = rtFixed.booleanValue();
    } // endif -- fixed null

    return fv;
  }
  public static boolean isSubtypeOf(
      XSDSimpleTypeDefinition startFrom, XSDSimpleTypeDefinition lookFor) {
    XSDSimpleTypeDefinition current = startFrom;
    XSDSimpleTypeDefinition root = startFrom.getRootTypeDefinition();

    while (current != root) {
      if (current == lookFor) {
        return true;
      } // endif
      current = current.getBaseTypeDefinition();
    } // endwhile

    return false;
  }
 public static void removeFacet(XSDSimpleTypeDefinition type, XSDConstrainingFacet facet) {
   try {
     ModelerCore.getModelEditor().removeValue(type, facet, type.getFacetContents());
   } catch (ModelerCoreException err) {
     ModelerXsdUiConstants.Util.log(err);
   } // endtry
 }
  private static XSDSimpleTypeDefinition getDefiningEnterpriseType(
      XSDSimpleTypeDefinition simpleType) {
    XSDSimpleTypeDefinition root = simpleType.getRootTypeDefinition();
    XSDSimpleTypeDefinition rv = root; // if nothing else is found, root will be right.

    while (simpleType != root) {
      if (ModelerCore.getWorkspaceDatatypeManager().isEnterpriseDatatype(simpleType)) {
        rv = simpleType;
        break;
      } // endif

      // try the parent:
      simpleType = simpleType.getBaseTypeDefinition();
    } // endwhile

    return rv;
  }
  private Object[] getXSDSimpleTypeDefinitionChildren_ATOMIC(XSDSimpleTypeDefinition parent) {
    ArrayList<Object> list = new ArrayList<Object>();
    // add Base Type if not a pre-defined type
    if (parent != null
        && parent.getSchema() != null
        && parent.getSchema().getSchemaForSchema() != null) {
      if (!parent.getSchema().getSchemaForSchema().getTypeDefinitions().contains(parent)) {
        list.add(parent.getBaseTypeDefinition());
      }
    }

    if (!Util.isBuildInType(parent)) {
      list.addAll(parent.getFacetContents());
    }

    return list.toArray(new Object[list.size()]);
  }
  public static boolean needsNumeric(XSDSimpleTypeDefinition simpleType) {
    // check main first:
    if (ModelerCore.getWorkspaceDatatypeManager().isNumeric(simpleType)) return true;

    // above only checks against decimal:
    XSDSimpleTypeDefinition base = simpleType.getBaseTypeDefinition();

    if (base != null) {
      String basename = base.getName();
      for (int i = 0; i < NUMERIC_TYPES.length; i++) {
        String numericTypeName = NUMERIC_TYPES[i];
        if (numericTypeName.equalsIgnoreCase(basename)) {
          return true;
        } // endif
      } // endfor
    } // endif

    return false;
  }
Example #10
0
  protected void processSimpleTypeDefinition(XSDSimpleTypeDefinition type, Node node)
      throws RepositoryException {
    boolean isAnonymous = type.getName() == null;
    String nodeName = isAnonymous ? XsdLexicon.SIMPLE_TYPE : type.getName();
    // This is a normal simple type definition ...
    logger.debug("Simple type: '{0}' in ns '{1}' ", type.getName(), type.getTargetNamespace());

    Node typeNode = node.addNode(nodeName, XsdLexicon.SIMPLE_TYPE_DEFINITION);
    typeNode.setProperty(XsdLexicon.NAMESPACE, type.getTargetNamespace());
    if (!isAnonymous) {
      typeNode.setProperty(XsdLexicon.NC_NAME, type.getName());
      registerForSymbolSpace(
          TYPE_DEFINITIONS, type.getTargetNamespace(), type.getName(), typeNode.getIdentifier());
    }
    processTypeFacets(type, typeNode, type.getBaseType());
    processNonSchemaAttributes(type, typeNode);
  }
Example #11
0
  public static XSDConstrainingFacet addOrSetFacetValue(
      XSDSimpleTypeDefinition type, String facetName, FacetValue fv) {
    XSDConstrainingFacet workFacet = fv.facet;
    // do we need to add?
    if (fv.facet == null || fv.facet.getContainer() != type) {
      // need to add to this type:
      boolean inclusiveness = false;
      if (fv.value instanceof InclusiveInteger) {
        inclusiveness = ((InclusiveInteger) fv.value).isInclusive;
      } // endif

      // remove any facets with opposite inclusiveness:
      if (facetName == FAKE_FACET_MAXIMUM || facetName == FAKE_FACET_MINIMUM) {
        // go ahead and remove:
        removeFacet(type, facetName);
      } // endif -- using fake facets?

      workFacet = createFacet(facetName, inclusiveness);

      try {
        ModelerCore.getModelEditor().addValue(type, workFacet, type.getFacetContents());
      } catch (ModelerCoreException err) {
        ModelerXsdUiConstants.Util.log(err);
      } // endtry
    } // endif

    // set main value:
    if (!FormUtil.safeEquals(fv.value, getMainFacetValue(workFacet))) {
      // only set if changed:
      workFacet = setMainFacetValue(type, workFacet, fv.value);
      // in case this is a bounds facet and we swapped them out:
      fv.facet = workFacet;
    } // endif

    // set description:
    String existingDesc = ModelObjectUtilities.getDescription(workFacet);
    if (fv.description != null) {
      // new not null:
      if (!fv.description.equals(existingDesc)) {
        // description changed to a nonnull value:
        ModelObjectUtilities.setDescription(workFacet, fv.description, type);
      } // endif -- different
    } else if (existingDesc != null && existingDesc.length() > 0) {
      // new null, old not null:
      ModelObjectUtilities.setDescription(workFacet, " ", type); // $NON-NLS-1$
    } // endif

    // Lastly, set fixed if applicable:
    setFixed(workFacet, fv.isFixedLocal);

    return workFacet;
  }
Example #12
0
  /**
   * @param location the XSDSchema object to add this type to.
   * @param typeName the name to give the newly created type.
   * @param baseType (optional) if not null, use this type as the base type of the new type.
   * @return
   */
  public static XSDSimpleTypeDefinition createAtomicSimpleTypeDefinintion(
      XSDSchema location, String typeName, XSDSimpleTypeDefinition baseType) {
    XSDSimpleTypeDefinition std =
        (XSDSimpleTypeDefinition)
            XSDFactory.eINSTANCE.create(XSDPackage.eINSTANCE.getXSDSimpleTypeDefinition());
    std.setName(typeName);
    // defect 18444 - make sure things are wrapped in transactions
    try {
      ModelerCore.getModelEditor().addValue(location, std, location.getContents());

      if (baseType != null) {
        ModelerCore.getDatatypeManager(std).setBasetypeDefinition(std, baseType);
      } else {
        XSDSimpleTypeDefinition defaultBaseType = getDefaultBaseType();
        ModelerCore.getDatatypeManager(std).setBasetypeDefinition(std, defaultBaseType);
      } // endif
    } catch (ModelerCoreException ex) {
      ModelerXsdUiConstants.Util.log(ex);
    } // endtry

    return std;
  }
Example #13
0
  private static void removeFacet(XSDSimpleTypeDefinition type, String facetName) {
    // resolve the name, in case it is one of the bounds facets:
    String nameEx = getRealFacetName(facetName, false);
    String nameIn = getRealFacetName(facetName, true); // most of the time, name == name2

    Iterator itor = type.getFacetContents().iterator();
    while (itor.hasNext()) {
      XSDConstrainingFacet facet = (XSDConstrainingFacet) itor.next();
      String thisName = facet.getFacetName();
      if (nameEx.equals(thisName) || nameIn.equals(thisName)) {
        itor.remove();
      } // endif
    } // endwhile
  }
  protected Object[] getXSDSimpleTypeDefinitionChildren(XSDSimpleTypeDefinition parent) {
    Object[] result = null;

    switch (parent.getVariety()) {
      case ATOMIC_LITERAL:
        result = getXSDSimpleTypeDefinitionChildren_ATOMIC(parent);
        break;
      case LIST_LITERAL:
        result = getXSDSimpleTypeDefinitionChildren_LIST(parent);
        break;
      case UNION_LITERAL:
        result = getXSDSimpleTypeDefinitionChildren_UNION(parent);
        break;
      default:
        result = new Object[0];
    }

    return result;
  }
 private Object[] getXSDSimpleTypeDefinitionChildren_LIST(XSDSimpleTypeDefinition parent) {
   // FIXME: How do we indicate it is a LIST?
   return new XSDSimpleTypeDefinition[] {parent.getBaseTypeDefinition()};
 }
 private Object[] getXSDSimpleTypeDefinitionChildren_UNION(XSDSimpleTypeDefinition parent) {
   return parent
       .getMemberTypeDefinitions()
       .toArray(new XSDSimpleTypeDefinition[parent.getMemberTypeDefinitions().size()]);
 }
Example #17
0
  protected void processTypeFacets(
      XSDSimpleTypeDefinition type, Node typeNode, XSDTypeDefinition baseType)
      throws RepositoryException {
    if (baseType == null) {
      baseType = type.getBaseType();
    }
    if (baseType == type) {
      // The base type is the anytype ...
      baseType =
          type.getSchema()
              .getSchemaForSchema()
              .resolveSimpleTypeDefinition("http://www.w3.org/2001/XMLSchema", "anyType");
    }
    if (baseType != null) {
      typeNode.setProperty(XsdLexicon.BASE_TYPE_NAME, baseType.getName());
      typeNode.setProperty(XsdLexicon.BASE_TYPE_NAMESPACE, baseType.getTargetNamespace());
      setReference(
          typeNode,
          XsdLexicon.BASE_TYPE_REFERENCE,
          TYPE_DEFINITIONS,
          baseType.getTargetNamespace(),
          baseType.getName());
    }

    processFacet(
        type.getEffectiveMaxLengthFacet(), typeNode, XsdLexicon.MAX_LENGTH, PropertyType.LONG);
    processFacet(type.getMaxLengthFacet(), typeNode, XsdLexicon.MAX_LENGTH, PropertyType.LONG);
    processFacet(
        type.getEffectiveMinLengthFacet(), typeNode, XsdLexicon.MIN_LENGTH, PropertyType.LONG);
    processFacet(type.getMinLengthFacet(), typeNode, XsdLexicon.MIN_LENGTH, PropertyType.LONG);
    processFacet(
        type.getEffectiveMaxFacet(), typeNode, XsdLexicon.MAX_VALUE_EXCLUSIVE, PropertyType.LONG);
    processFacet(
        type.getMaxExclusiveFacet(), typeNode, XsdLexicon.MAX_VALUE_EXCLUSIVE, PropertyType.LONG);
    processFacet(
        type.getEffectiveMinFacet(), typeNode, XsdLexicon.MIN_VALUE_EXCLUSIVE, PropertyType.LONG);
    processFacet(
        type.getMinExclusiveFacet(), typeNode, XsdLexicon.MIN_VALUE_EXCLUSIVE, PropertyType.LONG);
    processFacet(
        type.getMaxInclusiveFacet(), typeNode, XsdLexicon.MAX_VALUE_INCLUSIVE, PropertyType.LONG);
    processFacet(
        type.getMinInclusiveFacet(), typeNode, XsdLexicon.MIN_VALUE_INCLUSIVE, PropertyType.LONG);
    processFacet(
        type.getEffectiveTotalDigitsFacet(), typeNode, XsdLexicon.TOTAL_DIGITS, PropertyType.LONG);
    processFacet(type.getTotalDigitsFacet(), typeNode, XsdLexicon.TOTAL_DIGITS, PropertyType.LONG);
    processFacet(
        type.getEffectiveFractionDigitsFacet(),
        typeNode,
        XsdLexicon.FRACTION_DIGITS,
        PropertyType.LONG);
    processFacet(
        type.getFractionDigitsFacet(), typeNode, XsdLexicon.FRACTION_DIGITS, PropertyType.LONG);

    processFacet(
        type.getEffectiveWhiteSpaceFacet(), typeNode, XsdLexicon.WHITESPACE, PropertyType.STRING);
    processFacet(type.getWhiteSpaceFacet(), typeNode, XsdLexicon.WHITESPACE, PropertyType.STRING);

    processFacet(
        type.getEffectivePatternFacet(), typeNode, XsdLexicon.PATTERN, PropertyType.STRING);
    @SuppressWarnings("unchecked")
    List<XSDPatternFacet> patternFacets = type.getPatternFacets();
    processFacetsList(patternFacets, typeNode, XsdLexicon.PATTERN);

    processFacet(
        type.getEffectiveEnumerationFacet(),
        typeNode,
        XsdLexicon.ENUMERATED_VALUES,
        PropertyType.STRING);
    @SuppressWarnings("unchecked")
    List<XSDEnumerationFacet> enumFacets = type.getEnumerationFacets();
    processFacetsList(enumFacets, typeNode, XsdLexicon.ENUMERATED_VALUES);

    @SuppressWarnings("unchecked")
    List<XSDSimpleFinal> finalFacets2 = type.getFinal();
    processEnumerators(finalFacets2, typeNode, XsdLexicon.FINAL);

    processAnnotation(type.getAnnotation(), typeNode);
  }
Example #18
0
  /**
   * Sets the core value of the specified facet. If facet cannot be properly modified to match fv,
   * facets will be added or removed as necessary to make it work. This occurs when a min or max
   * value is changed from inclusive to exclusive, and when dealing with patterns and enumerations.
   *
   * @param facet
   * @param fv
   */
  private static XSDConstrainingFacet setMainFacetValue(
      XSDSimpleTypeDefinition type, XSDConstrainingFacet facet, Object value) {
    int facetClassifierID = facet.eClass().getClassifierID();
    switch (facetClassifierID) {
      case XSDPackage.XSD_LENGTH_FACET:
        {
          XSDLengthFacet lf = (XSDLengthFacet) facet;
          if (value instanceof Integer) {
            Integer i = (Integer) value;
            lf.setLexicalValue(i.toString());
          } else if (value instanceof InclusiveInteger) {
            InclusiveInteger ii = (InclusiveInteger) value;
            lf.setLexicalValue(Integer.toString(ii.value));
          } // endif
        }
        break;
      case XSDPackage.XSD_MAX_LENGTH_FACET:
        {
          XSDMaxLengthFacet mf = (XSDMaxLengthFacet) facet;
          if (value instanceof Integer) {
            Integer i = (Integer) value;
            mf.setLexicalValue(i.toString());
          } else if (value instanceof InclusiveInteger) {
            InclusiveInteger ii = (InclusiveInteger) value;
            mf.setLexicalValue(Integer.toString(ii.value));
          } // endif
        }
        break;
      case XSDPackage.XSD_MIN_LENGTH_FACET:
        {
          XSDMinLengthFacet mf = (XSDMinLengthFacet) facet;
          if (value instanceof Integer) {
            Integer i = (Integer) value;
            mf.setLexicalValue(i.toString());
          } else if (value instanceof InclusiveInteger) {
            InclusiveInteger ii = (InclusiveInteger) value;
            mf.setLexicalValue(Integer.toString(ii.value));
          } // endif
        }
        break;
      case XSDPackage.XSD_PATTERN_FACET:
        {
          XSDPatternFacet pf = (XSDPatternFacet) facet;
          pf.setLexicalValue((String) value);
        }
        break;
      case XSDPackage.XSD_ENUMERATION_FACET:
        {
          XSDEnumerationFacet ef = (XSDEnumerationFacet) facet;
          ef.setLexicalValue((String) value);
        }
        break;
      case XSDPackage.XSD_WHITE_SPACE_FACET:
        {
          XSDWhiteSpaceFacet wf = (XSDWhiteSpaceFacet) facet;
          if (value instanceof String) {
            String white = (String) value;
            wf.setLexicalValue(white);
          } // endif
        }
        break;
      case XSDPackage.XSD_MIN_EXCLUSIVE_FACET:
      case XSDPackage.XSD_MIN_INCLUSIVE_FACET:
        {
          XSDMinFacet mf = (XSDMinFacet) facet;
          if (value instanceof Integer) {
            Integer i = (Integer) value;
            mf.setLexicalValue(i.toString());
          } else if (value instanceof InclusiveInteger) {
            InclusiveInteger ii = (InclusiveInteger) value;
            if (ii.isInclusive == mf.isInclusive()) {
              // same inclusive types, don't need to do anything crazy
              mf.setLexicalValue(Integer.toString(ii.value));
            } else {
              XSDMinFacet mf2;
              if (ii.isInclusive) {
                mf2 = XSDFactory.eINSTANCE.createXSDMinInclusiveFacet();
              } else {
                mf2 = XSDFactory.eINSTANCE.createXSDMinExclusiveFacet();
              } // endif
              mf2.setLexicalValue(Integer.toString(ii.value));
              try {
                // remove old:
                ModelerCore.getModelEditor().removeValue(type, mf, type.getFacetContents());
                // add the copy:
                ModelerCore.getModelEditor().addValue(type, mf2, type.getFacetContents());
                // update the return value:
                facet = mf2;
              } catch (ModelerCoreException err) {
                ModelerXsdUiConstants.Util.log(err);
              } // endtry

              return mf2;
            } // endif -- same inclusive
          } // endif -- integer or iinteger
        }
        break;
      case XSDPackage.XSD_MAX_EXCLUSIVE_FACET:
      case XSDPackage.XSD_MAX_INCLUSIVE_FACET:
        {
          XSDMaxFacet mf = (XSDMaxFacet) facet;
          if (value instanceof Integer) {
            Integer i = (Integer) value;
            mf.setLexicalValue(i.toString());
          } else if (value instanceof InclusiveInteger) {
            InclusiveInteger ii = (InclusiveInteger) value;
            if (ii.isInclusive == mf.isInclusive()) {
              // same inclusive types, don't need to do anything crazy
              mf.setLexicalValue(Integer.toString(ii.value));
            } else {
              XSDMaxFacet mf2;
              if (ii.isInclusive) {
                mf2 = XSDFactory.eINSTANCE.createXSDMaxInclusiveFacet();
              } else {
                mf2 = XSDFactory.eINSTANCE.createXSDMaxExclusiveFacet();
              } // endif
              mf2.setLexicalValue(Integer.toString(ii.value));
              try {
                // remove old:
                ModelerCore.getModelEditor().removeValue(type, mf, type.getFacetContents());
                // add the copy:
                ModelerCore.getModelEditor().addValue(type, mf2, type.getFacetContents());
                // update the return value:
                facet = mf2;
              } catch (ModelerCoreException err) {
                ModelerXsdUiConstants.Util.log(err);
              } // endtry

              return mf2;
            } // endif -- same inclusive
          } // endif -- integer or iinteger
        }
        break;
      case XSDPackage.XSD_FRACTION_DIGITS_FACET:
        {
          XSDFractionDigitsFacet ff = (XSDFractionDigitsFacet) facet;
          if (value instanceof Integer) {
            Integer i = (Integer) value;
            ff.setLexicalValue(i.toString());
          } else if (value instanceof InclusiveInteger) {
            InclusiveInteger ii = (InclusiveInteger) value;
            ff.setLexicalValue(Integer.toString(ii.value));
          } // endif
        }
        break;
      case XSDPackage.XSD_TOTAL_DIGITS_FACET:
        {
          XSDTotalDigitsFacet tf = (XSDTotalDigitsFacet) facet;
          if (value instanceof Integer) {
            Integer i = (Integer) value;
            tf.setLexicalValue(i.toString());
          } else if (value instanceof InclusiveInteger) {
            InclusiveInteger ii = (InclusiveInteger) value;
            tf.setLexicalValue(Integer.toString(ii.value));
          } // endif
        }
        break;

      default:
        ModelerXsdUiConstants.Util.log(
            ModelerXsdUiConstants.Util.getString(ERROR_KEY_UNUSABLE_FACET, facet));
        break;
    } // endswitch

    return facet;
  }