4343import org .apache .brooklyn .api .catalog .CatalogItem ;
4444import org .apache .brooklyn .api .catalog .CatalogItem .CatalogBundle ;
4545import org .apache .brooklyn .api .catalog .CatalogItem .CatalogItemType ;
46+ import org .apache .brooklyn .api .entity .Application ;
4647import org .apache .brooklyn .api .internal .AbstractBrooklynObjectSpec ;
47- import org .apache .brooklyn .api .location .Location ;
48- import org .apache .brooklyn .api .location .LocationSpec ;
4948import org .apache .brooklyn .api .mgmt .ManagementContext ;
5049import org .apache .brooklyn .api .mgmt .classloading .BrooklynClassLoadingContext ;
5150import org .apache .brooklyn .api .objs .BrooklynObject ;
5655import org .apache .brooklyn .api .typereg .RegisteredType ;
5756import org .apache .brooklyn .core .catalog .CatalogPredicates ;
5857import org .apache .brooklyn .core .catalog .internal .CatalogClasspathDo .CatalogScanningModes ;
59- import org .apache .brooklyn .core .location . BasicLocationRegistry ;
58+ import org .apache .brooklyn .core .mgmt . BrooklynTags ;
6059import org .apache .brooklyn .core .mgmt .ha .OsgiBundleInstallationResult ;
6160import org .apache .brooklyn .core .mgmt .ha .OsgiManager ;
6261import 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 ));
0 commit comments