Skip to content

Commit 7a42cf8

Browse files
committed
support templates for RegisteredType instances, using tags
1 parent c5af549 commit 7a42cf8

5 files changed

Lines changed: 78 additions & 33 deletions

File tree

api/src/main/java/org/apache/brooklyn/api/objs/BrooklynObjectType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public static BrooklynObjectType of(Class<?> objectTypeOrSpecType) {
9595
}
9696

9797
public static BrooklynObjectType of(CatalogItemType t) {
98+
if (t==null) return null;
9899
switch (t) {
99100
case ENRICHER: return BrooklynObjectType.ENRICHER;
100101
case ENTITY: return BrooklynObjectType.ENTITY;

api/src/main/java/org/apache/brooklyn/api/typereg/BrooklynTypeRegistry.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,9 @@ public enum RegisteredTypeKind {
3838
/** a registered type which will create the java type described */
3939
BEAN,
4040
/** a partially registered type which requires subsequent validation and changing the kind;
41-
* until then, an item of this kind cannot be instantiated */
41+
* until then, an item of this kind cannot be instantiated.
42+
* items registered as templates (using a tag) may remain in this state
43+
* if they do not resolve. */
4244
UNRESOLVED
4345
// note: additional kinds should have the visitor in core/RegisteredTypeKindVisitor updated
4446
// to flush out all places which want to implement support for all kinds

core/src/main/java/org/apache/brooklyn/core/catalog/internal/BasicBrooklynCatalog.java

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@
4343
import org.apache.brooklyn.api.catalog.CatalogItem;
4444
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle;
4545
import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType;
46+
import org.apache.brooklyn.api.entity.Application;
4647
import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
47-
import org.apache.brooklyn.api.location.Location;
48-
import org.apache.brooklyn.api.location.LocationSpec;
4948
import org.apache.brooklyn.api.mgmt.ManagementContext;
5049
import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext;
5150
import org.apache.brooklyn.api.objs.BrooklynObject;
@@ -56,7 +55,7 @@
5655
import org.apache.brooklyn.api.typereg.RegisteredType;
5756
import org.apache.brooklyn.core.catalog.CatalogPredicates;
5857
import org.apache.brooklyn.core.catalog.internal.CatalogClasspathDo.CatalogScanningModes;
59-
import org.apache.brooklyn.core.location.BasicLocationRegistry;
58+
import org.apache.brooklyn.core.mgmt.BrooklynTags;
6059
import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
6160
import org.apache.brooklyn.core.mgmt.ha.OsgiManager;
6261
import org.apache.brooklyn.core.mgmt.internal.CampYamlParser;
@@ -869,22 +868,34 @@ private void collectCatalogItemsFromItemMetadataBlock(String sourceYaml, Managed
869868
// just need TODO to make sure we delete previously-persisted things which now come through this path.)
870869
// NB: when everything is a bundle and we've removed all scanning then this can be the _only_ path
871870
// and code can be massively simpler
871+
// TODO allow these to be set in catalog.bom ?
872+
List<String> aliases = MutableList.of();
873+
List<Object> tags = MutableList.of();
874+
Boolean catalogDisabled = null;
875+
876+
MutableList<Object> superTypes = MutableList.of();
877+
878+
if (itemType==CatalogItemType.TEMPLATE) {
879+
tags.add(BrooklynTags.CATALOG_TEMPLATE);
880+
itemType = CatalogItemType.ENTITY;
881+
superTypes.add(Application.class);
882+
}
872883

873884
if (resolutionError!=null) {
874-
if (requireValidation) {
875-
throw Exceptions.propagate(resolutionError);
885+
if (!tags.contains(BrooklynTags.CATALOG_TEMPLATE)) {
886+
if (requireValidation) {
887+
throw Exceptions.propagate(resolutionError);
888+
}
889+
// warn? add as "unresolved" ? just do nothing?
876890
}
877-
// warn? add as "unresolved" ? just do nothing?
878891
}
879-
String format = null; // could support specifying format
880-
// TODO if kind and supertype is known, set those here
881-
Class<?> javaType = null;
882-
List<Object> superTypes = MutableList.of().appendIfNotNull(javaType);
892+
String format = null; // could support specifying format?
883893

884-
// TODO allow these to be set in catalog.bom ?
885-
List<String> aliases = MutableList.of();
886-
List<Object> tags = MutableList.of();
887-
Boolean catalogDisabled = null;
894+
if (itemType!=null) {
895+
// if supertype is known, set it here;
896+
// we don't set kind (spec) because that is inferred from the supertype type
897+
superTypes.appendIfNotNull(BrooklynObjectType.of(itemType).getInterfaceType());
898+
}
888899

889900
if (version==null) {
890901
// use this as default version when nothing specified
@@ -1106,12 +1117,15 @@ public PlanInterpreterGuessingType reconstruct() {
11061117

11071118
} else {
11081119
attemptType(null, CatalogItemType.ENTITY);
1109-
1120+
11101121
List<Exception> oldEntityErrors = MutableList.copyOf(entityErrors);
1122+
// try with services key
11111123
attemptType("services", CatalogItemType.ENTITY);
11121124
entityErrors.removeAll(oldEntityErrors);
11131125
entityErrors.addAll(oldEntityErrors);
1114-
// prefer errors when wrapped in services block
1126+
// errors when wrapped in services block are better currently
1127+
// as we parse using CAMP and need that
1128+
// so prefer those for now (may change with YOML)
11151129

11161130
attemptType(POLICIES_KEY, CatalogItemType.POLICY);
11171131
attemptType(ENRICHERS_KEY, CatalogItemType.ENRICHER);
@@ -1447,6 +1461,10 @@ public Map<RegisteredType,Collection<Throwable>> validateTypes(Iterable<Register
14471461
public Collection<Throwable> validateType(RegisteredType typeToValidate) {
14481462
ReferenceWithError<RegisteredType> result = resolve(typeToValidate);
14491463
if (result.hasError()) {
1464+
if (RegisteredTypes.isTemplate(typeToValidate)) {
1465+
// ignore for templates
1466+
return Collections.emptySet();
1467+
}
14501468
if (result.getError() instanceof CompoundRuntimeException) {
14511469
return ((CompoundRuntimeException)result.getError()).getAllCauses();
14521470
}
@@ -1456,7 +1474,7 @@ public Collection<Throwable> validateType(RegisteredType typeToValidate) {
14561474
((BasicBrooklynTypeRegistry) mgmt.getTypeRegistry()).addToLocalUnpersistedTypeRegistry(result.get(), true);
14571475
return Collections.emptySet();
14581476
}
1459-
1477+
14601478
/**
14611479
* Resolves the given object with respect to the catalog. Returns any errors found while trying to resolve.
14621480
* The argument may be changed (e.g. its kind set, supertypes set), and normal usage is to add
@@ -1491,11 +1509,8 @@ public ReferenceWithError<RegisteredType> resolve(RegisteredType typeToValidate)
14911509
}
14921510
}
14931511

1494-
// TODO filter what we try based on kind,
1495-
// and set things based on declared itemType;
1496-
// also support itemType spec (generic) and bean to help filter
1497-
1498-
// TODO support "template" (never instantiable) in registry
1512+
// could filter what we try based on kind; also could support itemType spec (generic) and
1513+
// more importantly bean to allow arbitrary types to be added to catalog
14991514

15001515
RegisteredType resultT = null;
15011516

@@ -1508,6 +1523,7 @@ public ReferenceWithError<RegisteredType> resolve(RegisteredType typeToValidate)
15081523
} catch (Exception e) {
15091524
Exceptions.propagateIfFatal(e);
15101525
specError = e;
1526+
resultT = null;
15111527
}
15121528
} catch (Exception e) {
15131529
Exceptions.propagateIfFatal(e);
@@ -1522,6 +1538,7 @@ public ReferenceWithError<RegisteredType> resolve(RegisteredType typeToValidate)
15221538
} catch (Exception e) {
15231539
Exceptions.propagateIfFatal(e);
15241540
beanError = e;
1541+
resultT = null;
15251542
}
15261543
} catch (Exception e) {
15271544
Exceptions.propagateIfFatal(e);
@@ -1537,24 +1554,40 @@ public ReferenceWithError<RegisteredType> resolve(RegisteredType typeToValidate)
15371554
yaml, null, CatalogItemDtoAbstract.parseLibraries( typeToValidate.getLibraries() ), null);
15381555
guesser.reconstruct();
15391556
guesserErrors.addAll(guesser.getErrors());
1557+
15401558
if (guesser.isResolved()) {
1559+
// guesser resolved, but we couldn't create; did guesser change something?
1560+
15411561
CatalogItemType ciType = guesser.getCatalogItemType();
1542-
if (ciType==CatalogItemType.TEMPLATE) {
1543-
// TODO templates in registry
1544-
throw new IllegalStateException("Templates not yet supported in registry");
1545-
1546-
} else if (boType==null) {
1562+
// try this even for templates; errors in them will be ignored by validator
1563+
// but might be interesting to someone calling resolve directly
1564+
1565+
boolean changedSomething = false;
1566+
// reset resultT and change things as needed based on guesser
1567+
resultT = typeToValidate;
1568+
if (boType==null) {
1569+
// guesser inferred a type
15471570
boType = BrooklynObjectType.of(ciType);
15481571
if (boType!=null) {
15491572
supers = MutableSet.copyOf(supers);
15501573
supers.add(boType.getInterfaceType());
15511574
// didn't know type before, retry now that we know the type
1552-
resultT = RegisteredTypes.copyResolved(RegisteredTypeKind.SPEC, typeToValidate);
1575+
resultT = RegisteredTypes.copyResolved(RegisteredTypeKind.SPEC, resultT);
15531576
RegisteredTypes.addSuperTypes(resultT, supers);
1554-
RegisteredTypes.changePlan(resultT,
1555-
new BasicTypeImplementationPlan(null /* CampTypePlanTransformer.FORMAT */, guesser.getPlanYaml()));
1556-
return resolve(resultT);
1577+
changedSomething = true;
15571578
}
1579+
}
1580+
1581+
if (!Objects.equal(guesser.getPlanYaml(), yaml)) {
1582+
RegisteredTypes.changePlan(resultT,
1583+
new BasicTypeImplementationPlan(null /* CampTypePlanTransformer.FORMAT */, guesser.getPlanYaml()));
1584+
changedSomething = true;
1585+
}
1586+
1587+
if (changedSomething) {
1588+
// try again with new plan or supertype info
1589+
return resolve(resultT);
1590+
15581591
} else if (Objects.equal(boType, BrooklynObjectType.of(ciType))) {
15591592
if (specError==null) {
15601593
throw new IllegalStateException("Guesser resolved but TypeRegistry couldn't create");
@@ -1571,9 +1604,10 @@ public ReferenceWithError<RegisteredType> resolve(RegisteredType typeToValidate)
15711604
} catch (Exception e) {
15721605
Exceptions.propagateIfFatal(e);
15731606
guesserErrors.add(e);
1607+
resultT = null;
15741608
}
15751609

1576-
if (resultO!=null) {
1610+
if (resultO!=null && resultT!=null) {
15771611
if (resultO instanceof BrooklynObject) {
15781612
// if it was a bean that points at a BO then switch it to a spec and try to re-validate
15791613
return resolve(RegisteredTypes.copyResolved(RegisteredTypeKind.SPEC, typeToValidate));

core/src/main/java/org/apache/brooklyn/core/mgmt/BrooklynTags.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ public class BrooklynTags {
3939
public static final String NOTES_KIND = "notes";
4040
public static final String OWNER_ENTITY_ID = "owner_entity_id";
4141
public static final String ICON_URL = "icon_url";
42+
/** tag on a registered type indicating that an item is intended to be used as a template,
43+
* and does not have to resolve */
44+
public static final Object CATALOG_TEMPLATE = "catalog_template";
4245

4346
public static class NamedStringTag implements Serializable {
4447
private static final long serialVersionUID = 7932098757009051348L;

core/src/main/java/org/apache/brooklyn/core/typereg/RegisteredTypes.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,4 +584,9 @@ public static RegisteredType changePlan(RegisteredType type, TypeImplementationP
584584
return type;
585585
}
586586

587+
public static boolean isTemplate(RegisteredType type) {
588+
if (type==null) return false;
589+
return type.getTags().contains(BrooklynTags.CATALOG_TEMPLATE);
590+
}
591+
587592
}

0 commit comments

Comments
 (0)