/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.brooklyn.core.typereg; import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.typereg.RegisteredType; import org.apache.brooklyn.api.typereg.RegisteredTypeLoadingContext; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.javalang.JavaClassNames; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Convenience supertype for {@link BrooklynTypePlanTransformer} instances. * <p> * This supplies a default {@link #scoreForType(RegisteredType, RegisteredTypeLoadingContext)} * method which returns 1 if the format code matches, * and otherwise branches to two methods {@link #scoreForNullFormat(Object, RegisteredType, RegisteredTypeLoadingContext)} * and {@link #scoreForNonmatchingNonnullFormat(String, Object, RegisteredType, RegisteredTypeLoadingContext)} * which subclasses can implement. (Often the implementation of the latter is 0.) */ public abstract class AbstractTypePlanTransformer implements BrooklynTypePlanTransformer { private static final Logger log = LoggerFactory.getLogger(AbstractTypePlanTransformer.class); protected ManagementContext mgmt; @Override public void setManagementContext(ManagementContext mgmt) { this.mgmt = mgmt; } private final String format; private final String formatName; private final String formatDescription; protected AbstractTypePlanTransformer(String format, String formatName, String formatDescription) { this.format = format; this.formatName = formatName; this.formatDescription = formatDescription; } @Override public String getFormatCode() { return format; } @Override public String getFormatName() { return formatName; } @Override public String getFormatDescription() { return formatDescription; } @Override public String toString() { return getFormatCode()+":"+JavaClassNames.simpleClassName(this); } @Override public double scoreForType(RegisteredType type, RegisteredTypeLoadingContext context) { if (getFormatCode().equals(type.getPlan().getPlanFormat())) return 1; if (type.getPlan().getPlanFormat()==null) return scoreForNullFormat(type.getPlan().getPlanData(), type, context); else return scoreForNonmatchingNonnullFormat(type.getPlan().getPlanFormat(), type.getPlan().getPlanData(), type, context); } protected abstract double scoreForNullFormat(Object planData, RegisteredType type, RegisteredTypeLoadingContext context); protected abstract double scoreForNonmatchingNonnullFormat(String planFormat, Object planData, RegisteredType type, RegisteredTypeLoadingContext context); /** delegates to more specific abstract create methods, * and performs common validation and customisation of the items created. * <p> * this includes: * <li> setting the {@link AbstractBrooklynObjectSpec#catalogItemId(String)} */ @Override public Object create(final RegisteredType type, final RegisteredTypeLoadingContext context) { try { return tryValidate(new RegisteredTypeKindVisitor<Object>() { @Override protected Object visitSpec() { try { AbstractBrooklynObjectSpec<?, ?> result = createSpec(type, context); // see notes on catalogItemIdIfNotNull result.catalogItemIdIfNotNull(type.getId()); return result; } catch (Exception e) { throw Exceptions.propagate(e); } } @Override protected Object visitBean() { try { return createBean(type, context); } catch (Exception e) { throw Exceptions.propagate(e); } } }.visit(type.getKind()), type, context).get(); } catch (Exception e) { Exceptions.propagateIfFatal(e); if (!(e instanceof UnsupportedTypePlanException)) { log.debug("Could not instantiate "+type+" (rethrowing): "+Exceptions.collapseText(e)); } throw Exceptions.propagate(e); } } /** Validates the object. Subclasses may do further validation based on the context. * @throw UnsupportedTypePlanException if we want to quietly abandon this, any other exception to report the problem, when validation fails * @return the created object for fluent usage */ protected <T> Maybe<T> tryValidate(T createdObject, RegisteredType type, RegisteredTypeLoadingContext constraint) { return RegisteredTypes.tryValidate(createdObject, type, constraint); } protected abstract AbstractBrooklynObjectSpec<?,?> createSpec(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception; protected abstract Object createBean(RegisteredType type, RegisteredTypeLoadingContext context) throws Exception; }