docs: final JcrValue asType( int type,
                             boolean force ) throws ValueFormatException {
          if (!force && type == this.type) {
              return this.withTypeAndValue(this.type, this.value);
          }
  
          Object value = this.value;
          switch (type) {
              case PropertyType.BOOLEAN:
                  // Make sure the existing value is valid per the current type.
                  // This is required if we rely upon the value factories to cast correctly.
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY) {
                      throw createValueFormatException(boolean.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getBooleanFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
  
              case PropertyType.DATE:
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.DOUBLE
                      && this.type != PropertyType.LONG) {
                      throw createValueFormatException(Calendar.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getDateFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
  
              case PropertyType.NAME:
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.PATH) {
                      throw createValueFormatException(Name.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getNameFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
  
              case PropertyType.PATH:
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.NAME) {
                      throw createValueFormatException(Path.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getPathFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
  
              case PropertyType.REFERENCE:
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY
                      && this.type != PropertyType.WEAKREFERENCE) {
                      throw createValueFormatException(Node.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getReferenceFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
              case PropertyType.WEAKREFERENCE:
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.REFERENCE) {
                      throw createValueFormatException(Node.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getWeakReferenceFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
              case org.modeshape.jcr.api.PropertyType.SIMPLE_REFERENCE:
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.REFERENCE
                          && this.type != PropertyType.WEAKREFERENCE) {
                      throw createValueFormatException(Node.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getSimpleReferenceFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
              case PropertyType.DOUBLE:
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.LONG
                      && this.type != PropertyType.DATE) {
                      throw createValueFormatException(double.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getDoubleFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
              case PropertyType.LONG:
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.DOUBLE
                      && this.type != PropertyType.DATE) {
                      throw createValueFormatException(long.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getLongFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
              case PropertyType.DECIMAL:
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.DOUBLE
                      && this.type != PropertyType.LONG && this.type != PropertyType.DATE) {
                      throw createValueFormatException(BigDecimal.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getDecimalFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
              case PropertyType.URI:
                  if (this.type != PropertyType.STRING && this.type != PropertyType.BINARY && this.type != PropertyType.URI) {
                      throw createValueFormatException(URI.class);
                  }
                  try {
                      return this.withTypeAndValue(type, factories().getUriFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
  
                  // Anything can be converted to these types
              case PropertyType.BINARY:
                  try {
                      return this.withTypeAndValue(type, factories().getBinaryFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
              case PropertyType.STRING:
                  try {
                      return this.withTypeAndValue(type, factories().getStringFactory().create(value));
                  } catch (org.modeshape.jcr.value.ValueFormatException vfe) {
                      throw createValueFormatException(vfe);
                  }
              case PropertyType.UNDEFINED:
                  return this.withTypeAndValue(this.type, this.value);
  
              default:
                  assert false : "Unexpected JCR property type " + type;
                  // This should still throw an exception even if assertions are turned off
                  throw new IllegalStateException("Invalid property type " + type);
          }
      }