package org.ovirt.engine.ui.uicommonweb.models.vms.key_value;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.ovirt.engine.core.compat.StringHelper;
import org.ovirt.engine.ui.uicommonweb.validation.IValidation;
import org.ovirt.engine.ui.uicommonweb.validation.RegexValidation;
import org.ovirt.engine.ui.uicommonweb.validation.ValidationResult;
import org.ovirt.engine.ui.uicompat.ConstantsManager;
public class KeyValueModel extends BaseKeyModel {
public static final String PROPERTIES_DELIMETER = ";"; //$NON-NLS-1$
public static final String KEY_VALUE_DELIMETER = "="; //$NON-NLS-1$
private String saveEntity;
public KeyValueModel() {
super(ConstantsManager.getInstance().getConstants().pleaseSelectKey(), ConstantsManager.getInstance().getConstants().noKeyAvailable());
}
Map<String, String> allKeyValueMap;
Map<String, List<String>> allRegExKeys;
private Map<String, String> keyValueMap_used = new HashMap<>();
@Override
protected void initLineModel(KeyValueLineModel keyValueLineModel, String key) {
if (isKeyValid(key)) {
boolean constrainedValue = allRegExKeys.containsKey(key);
keyValueLineModel.getValue().setIsAvailable(!constrainedValue);
keyValueLineModel.getValues().setIsAvailable(constrainedValue);
if (constrainedValue) {
keyValueLineModel.getValues().setItems(allRegExKeys.get(key));
}
} else {
keyValueLineModel.getValue().setIsAvailable(false);
keyValueLineModel.getValues().setIsAvailable(false);
keyValueLineModel.getValue().setEntity("");
keyValueLineModel.getValues().setSelectedItem(null);
keyValueLineModel.getValues().setItems(null);
}
}
@Override
protected void setValueByKey(KeyValueLineModel lineModel, String key) {
if (allRegExKeys.containsKey(key)) {
lineModel.getValues().setSelectedItem(keyValueMap_used.get(key));
} else {
lineModel.getValue().setEntity(keyValueMap_used.get(key));
}
}
public void deserialize(String value) {
if (allKeyValueMap == null) {
saveEntity = value;
return;
}
//always reset the list of items when the item changes
keyValueMap_used = new HashMap<>();
if (value != null && !value.isEmpty()) {
String[] lines = value.split(PROPERTIES_DELIMETER);
String[] splitLine;
for (String line : lines) {
if (line.isEmpty()) {
continue;
}
splitLine = line.split(KEY_VALUE_DELIMETER, 2);
String key = splitLine[0];
if (allKeyValueMap.containsKey(key)) {
keyValueMap_used.put(key, splitLine[1]);
}
}
}
init(allKeyValueMap.keySet(), keyValueMap_used.keySet());
}
public void setKeyValueString(List<String> lines) {
if (lines == null) {
return;
}
allKeyValueMap = new HashMap<>();
allRegExKeys = new HashMap<>();
RegexValidation regexValidation = new RegexValidation();
regexValidation.setExpression("\\^\\((([a-zA-Z0-9_]+[|]+)*)[a-zA-Z0-9_]+\\)\\$"); //$NON-NLS-1$
String[] splitLine;
for (String line : lines) {
if (line.isEmpty()) {
continue;
}
splitLine = line.split(KEY_VALUE_DELIMETER, 2);
String key = splitLine[0];
allKeyValueMap.put(key, splitLine[1]);
ValidationResult valid = regexValidation.validate(allKeyValueMap.get(key));
if (valid.getSuccess()) {
String[] values = allKeyValueMap.get(key)
.substring(2, allKeyValueMap.get(key).length() - 2)
.split("\\|"); //$NON-NLS-1$
allRegExKeys.put(key, Arrays.asList(values));
}
}
deserialize(saveEntity);
}
public void setKeyValueMap(Map<String, String> keyValueMap) {
if (keyValueMap == null) {
return;
}
List<String> lines = new ArrayList<>();
for (Map.Entry<String, String> entry : keyValueMap.entrySet()) {
lines.add(entry.getKey() + '=' + entry.getValue());
}
setKeyValueString(lines);
}
public String serialize() {
StringBuilder builder = new StringBuilder();
if (getItems() == null) {
return "";
}
for (KeyValueLineModel keyValueLineModel : getItems()) {
String key = keyValueLineModel.getKeys().getSelectedItem();
if (!isKeyValid(key)) {
continue;
}
builder.append(key);
builder.append(KEY_VALUE_DELIMETER);
if (keyValueLineModel.getValue().getIsAvailable()) {
builder.append(keyValueLineModel.getValue().getEntity());
} else if (keyValueLineModel.getValues().getIsAvailable()) {
builder.append(keyValueLineModel.getValues().getSelectedItem());
}
builder.append(PROPERTIES_DELIMETER);
}
// remove the last delimiter
if (builder.toString().endsWith(PROPERTIES_DELIMETER)) {
return builder.subSequence(0, builder.length() - PROPERTIES_DELIMETER.length()).toString();
}
return builder.toString();
}
public boolean validate() {
setIsValid(true);
if (getItems() == null || !getIsAvailable()) {
return true;
}
boolean isValid = true;
for (KeyValueLineModel keyValueLineModel : getItems()) {
String key = keyValueLineModel.getKeys().getSelectedItem();
if (!isKeyValid(key)) {
continue;
}
keyValueLineModel.getValue().setIsValid(true);
RegexValidation regexValidation = new RegexValidation();
regexValidation.setMessage(ConstantsManager.getInstance()
.getMessages()
.customPropertyValueShouldBeInFormatReason(key, allKeyValueMap.get(key)));
regexValidation.setExpression(allKeyValueMap.get(key));
keyValueLineModel.getValue().validateEntity(
new IValidation[] { regexValidation });
isValid &= keyValueLineModel.getValue().getIsValid();
}
setIsValid(isValid);
return isValid;
}
/**
* Converts properties from string to map. Method assumes, that properties are syntactically valid
*
* @param properties
* specified properties
* @return map containing all properties ({@code LinkedHashMap} is used to ensure properties order is
* constant)
*/
public static Map<String, String> convertProperties(String properties) {
Map<String, String> map = new LinkedHashMap<>();
if (!StringHelper.isNullOrEmpty(properties)) {
String[] keyValuePairs = properties.split(PROPERTIES_DELIMETER);
for (String keyValuePairStr : keyValuePairs) {
String[] pairParts = keyValuePairStr.split(KEY_VALUE_DELIMETER, 2);
String key = pairParts[0];
// property value may be null
String value = pairParts[1];
map.put(key, value);
}
}
return map;
}
/**
* Converts properties from map to string.
*
* @param properties
* specified properties
* @return string containing all properties in map
*/
public static String convertProperties(Map<String, String> map) {
StringBuilder sb = new StringBuilder();
if (map != null && !map.isEmpty()) {
for (Map.Entry<String, String> e : map.entrySet()) {
sb.append(e.getKey());
sb.append(KEY_VALUE_DELIMETER);
sb.append(e.getValue());
sb.append(PROPERTIES_DELIMETER);
}
// remove last PROPERTIES_DELIMETER
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
}