/** * Copyright 2013-2015 Pierre Merienne * * Licensed 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 stormy.pythian.component; import static org.apache.commons.lang.RandomStringUtils.randomAlphabetic; import static stormy.pythian.model.annotation.ComponentType.NO_TYPE; import static stormy.pythian.model.instance.FeatureType.DATE; import static stormy.pythian.model.instance.FeatureType.DECIMAL; import static stormy.pythian.model.instance.FeatureType.INTEGER; import static stormy.pythian.model.instance.FeatureType.TEXT; import static stormy.pythian.model.instance.Instance.NEW_INSTANCE_FIELD; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import storm.trident.Stream; import storm.trident.TridentTopology; import storm.trident.operation.BaseFunction; import storm.trident.operation.TridentCollector; import storm.trident.state.StateFactory; import storm.trident.tuple.TridentTuple; import stormy.pythian.model.annotation.Documentation; import stormy.pythian.model.annotation.ExpectedFeature; import stormy.pythian.model.annotation.InputStream; import stormy.pythian.model.annotation.ListMapper; import stormy.pythian.model.annotation.NameMapper; import stormy.pythian.model.annotation.OutputStream; import stormy.pythian.model.annotation.Property; import stormy.pythian.model.annotation.State; import stormy.pythian.model.annotation.Topology; import stormy.pythian.model.component.Component; import stormy.pythian.model.instance.DateFeature; import stormy.pythian.model.instance.Feature; import stormy.pythian.model.instance.Instance; import stormy.pythian.model.instance.IntegerFeature; import stormy.pythian.model.instance.ListedFeaturesMapper; import stormy.pythian.model.instance.NamedFeaturesMapper; import backtype.storm.spout.SpoutOutputCollector; import backtype.storm.task.TopologyContext; import backtype.storm.topology.OutputFieldsDeclarer; import backtype.storm.topology.base.BaseRichSpout; import backtype.storm.tuple.Fields; import backtype.storm.tuple.Values; import backtype.storm.utils.Utils; @SuppressWarnings("serial") @Documentation(name = "Test", description = "Use me as a test for component edition", type = NO_TYPE) public class TestComponent implements Component { @InputStream(name = "Input 1") private Stream input1; @NameMapper(stream = "Input 1", expectedFeatures = { @ExpectedFeature(name = "Double", type = DECIMAL), @ExpectedFeature(name = "Integer", type = INTEGER), @ExpectedFeature(name = "String", type = TEXT), }) private NamedFeaturesMapper intput1Mapper; @InputStream(name = "Input 2") private Stream input2; @ListMapper(stream = "Input 2") private ListedFeaturesMapper intput2Mapper; @OutputStream(name = "Output 1", from = "Input 1") private Stream output1; @NameMapper(stream = "Output 1", expectedFeatures = { @ExpectedFeature(name = "Date", type = DATE) }) private NamedFeaturesMapper output1Mapper; @OutputStream(name = "Output 2", from = "Input 2") private Stream output2; @NameMapper(stream = "Output 2", expectedFeatures = { @ExpectedFeature(name = "Feature count", type = INTEGER) }) private NamedFeaturesMapper output2Mapper; @OutputStream(name = "Output 3") private Stream output3; @ListMapper(stream = "Output 3") private ListedFeaturesMapper output3Mapper; @Property(name = "String property", description = "I'm a mandatory string", mandatory = true) private String stringProp; @Property(name = "Integer property", description = "I'm a integer", mandatory = false) private Integer integerProp; @Property(name = "Double property", description = "I'm a double", mandatory = false) private Double doubleProp; @Property(name = "Number property", description = "I'm a number", mandatory = false) private Number numberProp; @Property(name = "Boolean property", description = "I'm a mandatory boolean", mandatory = true) private Boolean booleanProp; @Property(name = "Enum property 1", description = "I'm a enum", mandatory = false) private TestEnum enumProp1; @Property(name = "Enum property 2", description = "I'm a mandatory enum", mandatory = true) private TestEnum enumProp2; @State(name = "Test's state") private StateFactory stateFactory; @Topology private TridentTopology topology; @Override public void init() { output1 = input1.each(new BaseFunction() { @Override public void execute(TridentTuple tuple, TridentCollector collector) { Instance instance = Instance.get(tuple, (NamedFeaturesMapper) null, output1Mapper); instance.setFeature("Date", new DateFeature(new Date())); collector.emit(new Values(instance)); } }, new Fields(NEW_INSTANCE_FIELD)); output2 = input2.each(new BaseFunction() { @Override public void execute(TridentTuple tuple, TridentCollector collector) { Instance instance = Instance.get(tuple, (NamedFeaturesMapper) null, output2Mapper); instance.setFeature("Feature count", new IntegerFeature((long) instance.size())); collector.emit(new Values(instance)); } }, new Fields(NEW_INSTANCE_FIELD)); output3 = topology.newStream(randomAlphabetic(6), new BaseRichSpout() { private SpoutOutputCollector _collector; @Override public void declareOutputFields(OutputFieldsDeclarer declarer) { declarer.declare(new Fields(NEW_INSTANCE_FIELD)); } @Override public void open(@SuppressWarnings("rawtypes") Map conf, TopologyContext context, SpoutOutputCollector collector) { _collector = collector; } @Override public void nextTuple() { Utils.sleep(200); List<Feature<?>> features = new ArrayList<>(); for (int i = 0; i < output2Mapper.size(); i++) { features.add(new IntegerFeature((long) i)); } Instance newInstance = Instance.create(output3Mapper); newInstance.addFeatures(features); _collector.emit(new Values(newInstance)); } }); } public static enum TestEnum { VALUE1, VALUE2, VALUE3, VALUE4; } }