/* * 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 com.alibaba.jstorm.flux.model; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.*; /** * Bean represenation of a topology. * * It consists of the following: * 1. The topology name * 2. A `java.util.Map` representing the `backtype.storm.config` for the topology * 3. A list of spout definitions * 4. A list of bolt definitions * 5. A list of stream definitions that define the flow between spouts and bolts. * */ public class TopologyDef { private static Logger LOG = LoggerFactory.getLogger(TopologyDef.class); private String name; private Map<String, BeanDef> componentMap = new LinkedHashMap<String, BeanDef>(); // not required private List<IncludeDef> includes; // not required private Map<String, Object> config = new HashMap<String, Object>(); // a "topology source" is a class that can produce a `StormTopology` thrift object. private TopologySourceDef topologySource; // the following are required if we're defining a core storm topology DAG in YAML, etc. private Map<String, BoltDef> boltMap = new LinkedHashMap<String, BoltDef>(); private Map<String, SpoutDef> spoutMap = new LinkedHashMap<String, SpoutDef>(); private List<StreamDef> streams = new ArrayList<StreamDef>(); public String getName() { return name; } public void setName(String name) { this.name = name; } public void setName(String name, boolean override){ if(this.name == null || override){ this.name = name; } else { LOG.warn("Ignoring attempt to set property 'name' with override == false."); } } public List<SpoutDef> getSpouts() { ArrayList<SpoutDef> retval = new ArrayList<SpoutDef>(); retval.addAll(this.spoutMap.values()); return retval; } public void setSpouts(List<SpoutDef> spouts) { this.spoutMap = new LinkedHashMap<String, SpoutDef>(); for(SpoutDef spout : spouts){ this.spoutMap.put(spout.getId(), spout); } } public List<BoltDef> getBolts() { ArrayList<BoltDef> retval = new ArrayList<BoltDef>(); retval.addAll(this.boltMap.values()); return retval; } public void setBolts(List<BoltDef> bolts) { this.boltMap = new LinkedHashMap<String, BoltDef>(); for(BoltDef bolt : bolts){ this.boltMap.put(bolt.getId(), bolt); } } public List<StreamDef> getStreams() { return streams; } public void setStreams(List<StreamDef> streams) { this.streams = streams; } public Map<String, Object> getConfig() { return config; } public void setConfig(Map<String, Object> config) { this.config = config; } public List<BeanDef> getComponents() { ArrayList<BeanDef> retval = new ArrayList<BeanDef>(); retval.addAll(this.componentMap.values()); return retval; } public void setComponents(List<BeanDef> components) { this.componentMap = new LinkedHashMap<String, BeanDef>(); for(BeanDef component : components){ this.componentMap.put(component.getId(), component); } } public List<IncludeDef> getIncludes() { return includes; } public void setIncludes(List<IncludeDef> includes) { this.includes = includes; } // utility methods public int parallelismForBolt(String boltId){ return this.boltMap.get(boltId).getParallelism(); } public BoltDef getBoltDef(String id){ return this.boltMap.get(id); } public SpoutDef getSpoutDef(String id){ return this.spoutMap.get(id); } public BeanDef getComponent(String id){ return this.componentMap.get(id); } // used by includes implementation public void addAllBolts(List<BoltDef> bolts, boolean override){ for(BoltDef bolt : bolts){ String id = bolt.getId(); if(this.boltMap.get(id) == null || override) { this.boltMap.put(bolt.getId(), bolt); } else { LOG.warn("Ignoring attempt to create bolt '{}' with override == false.", id); } } } public void addAllSpouts(List<SpoutDef> spouts, boolean override){ for(SpoutDef spout : spouts){ String id = spout.getId(); if(this.spoutMap.get(id) == null || override) { this.spoutMap.put(spout.getId(), spout); } else { LOG.warn("Ignoring attempt to create spout '{}' with override == false.", id); } } } public void addAllComponents(List<BeanDef> components, boolean override) { for(BeanDef bean : components){ String id = bean.getId(); if(this.componentMap.get(id) == null || override) { this.componentMap.put(bean.getId(), bean); } else { LOG.warn("Ignoring attempt to create component '{}' with override == false.", id); } } } public void addAllStreams(List<StreamDef> streams, boolean override) { //TODO figure out how we want to deal with overrides. Users may want to add streams even when overriding other // properties. For now we just add them blindly which could lead to a potentially invalid topology. this.streams.addAll(streams); } public TopologySourceDef getTopologySource() { return topologySource; } public void setTopologySource(TopologySourceDef topologySource) { this.topologySource = topologySource; } public boolean isDslTopology(){ return this.topologySource == null; } public boolean validate(){ boolean hasSpouts = this.spoutMap != null && this.spoutMap.size() > 0; boolean hasBolts = this.boltMap != null && this.boltMap.size() > 0; boolean hasStreams = this.streams != null && this.streams.size() > 0; boolean hasSpoutsBoltsStreams = hasStreams && hasBolts && hasSpouts; // you cant define a topologySource and a DSL topology at the same time... if (!isDslTopology() && ((hasSpouts || hasBolts || hasStreams))) { return false; } if(isDslTopology() && (hasSpouts && hasBolts && hasStreams)) { return true; } return true; } }