Github user aledsage commented on a diff in the pull request:

    https://github.com/apache/brooklyn-server/pull/810#discussion_r140307032
  
    --- Diff: 
rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java
 ---
    @@ -0,0 +1,194 @@
    +/*
    + * 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.rest.transform;
    +
    +import static 
org.apache.brooklyn.rest.util.WebResourceUtils.serviceUriBuilder;
    +
    +import java.net.URI;
    +import java.util.Collections;
    +import java.util.Map;
    +import java.util.Set;
    +import java.util.concurrent.atomic.AtomicInteger;
    +
    +import javax.ws.rs.core.UriBuilder;
    +import javax.ws.rs.core.UriInfo;
    +
    +import org.apache.brooklyn.api.effector.Effector;
    +import org.apache.brooklyn.api.entity.Entity;
    +import org.apache.brooklyn.api.entity.EntitySpec;
    +import org.apache.brooklyn.api.entity.EntityType;
    +import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec;
    +import org.apache.brooklyn.api.location.Location;
    +import org.apache.brooklyn.api.mgmt.ManagementContext;
    +import org.apache.brooklyn.api.objs.EntityAdjunct;
    +import org.apache.brooklyn.api.objs.SpecParameter;
    +import org.apache.brooklyn.api.policy.Policy;
    +import org.apache.brooklyn.api.sensor.Enricher;
    +import org.apache.brooklyn.api.sensor.Feed;
    +import org.apache.brooklyn.api.sensor.Sensor;
    +import org.apache.brooklyn.api.typereg.ManagedBundle;
    +import org.apache.brooklyn.api.typereg.RegisteredType;
    +import org.apache.brooklyn.core.entity.EntityDynamicType;
    +import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
    +import org.apache.brooklyn.core.objs.BrooklynTypes;
    +import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
    +import org.apache.brooklyn.core.typereg.RegisteredTypes;
    +import org.apache.brooklyn.rest.api.TypeApi;
    +import org.apache.brooklyn.rest.domain.AdjunctConfigSummary;
    +import org.apache.brooklyn.rest.domain.BundleInstallationRestResult;
    +import org.apache.brooklyn.rest.domain.BundleSummary;
    +import org.apache.brooklyn.rest.domain.EffectorSummary;
    +import org.apache.brooklyn.rest.domain.EntityConfigSummary;
    +import org.apache.brooklyn.rest.domain.SensorSummary;
    +import org.apache.brooklyn.rest.domain.SummaryComparators;
    +import org.apache.brooklyn.rest.domain.TypeDetail;
    +import org.apache.brooklyn.rest.domain.TypeSummary;
    +import org.apache.brooklyn.rest.util.BrooklynRestResourceUtils;
    +import org.apache.brooklyn.util.collections.MutableMap;
    +import org.apache.brooklyn.util.exceptions.Exceptions;
    +import org.slf4j.LoggerFactory;
    +
    +import com.google.common.collect.Sets;
    +
    +public class TypeTransformer {
    +
    +    private static final org.slf4j.Logger log = 
LoggerFactory.getLogger(TypeTransformer.class);
    +    
    +    public static <T extends Entity> TypeSummary 
summary(BrooklynRestResourceUtils b, RegisteredType item, UriBuilder ub) {
    +        return embellish(new TypeSummary(item), item, false, b, ub);
    +    }
    +
    +    public static TypeDetail detail(BrooklynRestResourceUtils b, 
RegisteredType item, UriBuilder ub) {
    +        return embellish(new TypeDetail(item), item, true, b, ub);
    +    }
    +
    +    private static <T extends TypeSummary> T embellish(T result, 
RegisteredType item, boolean detail, BrooklynRestResourceUtils b, UriBuilder 
ub) {
    +        result.getExtraFields().put("links", makeLinks(item, ub));
    +        
    +        if (RegisteredTypes.isTemplate(item)) {
    +            result.getExtraFields().put("template", true);
    +        }
    +        if (item.getIconUrl()!=null) {
    +            result.setIconUrl(tidyIconLink(b, item, item.getIconUrl(), 
ub));
    +        }
    +        
    +        if (detail) {
    +            if (RegisteredTypes.isSubtypeOf(item, Entity.class)) {
    +                embellishEntity(result, item, b);
    +            } else if (RegisteredTypes.isSubtypeOf(item, 
EntityAdjunct.class) ||
    +                    // when implied supertypes are used we won't need the 
code below
    +                    RegisteredTypes.isSubtypeOf(item, Policy.class) || 
RegisteredTypes.isSubtypeOf(item, Enricher.class) || 
RegisteredTypes.isSubtypeOf(item, Feed.class)
    +                    ) {
    +                try {
    +                    Set<AdjunctConfigSummary> config = 
Sets.newLinkedHashSet();
    +                    
    +                    AbstractBrooklynObjectSpec<?,?> spec = 
b.getTypeRegistry().createSpec(item, null, null);
    +                    for (final SpecParameter<?> input : 
spec.getParameters()){
    +                        
config.add(EntityTransformer.adjunctConfigSummary(input));
    +                    }
    +                    
    +                    result.getExtraFields().put("config", config);
    +                } catch (Exception e) {
    +                    Exceptions.propagateIfFatal(e);
    +                    log.trace("Unable to create spec for "+item+": "+e, e);
    +                }
    +                
    +            } else if (RegisteredTypes.isSubtypeOf(item, Location.class)) {
    +                // TODO include config on location specs?  (wasn't done 
previously so not needed, but good for completeness)
    +                result.getExtraFields().put("config", 
Collections.emptyMap());
    +            }
    +        }
    +        return result;
    +    }
    +
    +    protected static <T extends TypeSummary> void embellishEntity(T 
result, RegisteredType item, BrooklynRestResourceUtils b) {
    +        try {
    +            Set<EntityConfigSummary> config = Sets.newLinkedHashSet();
    +            Set<SensorSummary> sensors = 
Sets.newTreeSet(SummaryComparators.nameComparator());
    +            Set<EffectorSummary> effectors = 
Sets.newTreeSet(SummaryComparators.nameComparator());
    +      
    +            EntitySpec<?> spec = b.getTypeRegistry().createSpec(item, 
null, EntitySpec.class);
    +            EntityDynamicType typeMap = 
BrooklynTypes.getDefinedEntityType(spec.getType());
    +            EntityType type = typeMap.getSnapshot();
    +   
    +            AtomicInteger paramPriorityCnt = new AtomicInteger();
    +            for (SpecParameter<?> input: spec.getParameters())
    +                config.add(EntityTransformer.entityConfigSummary(input, 
paramPriorityCnt));
    +            for (Sensor<?> x: type.getSensors())
    +                sensors.add(SensorTransformer.sensorSummaryForCatalog(x));
    +            for (Effector<?> x: type.getEffectors())
    +                
effectors.add(EffectorTransformer.effectorSummaryForCatalog(x));
    +            
    +            result.getExtraFields().put("config", config);
    --- End diff --
    
    Where do you imagine we'll document the names "config", "sensors" and 
"effectors" (or do people have to discover it by making some live calls and 
figuring out what looks to be there consistently for everything of a given 
type)?
    
    Where would we document the type of the values for something like an 
effector?
    
    I think the looseness won't be an issue for Brooklyn developers (because we 
can easily navigate the code base to find the `EffectorTransformer`, when 
working on the CLI or UI).
    
    However, I think it makes it feel more scary for a user of Brooklyn who is 
thinking of writing an integration with our REST api. They won't know what 
fields to expect. They can make a few calls and then guess at what is optional 
versus mandatory, and then code as defensively as possible in case their guess 
was wrong.


---

Reply via email to