Some simplifications of dynamic CA/Reconcilng using PartialCollection
This commit is contained in:
@@ -192,36 +192,30 @@ public class BoshDeploymentManifestSchema implements YamlSchema {
|
||||
addProp(t_instance_group_env, "bosh", t_params);
|
||||
addProp(t_instance_group_env, "password", t_ne_string);
|
||||
|
||||
YType t_release_version = f.contextAware("ReleaseVersion", new SchemaContextAware<YType>() {
|
||||
private AbstractType no_dynamic_checks = f.yenumFromDynamicValues("ReleaseVersion",
|
||||
dc -> PartialCollection.compute(() -> releasesProvider.getModel(dc).getVersions())
|
||||
)
|
||||
.addHints("latest")
|
||||
.parseWith(ValueParsers.NE_STRING);
|
||||
private AbstractType base_type = f.yenumFromDynamicValues("ReleaseVersion",
|
||||
dc -> PartialCollection.compute(() -> releasesProvider.getModel(dc).getVersions())
|
||||
)
|
||||
.addHints("latest")
|
||||
.alsoAccept("latest");
|
||||
|
||||
@Override
|
||||
public YType withContext(DynamicSchemaContext dc) throws Exception {
|
||||
if (StringUtil.hasText(getCurrentEntityProperty(dc,"url"))) {
|
||||
return no_dynamic_checks;
|
||||
YType t_release_version = f.yenumFromDynamicValues("ReleaseVersion",
|
||||
//message formatter:
|
||||
dc -> (s, values) -> {
|
||||
String name = getCurrentEntityProperty(dc, "name");
|
||||
if (StringUtil.hasText(name)) {
|
||||
return "'"+s+"' is an unknown 'ReleaseVersion[name="+name+"]'. Valid values are: "+values;
|
||||
} else {
|
||||
return "'"+s+"' is an unknown 'ReleaseVersion'. Valid values are: "+values;
|
||||
}
|
||||
},
|
||||
//value provider:
|
||||
dc -> {
|
||||
PartialCollection<ReleaseData> releases = PartialCollection.compute(() -> releasesProvider.getModel(dc).getReleases());
|
||||
if (StringUtil.hasText(getCurrentEntityProperty(dc, "url"))) {
|
||||
releases = releases.addUncertainty();
|
||||
} else {
|
||||
String name = getCurrentEntityProperty(dc, "name");
|
||||
if (StringUtil.hasText(name)) {
|
||||
return f.yenumFromDynamicValues("ReleaseVersion[name="+name+"]", (_dc) ->
|
||||
PartialCollection.compute(() -> releasesProvider.getModel(dc).getReleases())
|
||||
.map(r -> name.equals(r.getName()) ? r.getVersion() : null)
|
||||
)
|
||||
.addHints("latest")
|
||||
.alsoAccept("latest");
|
||||
releases = releases.map(r -> name.equals(r.getName()) ? r : null);
|
||||
}
|
||||
}
|
||||
return base_type;
|
||||
return releases.map(r -> r.getVersion()).add("latest");
|
||||
}
|
||||
}).treatAsAtomic();
|
||||
);
|
||||
|
||||
YBeanType t_release = f.ybean("Release");
|
||||
addProp(t_release, "name", t_release_name_def).isPrimary(true);
|
||||
@@ -244,34 +238,25 @@ public class BoshDeploymentManifestSchema implements YamlSchema {
|
||||
YType t_stemcell_os_ref = f.yenumFromDynamicValues("StemcellOs", (dc) ->
|
||||
PartialCollection.compute(() -> stemcellsProvider.getModel(dc).getStemcellOss())
|
||||
);
|
||||
YType t_stemcell_version_ref = f.contextAware("StemcellVersion", new SchemaContextAware<YType>() {
|
||||
|
||||
YAtomicType baseType = f.yenumFromDynamicValues("StemcellVersion", (dc) ->
|
||||
PartialCollection.compute(() -> stemcellsProvider.getModel(dc).getVersions())
|
||||
);
|
||||
{
|
||||
baseType.addHints("latest");
|
||||
baseType.alsoAccept("latest");
|
||||
}
|
||||
|
||||
@Override
|
||||
public YType withContext(DynamicSchemaContext dc) throws Exception {
|
||||
StemcellModel currentStemcell = getCurrentStemcell(dc);
|
||||
if (StringUtil.hasText(currentStemcell.getName())||StringUtil.hasText(currentStemcell.getOs())) {
|
||||
Predicate<StemcellData> filter = currentStemcell.createVersionFilter();
|
||||
YAtomicType filteredType = f.yenumFromDynamicValues("StemcellVersion["+filter+"]", (_dc) -> {
|
||||
//Note: it doesn't really matter whether we use _dc or dc in code below as they should be the same.
|
||||
Predicate<StemcellData> versionFilter = currentStemcell.createVersionFilter();
|
||||
return PartialCollection.compute(() -> stemcellsProvider.getModel(dc).getStemcells())
|
||||
.map(sc -> versionFilter.test(sc) ? sc.getVersion() : null);
|
||||
});
|
||||
filteredType.addHints("latest");
|
||||
filteredType.alsoAccept("latest");
|
||||
return filteredType;
|
||||
YType t_stemcell_version_ref = f.yenumFromDynamicValues("StemcellVersion",
|
||||
(dc) -> (parseString, validValues) -> {
|
||||
try {
|
||||
Predicate<StemcellData> filter = getCurrentStemcell(dc).createVersionFilter();
|
||||
if (filter!=StemcellModel.ALLWAYS_TRUE_FILTER) {
|
||||
return "'"+parseString+"' is an unknown 'StemcellVersion["+filter+"]'. Valid values are: "+validValues;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//ignore (parse error most likely)
|
||||
}
|
||||
return baseType;
|
||||
return "'"+parseString+"' is an unknown 'StemcellVersion'. Valid values are: "+validValues;
|
||||
},
|
||||
(dc) -> {
|
||||
Predicate<StemcellData> filter = getCurrentStemcell(dc).createVersionFilter();
|
||||
return PartialCollection.compute(() -> stemcellsProvider.getModel(dc).getStemcells())
|
||||
.map(sc -> filter.test(sc) ? sc.getVersion() : null)
|
||||
.add("latest");
|
||||
}
|
||||
}).treatAsAtomic();
|
||||
);
|
||||
|
||||
addProp(t_stemcell, "alias", t_stemcell_alias_def).isRequired(true);
|
||||
addProp(t_stemcell, "version", t_stemcell_version_ref).isRequired(true);
|
||||
|
||||
@@ -21,6 +21,16 @@ import org.yaml.snakeyaml.nodes.Node;
|
||||
*/
|
||||
public class StemcellModel {
|
||||
|
||||
public static final Predicate<StemcellData> ALLWAYS_TRUE_FILTER = new Predicate<StemcellData>() {
|
||||
@Override
|
||||
public boolean test(StemcellData sc) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "true";
|
||||
}
|
||||
};
|
||||
private Node node;
|
||||
|
||||
public StemcellModel(Node node) {
|
||||
@@ -79,16 +89,7 @@ public class StemcellModel {
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return new Predicate<StemcellData>() {
|
||||
@Override
|
||||
public boolean test(StemcellData sc) {
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "true";
|
||||
}
|
||||
};
|
||||
return ALLWAYS_TRUE_FILTER;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1122,8 +1122,8 @@ public class BoshEditorTest {
|
||||
);
|
||||
editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY);
|
||||
editor.assertProblems(
|
||||
"123.4|unknown 'StemcellVersion[name=centos-agent]'. Valid values are: [222.2, 333.3]",
|
||||
"333.3|unknown 'StemcellVersion[os=ubuntu]'. Valid values are: [123.4, 222.2]"
|
||||
"123.4|unknown 'StemcellVersion[name=centos-agent]'. Valid values are: [222.2, 333.3, latest]",
|
||||
"333.3|unknown 'StemcellVersion[os=ubuntu]'. Valid values are: [123.4, 222.2, latest]"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1200,6 +1200,17 @@ public class BoshEditorTest {
|
||||
"latest<*>"
|
||||
);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"releases:\n" +
|
||||
"- name: foo\n" +
|
||||
" version: <*>"
|
||||
);
|
||||
editor.assertContextualCompletions("<*>",
|
||||
"123.4<*>",
|
||||
"222.2<*>",
|
||||
"latest<*>"
|
||||
);
|
||||
|
||||
//Still get all suggestions even when 'url' property is added
|
||||
editor = harness.newEditor(
|
||||
"releases:\n" +
|
||||
@@ -1213,6 +1224,19 @@ public class BoshEditorTest {
|
||||
"latest<*>"
|
||||
);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"releases:\n" +
|
||||
"- name: foo\n" +
|
||||
" url: blah\n" +
|
||||
" version: <*>"
|
||||
);
|
||||
editor.assertContextualCompletions("<*>",
|
||||
"123.4<*>",
|
||||
"222.2<*>",
|
||||
"333.3<*>",
|
||||
"latest<*>"
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@Test public void reconcileReleaseVersion() throws Exception {
|
||||
@@ -1228,10 +1252,13 @@ public class BoshEditorTest {
|
||||
"releases:\n" +
|
||||
"- version: bogus\n" +
|
||||
"- version: url-makes-this-possibly-correct\n" +
|
||||
" url: file:///relesease-folder/blah-release.tar.gz"
|
||||
" url: file:///relesease-folder/blah-release.tar.gz\n"+
|
||||
"- name: bar\n" +
|
||||
" version: url-makes-this-also-possibly-correct\n" +
|
||||
" url: file:///relesease-folder/other-release.tar.gz"
|
||||
);
|
||||
editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY);
|
||||
editor.assertProblems("bogus|unknown 'ReleaseVersion'. Valid values are: [123.4, 222.2, 333.3]");
|
||||
editor.assertProblems("bogus|unknown 'ReleaseVersion'. Valid values are: [123.4, 222.2, 333.3, latest]");
|
||||
|
||||
editor = harness.newEditor(
|
||||
"releases:\n" +
|
||||
@@ -1240,7 +1267,32 @@ public class BoshEditorTest {
|
||||
"- version: bogus\n"
|
||||
);
|
||||
editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY);
|
||||
editor.assertProblems("bogus|unknown 'ReleaseVersion'. Valid values are: [123.4, 222.2, 333.3]");
|
||||
editor.assertProblems("bogus|unknown 'ReleaseVersion'. Valid values are: [123.4, 222.2, 333.3, latest]");
|
||||
|
||||
editor = harness.newEditor(
|
||||
"releases:\n" +
|
||||
"- name: foo\n" +
|
||||
" version: 123.4\n"
|
||||
);
|
||||
editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY);
|
||||
editor.assertProblems(/*NONE*/);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"releases:\n" +
|
||||
"- name: foo\n" +
|
||||
" version: 222.2\n"
|
||||
);
|
||||
editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY);
|
||||
editor.assertProblems(/*NONE*/);
|
||||
|
||||
editor = harness.newEditor(
|
||||
"releases:\n" +
|
||||
"- name: foo\n" +
|
||||
" version: 333.3\n"
|
||||
);
|
||||
editor.ignoreProblem(YamlSchemaProblems.MISSING_PROPERTY);
|
||||
editor.assertProblems("333.3|unknown 'ReleaseVersion[name=foo]'. Valid values are: [123.4, 222.2, latest]");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ public class EnumValueParser implements ValueParser {
|
||||
|
||||
PartialCollection<String> values = this.values.get();
|
||||
|
||||
// If values is not known (null) then just assume the str is acceptable.
|
||||
// If values is not fully known then just assume the str is acceptable.
|
||||
if (values == null || !values.isComplete() || values.getElements().contains(str)) {
|
||||
return str;
|
||||
} else {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.commons.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
@@ -132,4 +133,7 @@ public class PartialCollection<T> {
|
||||
return explanation;
|
||||
}
|
||||
|
||||
public PartialCollection<T> add(@SuppressWarnings("unchecked") T... values) {
|
||||
return addAll(Arrays.asList(values));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -855,7 +855,7 @@ public class YTypeFactory {
|
||||
return ((YTypedPropertyImpl)prop).copy();
|
||||
}
|
||||
|
||||
public YAtomicType yenumFromHints(String name, BiFunction<String, Collection<String>, String> errorMessageFormatter, SchemaContextAware<PartialCollection<YValueHint>> values) {
|
||||
public YAtomicType yenumFromHints(String name, SchemaContextAware<BiFunction<String, Collection<String>, String>> errorMessageFormatter, SchemaContextAware<PartialCollection<YValueHint>> values) {
|
||||
YAtomicType t = yatomic(name);
|
||||
t.setHintProvider(values);
|
||||
t.parseWith((DynamicSchemaContext dc) -> {
|
||||
@@ -865,7 +865,11 @@ public class YTypeFactory {
|
||||
return new EnumValueParser(name, strings) {
|
||||
@Override
|
||||
protected String createErrorMessage(String parseString, Collection<String> values) {
|
||||
return errorMessageFormatter.apply(parseString, values);
|
||||
try {
|
||||
return errorMessageFormatter.withContext(dc).apply(parseString, values);
|
||||
} catch (Exception e) {
|
||||
return super.createErrorMessage(parseString, values);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -874,10 +878,22 @@ public class YTypeFactory {
|
||||
return t;
|
||||
}
|
||||
|
||||
public YAtomicType yenumFromDynamicValues(String name,
|
||||
SchemaContextAware<BiFunction<String, Collection<String>, String>> errorMessageFormatter,
|
||||
SchemaContextAware<PartialCollection<String>> values
|
||||
) {
|
||||
return yenumFromHints(name,
|
||||
//Error message formatter:
|
||||
errorMessageFormatter,
|
||||
//Hints provider:
|
||||
(dc) -> hints(values.withContext(dc))
|
||||
);
|
||||
}
|
||||
|
||||
public YAtomicType yenumFromDynamicValues(String name, SchemaContextAware<PartialCollection<String>> values) {
|
||||
return yenumFromHints(name,
|
||||
//Error message formatter:
|
||||
(parseString, validValues) -> "'"+parseString+"' is an unknown '"+name+"'. Valid values are: "+validValues,
|
||||
(dc) -> (parseString, validValues) -> "'"+parseString+"' is an unknown '"+name+"'. Valid values are: "+validValues,
|
||||
//Hints provider:
|
||||
(dc) -> hints(values.withContext(dc))
|
||||
);
|
||||
@@ -887,7 +903,7 @@ public class YTypeFactory {
|
||||
return new EnumTypeBuilder(name, values);
|
||||
}
|
||||
|
||||
public YAtomicType yenum(String name, BiFunction<String, Collection<String>, String> errorMessageFormatter, SchemaContextAware<Collection<String>> values) {
|
||||
public YAtomicType yenum(String name, SchemaContextAware<BiFunction<String, Collection<String>, String>> errorMessageFormatter, SchemaContextAware<Collection<String>> values) {
|
||||
YAtomicType t = yatomic(name);
|
||||
t.setHintProvider((dc) -> {
|
||||
return PartialCollection.compute(() -> values.withContext(dc))
|
||||
@@ -897,12 +913,21 @@ public class YTypeFactory {
|
||||
EnumValueParser enumParser = new EnumValueParser(name, values.withContext(dc)) {
|
||||
@Override
|
||||
protected String createErrorMessage(String parseString, Collection<String> values) {
|
||||
return errorMessageFormatter.apply(parseString, values);
|
||||
try {
|
||||
return errorMessageFormatter.withContext(dc).apply(parseString, values);
|
||||
} catch (Exception e) {
|
||||
return super.createErrorMessage(parseString, values);
|
||||
}
|
||||
}
|
||||
};
|
||||
return enumParser;
|
||||
});
|
||||
return t;
|
||||
|
||||
}
|
||||
|
||||
public YAtomicType yenum(String name, BiFunction<String, Collection<String>, String> errorMessageFormatter, SchemaContextAware<Collection<String>> values) {
|
||||
return yenum(name, (dc) -> errorMessageFormatter, values);
|
||||
}
|
||||
|
||||
public static Collection<String> values(Collection<YValueHint> hints) {
|
||||
|
||||
@@ -171,7 +171,7 @@ public class PipelineYmlSchema implements YamlSchema {
|
||||
t_version.addHints("latest", "every");
|
||||
|
||||
t_resource_type_name = f.yenumFromHints("ResourceType Name",
|
||||
(parseString, validValues) -> {
|
||||
(dc) -> (parseString, validValues) -> {
|
||||
return "The '"+parseString+"' Resource Type does not exist. Existing types: "+validValues;
|
||||
},
|
||||
(DynamicSchemaContext dc) -> {
|
||||
|
||||
Reference in New Issue
Block a user