mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-12-22 02:27:58 +01:00
[xdata] Use extra registry for fields in clark notation
If a field name is in clark notation, then lookup the field's type via an extra registry.
This commit is contained in:
parent
ce4f85acf8
commit
1c262471e5
3 changed files with 69 additions and 88 deletions
|
@ -64,4 +64,13 @@ public class XmlUtil {
|
||||||
|
|
||||||
return stringWriter.toString();
|
return stringWriter.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isClarkNotation(String text) {
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This is currently a mediocre heuristic to check for clark notation.
|
||||||
|
return text.charAt(0) == '{';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright 2020 Florian Schmaus
|
* Copyright 2020-2021 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -18,27 +18,26 @@ package org.jivesoftware.smackx.formtypes;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
|
import org.jivesoftware.smack.util.XmlUtil;
|
||||||
import org.jivesoftware.smackx.xdata.FormField;
|
import org.jivesoftware.smackx.xdata.FormField;
|
||||||
import org.jivesoftware.smackx.xdata.TextSingleFormField;
|
import org.jivesoftware.smackx.xdata.TextSingleFormField;
|
||||||
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
import org.jivesoftware.smackx.xdata.packet.DataForm;
|
||||||
|
|
||||||
public class FormFieldRegistry {
|
public class FormFieldRegistry {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(FormFieldRegistry.class.getName());
|
||||||
|
|
||||||
private static final Map<String, Map<String, FormField.Type>> REGISTRY = new HashMap<>();
|
private static final Map<String, Map<String, FormField.Type>> REGISTRY = new HashMap<>();
|
||||||
|
|
||||||
private static final Map<String, FormField.Type> LOOKASIDE_REGISTRY = new HashMap<>();
|
private static final Map<String, FormField.Type> CLARK_NOTATION_FIELD_REGISTRY = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static final Map<String, String> FIELD_NAME_TO_FORM_TYPE = new HashMap<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
register(FormField.FORM_TYPE, FormField.Type.hidden);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("ReferenceEquality")
|
@SuppressWarnings("ReferenceEquality")
|
||||||
public static synchronized void register(DataForm dataForm) {
|
public static void register(DataForm dataForm) {
|
||||||
// TODO: Also allow forms of type 'result'?
|
// TODO: Also allow forms of type 'result'?
|
||||||
if (dataForm.getType() != DataForm.Type.form) {
|
if (dataForm.getType() != DataForm.Type.form) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
|
@ -56,64 +55,57 @@ public class FormFieldRegistry {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
String fieldName = formField.getFieldName();
|
|
||||||
FormField.Type type = formField.getType();
|
FormField.Type type = formField.getType();
|
||||||
|
if (type == FormField.Type.fixed) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String fieldName = formField.getFieldName();
|
||||||
register(formType, fieldName, type);
|
register(formType, fieldName, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void register(String formType, String fieldName, FormField.Type type) {
|
public static void register(String formType, String fieldName, FormField.Type fieldType) {
|
||||||
|
StringUtils.requireNotNullNorEmpty(fieldName, "fieldName must be provided");
|
||||||
|
Objects.requireNonNull(fieldType);
|
||||||
|
|
||||||
if (formType == null) {
|
if (formType == null) {
|
||||||
FormFieldInformation formFieldInformation = lookup(fieldName);
|
if (XmlUtil.isClarkNotation(fieldName)) {
|
||||||
if (formFieldInformation != null) {
|
CLARK_NOTATION_FIELD_REGISTRY.put(fieldName, fieldType);
|
||||||
if (Objects.equals(formType, formFieldInformation.formType)
|
}
|
||||||
&& type.equals(formFieldInformation.formFieldType)) {
|
|
||||||
// The field is already registered, nothing to do here.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String message = "There is already a field with the name'" + fieldName
|
|
||||||
+ "' registered with the field type '" + formFieldInformation.formFieldType
|
|
||||||
+ "', while this tries to register the field with the type '" + type + '\'';
|
|
||||||
throw new IllegalArgumentException(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOOKASIDE_REGISTRY.put(fieldName, type);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FormField.Type previousType;
|
||||||
|
synchronized (REGISTRY) {
|
||||||
Map<String, FormField.Type> fieldNameToType = REGISTRY.get(formType);
|
Map<String, FormField.Type> fieldNameToType = REGISTRY.get(formType);
|
||||||
if (fieldNameToType == null) {
|
if (fieldNameToType == null) {
|
||||||
fieldNameToType = new HashMap<>();
|
fieldNameToType = new HashMap<>();
|
||||||
REGISTRY.put(formType, fieldNameToType);
|
REGISTRY.put(formType, fieldNameToType);
|
||||||
} else {
|
} else {
|
||||||
FormField.Type previousType = fieldNameToType.get(fieldName);
|
previousType = fieldNameToType.get(fieldName);
|
||||||
if (previousType != null && previousType != type) {
|
if (previousType != null && previousType != fieldType) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fieldNameToType.put(fieldName, type);
|
previousType = fieldNameToType.put(fieldName, fieldType);
|
||||||
|
}
|
||||||
FIELD_NAME_TO_FORM_TYPE.put(fieldName, formType);
|
if (previousType != null && fieldType != previousType) {
|
||||||
|
LOGGER.warning("Form field registry inconsitency detected: Registered field '" + fieldName + "' of type " + fieldType + " but previous type was " + previousType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized void register(String fieldName, FormField.Type type) {
|
|
||||||
FormField.Type previousType = LOOKASIDE_REGISTRY.get(fieldName);
|
|
||||||
if (previousType != null) {
|
|
||||||
if (previousType == type) {
|
|
||||||
// Nothing to do here.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("There is already a field with the name '" + fieldName
|
|
||||||
+ "' registered with type " + previousType
|
|
||||||
+ ", while trying to register this field with type '" + type + "'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOOKASIDE_REGISTRY.put(fieldName, type);
|
public static FormField.Type lookup(String formType, String fieldName) {
|
||||||
|
if (formType == null) {
|
||||||
|
if (!XmlUtil.isClarkNotation(fieldName)) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized FormField.Type lookup(String formType, String fieldName) {
|
return CLARK_NOTATION_FIELD_REGISTRY.get(fieldName);
|
||||||
if (formType != null) {
|
}
|
||||||
|
|
||||||
|
synchronized (REGISTRY) {
|
||||||
Map<String, FormField.Type> fieldNameToTypeMap = REGISTRY.get(formType);
|
Map<String, FormField.Type> fieldNameToTypeMap = REGISTRY.get(formType);
|
||||||
if (fieldNameToTypeMap != null) {
|
if (fieldNameToTypeMap != null) {
|
||||||
FormField.Type type = fieldNameToTypeMap.get(fieldName);
|
FormField.Type type = fieldNameToTypeMap.get(fieldName);
|
||||||
|
@ -121,38 +113,13 @@ public class FormFieldRegistry {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
formType = FIELD_NAME_TO_FORM_TYPE.get(fieldName);
|
|
||||||
if (formType != null) {
|
|
||||||
FormField.Type type = lookup(formType, fieldName);
|
|
||||||
if (type != null) {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to lookaside registry.
|
|
||||||
return LOOKASIDE_REGISTRY.get(fieldName);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static synchronized FormFieldInformation lookup(String fieldName) {
|
|
||||||
String formType = FIELD_NAME_TO_FORM_TYPE.get(fieldName);
|
|
||||||
FormField.Type type = lookup(formType, fieldName);
|
|
||||||
if (type == null) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new FormFieldInformation(type, formType);
|
public static synchronized FormField.Type lookup(String fieldName) {
|
||||||
|
return lookup(null, fieldName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class FormFieldInformation {
|
|
||||||
public final FormField.Type formFieldType;
|
|
||||||
public final String formType;
|
|
||||||
|
|
||||||
|
|
||||||
private FormFieldInformation(FormField.Type formFieldType, String formType) {
|
|
||||||
this.formFieldType = formFieldType;
|
|
||||||
this.formType = formType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,6 +207,10 @@ public class DataFormProvider extends ExtensionElementProvider<DataForm> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == null) {
|
if (type == null) {
|
||||||
|
// The field name 'FORM_TYPE' is magic.
|
||||||
|
if (fieldName.equals(FormField.FORM_TYPE)) {
|
||||||
|
type = FormField.Type.hidden;
|
||||||
|
} else {
|
||||||
// If no field type was explicitly provided, then we need to lookup the
|
// If no field type was explicitly provided, then we need to lookup the
|
||||||
// field's type in the registry.
|
// field's type in the registry.
|
||||||
type = FormFieldRegistry.lookup(formType, fieldName);
|
type = FormFieldRegistry.lookup(formType, fieldName);
|
||||||
|
@ -217,6 +221,7 @@ public class DataFormProvider extends ExtensionElementProvider<DataForm> {
|
||||||
type = FormField.Type.text_single;
|
type = FormField.Type.text_single;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FormField.Builder<?, ?> builder;
|
FormField.Builder<?, ?> builder;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
Loading…
Reference in a new issue