[GO] J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming [Development] (2/3)

introduction

Bonjour. Conseiller Yorozu Sugimon: miam:. Cette fois, je vais essayer de développer un composant (adaptateur) en utilisant le SDK de HULFT IoT Edge Streaming. Il est décrit de manière à être complété dans les trois parties.

Que faire cette fois

Cette fois, comme deuxième étape, je développerai un plug en utilisant le SDK HULFT IoT EdgeStreaming Plugin. Il existe d'autres articles sur la configuration et l'exécution, veuillez donc les consulter.

: arrow_forward: [J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming Configuration] (https://qiita.com/sugimon/items/cf7503479c6e4c46c3b3) : arrow_forward: J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming Développement : arrow_forward: [J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming Execution](https://qiita.com/sugimon/items/93f47d7bd472a8b18e54)

Présentation de la création d'un plug-in

La configuration pour créer un plug-in pour EdgeStreaming est la suivante. image.png

image.png

Configuration de l'environnement d'exécution

Il s'agit de la partie Runtime qui exécute le processus de streaming spécifié par Studio.

SourceOperation `Ceci est une opération pour générer des données de streaming (Tuple). Ce sera le "traitement d'entrée".

SinkOperation `Il s'agit d'une opération de sortie des données Streaming (Tuple) vers l'extérieur. Cela devient "traitement de sortie". ''

UDSFOperation Il s'agit d'une opération de conversion de données Streaming (Tuple). Il génère également le Streming converti (Tuple). "Traitement d'entrée / sortie (conversion)"

Configuration de l'environnement de développement

Génère un BQL (syntaxe de type SQL) qui indique à RunTime comment effectuer le traitement en continu.

AdapterModuleComponent ʻUne classe qui représente un composant (adaptateur). C'est plusieurs-à-un avec l'opération. ''

BQLPluginSourceOperationFactory `Définit les propriétés de SourceOperartion. "Traitement des entrées" Sort le BQL (instruction Create Source) qui crée l'opération Source. ''

BQLPluginOutputOperationFactory `Définit les propriétés de SinkOperation. "Traitement de sortie" Produit une instruction BQL (Create Sink) qui crée une opération Sink. ''

BQLPluginUDSFOperationFactory ʻDéfinir les propriétés UDSF. "Traitement d'entrée / sortie (conversion)" Sort une instruction BQL (instruction Select) qui génère une opération UDSF. ''

Créer un plug-in

Cette fois, j'ai essayé de créer un plug-in sous la forme suivante.

·Informations de base image.png

** ・ Informations sur le fonctionnement ** image.png

Implémentation côté environnement d'exécution (Golang)

Implémente le processus de streaming spécifié par Studio.

** Préparation environnementale **

  1. Création d'un répertoire de modules ・ $ SDK_HOME / dev / go / src / github.sis.saison.co.jp / sherpa / es-agent / sample
  1. Créez un répertoire de plugins ・ $ SDK_HOME / dev / go / src / github.sis.saison.co.jp / sherpa / es-agent / sample / plugin
  2. Créez un répertoire externe ・ $ SDK_HOME / dev / go / src / github.sis.saison.co.jp / sherpa / es-agent / sample / external

** Création d'un fichier source ** Créons un fichier source avec le nom de fichier suivant dans le répertoire du module (exemple dans ce cas).

-La structure du fichier est la suivante.

├─sample
│   ├─source.go (traitement d'entrée)
│   ├─sink.go (traitement de sortie)
│   ├─udsf.go (traitement de conversion entrée / sortie)
│   │ 
│   ├─external
│   │   ├─plugin_main.aller (fonction principale)
│   │   │ 
│   └─plugin
│   │   ├─plugin.go (enregistrez les fichiers source sous chaque échantillon)
│   │   │ 

Créons maintenant le fichier source.

** ・ source.go (traitement d'entrée) ** Créez un processus pour générer des nombres pseudo aléatoires à intervalles de temps réguliers. Le flux principal est le suivant.

  1. Recevoir le paramètre de type entier "intervalle"
  2. Générer des nombres pseudo aléatoires à des intervalles d'intervalle
  3. Générer un tuple avec des données de schéma JSON

Tuple


{
  "type": "object",
  "required": ["payload"],
  "properties": {
    "payload": {
      "type": "object",
      "required": ["value"],
      "properties": {
        "value": {
          "type": "number"
        }
      }
    }
  }
}

Les données Tuple JSON de sortie ont le format suivant.

{"payload": {"value": 3.5423242}}

J'ai créé source.go comme suit.

source.go


package sample

import (
	"math/rand"
	"time"

	"gopkg.in/sensorbee/sensorbee.v0/bql"
	"gopkg.in/sensorbee/sensorbee.v0/core"
	"gopkg.in/sensorbee/sensorbee.v0/data"
)

type source struct {
	interval time.Duration
	term     chan struct{}
}

func (s *source) GenerateStream(ctx *core.Context, w core.Writer) error {
	rand.Seed(time.Now().UnixNano())

	next := time.Now()
	for {
		val := rand.Float64()
		m := data.Map{"value": data.Float(val)}
		t := core.NewTuple(data.Map{"payload": m})
		if s.interval > 0 {
			t.Timestamp = next
		}
		ctx.Log().Debug("generation: ", val)
		if err := w.Write(ctx, t); err != nil {
			return err
		}

		if s.interval > 0 {
			now := time.Now()
			next = next.Add(s.interval)
			if next.Before(now) {
				next = now.Add(s.interval)
			}

			select {
			case <-s.term:
				return core.ErrSourceStopped
			case <-time.After(next.Sub(now)):
			}
		}
	}
	return nil
}

func (s *source) Stop(ctx *core.Context) error {
	s.term <- struct{}{}
	return nil
}

func CreateSource(ctx *core.Context, ioParams *bql.IOParams, params data.Map) (core.Source, error) {
	interval, err := getInterval(params)
	if err != nil {
		return nil, err
	}

	return &source{
		interval: interval,
		term:     make(chan struct{}),
	}, nil
}

func getInterval(params data.Map) (time.Duration, error) {
	interval := 1 * time.Second
	if v, ok := params["interval"]; ok {
		i, err := data.ToDuration(v)
		if err != nil {
			return interval, err
		}
		interval = i
	}
	return interval, nil
}

** ・ sink.go (traitement de sortie) ** Créez un processus pour tronquer par le nombre de chiffres décimaux effectifs et sortir dans le journal.

Le flux principal est le suivant.

  1. Recevoir le paramètre de type entier "décimal"
  2. Sortez la valeur reçue sur la sortie standard avec le nombre de chiffres décimaux valides de "décimal"
  3. Recevoir Tuple avec les données de schéma des données JSON`

Tuple


{
  "type": "object",
  "required": ["payload"],
  "properties": {
    "payload": {
      "type": "object",
      "required": ["value", "formula"],
      "properties": {
        "value": {
          "type": "number"
        }
        "formula": {
          "type": "string"
        }
      }
    }
  }
}

J'ai créé sink.go comme suit.

sink.go


package sample

import (
	"fmt"
	"math"

	"gopkg.in/sensorbee/sensorbee.v0/bql"
	"gopkg.in/sensorbee/sensorbee.v0/core"
	"gopkg.in/sensorbee/sensorbee.v0/data"
)

type sink struct {
	decimal int
}

func (s *sink) Write(ctx *core.Context, tuple *core.Tuple) error {
	p, ok := tuple.Data["payload"]
	if !ok {
		return fmt.Errorf("the tuple doesn't have the required field: payload")
	}

	payload, err := data.AsMap(p)
	if err != nil {
		return err
	}

	v, ok := payload["value"]
	if !ok {
		return fmt.Errorf("the tuple doesn't have the required field: value")
	}

	value, err := data.AsFloat(v)
	if err != nil {
		return err
	}

	f, ok := payload["formula"]
	if !ok {
		return fmt.Errorf("the tuple doesn't have the required field: formula")
	}

	formula, err := data.AsString(f)
	if err != nil {
		return err
	}
	shift := math.Pow(10, float64(s.decimal))
	value = math.Floor(value*shift) / shift
	ctx.Log().Infof("formula: %s", formula)
	ctx.Log().Infof("value: %f", value)
	return nil
}

func (s *sink) Close(ctx *core.Context) error {
	return nil
}

func CreateSink(ctx *core.Context, ioParams *bql.IOParams, params data.Map) (core.Sink, error) {
	decimal, err := getDecimal(params)
	if err != nil {
		return nil, err
	}

	return &sink{
		decimal: decimal,
	}, nil
}

func getDecimal(params data.Map) (int, error) {
	node, ok := params["decimal"]
	if !ok {
		return 0, fmt.Errorf("decimal is required")
	}
	decimal, err := data.AsInt(node)
	if err != nil {
		return 0, fmt.Errorf("decimal must be a int:%s", err)
	}
	return int(decimal), nil
}

** ・ udsf.go (traitement de conversion d'entrée / sortie) ** L'objet udsf reçoit les données suivantes:

L'objet udsf continue de calculer la valeur de l'élément de valeur Tuple reçu avec l'opérateur spécifié dans la valeur actuelle (valeur_initial au début).

J'ai créé udsf.go comme suit.

udsf.go


package sample

import (
	"fmt"

	"gopkg.in/sensorbee/sensorbee.v0/bql/udf"
	"gopkg.in/sensorbee/sensorbee.v0/core"
	"gopkg.in/sensorbee/sensorbee.v0/data"
)

type operator byte

const (
	none    = ' '
	plus    = '+'
	minus   = '-'
	times   = '*'
	divided = '/'
)

type udsf struct {
	cur float64
	ope operator
}

func (u *udsf) Process(ctx *core.Context, tuple *core.Tuple, w core.Writer) error {
	p, ok := tuple.Data["payload"]
	if !ok {
		return fmt.Errorf("the tuple doesn't have the required field: payload")
	}

	payload, err := data.AsMap(p)
	if err != nil {
		return err
	}

	v, ok := payload["value"]
	if !ok {
		return fmt.Errorf("the tuple doesn't have the required field: value")
	}

	value, err := data.AsFloat(v)
	if err != nil {
		return err
	}

	var formula string
	newVal := u.cur
	switch u.ope {
	case plus:
		newVal += value
	case minus:
		newVal -= value
	case times:
		newVal *= value
	case divided:
		newVal /= value
	}
	formula = fmt.Sprintf("%f %s %f", u.cur, string(u.ope), value)
	ctx.Log().Debug("calculate: " + formula)
	m := data.Map{
		"value":   data.Float(newVal),
		"formula": data.String(formula),
	}
	if err := w.Write(ctx, core.NewTuple(data.Map{"payload": m})); err != nil {
		return err
	}
	u.cur = newVal
	return nil
}

func (u *udsf) Terminate(ctx *core.Context) error {
	return nil
}

func CreateUDSF(decl udf.UDSFDeclarer, params data.Map) (udf.UDSF, error) {
	inputStream, err := getStreamName(params)
	if err != nil {
		return nil, err
	}

	operator, err := getOperator(params)
	if err != nil {
		return nil, err
	}

	initialValue, err := getInitialValue(params)
	if err != nil {
		return nil, err
	}

	if err := decl.Input(inputStream, nil); err != nil {
		return nil, err
	}

	return &udsf{
		ope: operator,
		cur: initialValue,
	}, nil
}

func getStreamName(params data.Map) (string, error) {
	node, ok := params["stream_name"]
	if !ok {
		return "", fmt.Errorf("stream_name is required")
	}
	streamName, err := data.AsString(node)
	if err != nil {
		return "", fmt.Errorf("stream_name must be a string:%s", err)
	}
	return streamName, nil
}

func getOperator(params data.Map) (operator, error) {
	node, ok := params["operator"]
	if !ok {
		return none, fmt.Errorf("operator is required")
	}
	operatorStr, err := data.AsString(node)
	if err != nil {
		return none, fmt.Errorf("operator must be a string:%s", err)
	}

	switch operatorStr {
	case "plus":
		return plus, nil
	case "minus":
		return minus, nil
	case "times":
		return times, nil
	case "divided":
		return divided, nil
	default:
		return none, fmt.Errorf("invalid oparator")
	}
}

func getInitialValue(params data.Map) (float64, error) {
	initialValue := 0.0
	node, ok := params["initial_value"]
	if !ok {
		return initialValue, nil
	}
	initialValue, err := data.AsFloat(node)
	if err != nil {
		return initialValue, fmt.Errorf("initial_value is invalid")
	}
	return initialValue, nil
}

** Enregistrement du fichier source ** Créez plugin.go dans le répertoire plugin et implémentez le processus d'enregistrement pour les opérations Source, Sink et UDSF (à utiliser comme BQL).

image.png

J'ai créé plugin.go comme suit.

plugin.go


package plugin

import (
	"github.sis.saison.co.jp/sherpa/es-agent/sample"
	"gopkg.in/sensorbee/sensorbee.v0/bql"
	"gopkg.in/sensorbee/sensorbee.v0/bql/udf"
)

func init() {
	bql.MustRegisterGlobalSourceCreator("sample_source", bql.SourceCreatorFunc(sample.CreateSource))
	bql.MustRegisterGlobalSinkCreator("sample_sink", bql.SinkCreatorFunc(sample.CreateSink))
	udf.MustRegisterGlobalUDSFCreator("sample_udsf", udf.MustConvertToUDSFCreator(sample.CreateUDSF))
}

** Création de la fonction principale ** Enfin, créez et implémentez plugin_main.go dans le répertoire externe de la fonction main qui appelle le processus en tant que module d'exécution unique.

J'ai créé plugin_main.go comme suit.

plugin_main.go



package main

import (
	"os"

	"github.sis.saison.co.jp/sherpa/es-agent/external/plugin"
	_ "github.sis.saison.co.jp/sherpa/es-agent/sample/plugin"
)

func main() {
	if err := plugin.NewServer().ListenAndServe(); err != nil {
		os.Exit(1)
	}
}

À ce stade, la préparation côté Runtime est terminée. Ensuite, nous implémenterons le côté environnement de développement.

Implémentation côté environnement de développement (Java)

Implémente la génération BQL (syntaxe de type SQL) qui indique à Runtime comment effectuer le traitement de streaming.

** Préparation environnementale ** ** Création d'un répertoire de modules ** -Créez le répertoire $ SDK_HOME / dev / sample_adapter.

** Copier un fichier ** -Copiez build.xml et config.properties dans le répertoire $ SDK_HOME / dev / conf dans le répertoire du module. $SDK_HOME/dev/conf/build.xml$SDK_HOME/dev/sample_adapter/build.xml $SDK_HOME/dev/conf/config.properties$SDK_HOME/dev/sample_adapter/config.propertites

Modifiez le fichier config.properties copié.

Implementation-Title=SampleAdapter
Implementation-Vendor=sugimon
Implementation-Version=0

module.category=Sample
module.label=Sample Plugin
display.name=Sample Plugin Adapter

plugin.name=sample_plugin
esagent.plugin.package=github.sis.saison.co.jp/sherpa/es-agent/sample

** Créer un répertoire pour les fichiers source ** Créez un répertoire src dans $ SDK_HOME / dev / sample_adapter. ($SDK_HOME/dev/sample_adapter/src)

Ensuite, créez le package de fichiers java com / appresso / ds / dp / modules / adapter / sample Créez un répertoire pour les packages suivants afin que ($SDK_HOME/dev/sample_adapter/src/com/appresso/ds/dp/modules/adapter/sample)

** Création d'un fichier source ** Créez un fichier source dans le répertoire du package avec le nom de fichier suivant.

・SampleAdapterModuleComponent.java ・SampleSinkOperationFactory.java ・SampleSourceOperationFactory.java ・SampleUDSFOperationFactory.java

├─ sample_adapter
│      │  build.xml
│      │  config.properties
│      ├─ src
│      │   └com
│      │     └appresso
│      │       └ds
│      │         └dp
│      │           └modules
│      │              └adapter
│      │                 └sample
│      │                    SampleAdapterModuleComponent.java
│      │                    SampleSinkOperationFactory.java
│      │                    SampleSourceOperationFactory.java
│      │                    SampleUDSFOperationFactory.java

Créons également un fichier source pour chacun d'entre eux.

** ・ SampleSourceOperationFactory.java (traitement d'entrée) ** Renvoie un objet contenant les propriétés de l'opération Source ou un objet d'opération. (Classe source d'héritage: classe BQLPluginSourceOperationFactory)

J'ai créé SampleSourceOperationFactory.java comme suit.

SampleSourceOperationFactory.java


package com.appresso.ds.dp.modules.adapter.sample;

import com.appresso.ds.common.spi.constraint.NumberFillin;
import com.appresso.ds.common.spi.param.SimpleParameter;
import com.appresso.ds.common.xmlfw.xml.XmlHandler;
import com.appresso.ds.dp.share.adapter.bql.common.BQLPluginSourceOperationFactory;
import com.appresso.ds.dp.spi.OperationConfiguration;
import com.appresso.ds.dp.spi.OperationConfigurator;
import org.xml.sax.SAXException;

import static com.appresso.ds.common.bql.BQLSimpleParameterType.FLOAT;

public class SampleSourceOperationFactory extends BQLPluginSourceOperationFactory {

	@Override
	protected String getLabel() {
		return "Sample source";
	}

	@Override
	protected String getPluginName() {
		return "sample_plugin";
	}

	@Override
	public String getOperationName() {
		return "sample_source";
	}

	@Override
	protected String getTypeName() {
		return "sample_source";
	}

	@Override
	protected void setupOperationConfigurator(OperationConfigurator operationConfigurator) {
		operationConfigurator.addSimpleParameter(createIntervalParameter());
	}

	@Override
	protected void setupOutputSchema(XmlHandler handler, OperationConfiguration conf) throws Exception {
		handler.startElement("", "payload", "payload", EMPTY_ATTRIBUTE);
		writeElement(handler, "value");
		handler.endElement("", "payload", "payload");
	}

	protected void writeElement(XmlHandler handler, String name) throws SAXException {
		handler.startElement("", name, name, EMPTY_ATTRIBUTE);
		handler.endElement("", name, name);
	}

	static SimpleParameter createIntervalParameter() {
		NumberFillin fillin = new NumberFillin();
		fillin.setMinValue(0.001);
		fillin.setMaxValue(1314000);
		fillin.setAllowMin(true);
		fillin.setAllowMax(true);
		fillin.setPrecision(10);
		fillin.setDecimal(3);
		fillin.setAllowDouble(true);
		fillin.setLabel("Interval[sec]");
		fillin.setRequired(true);
		return new SimpleParameter(FLOAT.toParameterKey("interval"), fillin);
	}
}

** ・ SampleSinkOperationFactory.java (traitement de sortie) ** Renvoie un objet contenant les propriétés d'une opération Sink ou d'un objet d'opération. (Classe source d'héritage: classe BQLPluginSinkOperationFactory)

J'ai créé SampleSinkOperationFactory.java comme suit.

SampleSinkOperationFactory.java


package com.appresso.ds.dp.modules.adapter.sample;

import com.appresso.ds.common.spi.constraint.NumberFillin;
import com.appresso.ds.common.spi.param.SimpleParameter;
import com.appresso.ds.common.xmlfw.xml.XmlHandler;
import com.appresso.ds.dp.share.adapter.bql.common.BQLPluginOutputOperationFactory;
import com.appresso.ds.dp.spi.OperationConfiguration;
import com.appresso.ds.dp.spi.OperationConfigurator;
import com.appresso.ds.dp.spi.OperationContext;
import org.xml.sax.SAXException;

import static com.appresso.ds.common.bql.BQLSimpleParameterType.INTEGER;

public class SampleSinkOperationFactory extends BQLPluginOutputOperationFactory {
	@Override
	protected String getLabel() {
		return "Sample sink";
	}

	@Override
	protected String getPluginName() {
		return "sample_plugin";
	}

	@Override
	public String getOperationName() {
		return "sample_sink";
	}

	@Override
	protected String getTypeName() {
		return "sample_sink";
	}

	@Override
	protected void setupOperationConfigurator(OperationConfigurator operationConfigurator) {
		operationConfigurator.addSimpleParameter(createDecimalParameter());
	}

	protected void setupInputSchema(XmlHandler handler, OperationConfiguration conf, OperationContext context)
			throws Exception {
		handler.startElement("", "payload", "payload", EMPTY_ATTRIBUTE);
		writeElement(handler, "formula");
		writeElement(handler, "value");
		handler.endElement("", "payload", "payload");
	}

	protected void writeElement(XmlHandler handler, String name) throws SAXException {
		handler.startElement("", name, name, EMPTY_ATTRIBUTE);
		handler.endElement("", name, name);
	}

	static SimpleParameter createDecimalParameter() {
		NumberFillin fillin = new NumberFillin();
		fillin.setMinValue(0);
		fillin.setMaxValue(10);
		fillin.setAllowMin(true);
		fillin.setAllowMax(true);
		fillin.setLabel("Decimal");
		fillin.setRequired(true);
		return new SimpleParameter(INTEGER.toParameterKey("decimal"), fillin);
	}
}


** ・ ExempleUDSFOperationFactory ** Renvoie un objet contenant les propriétés d'une opération UDSF ou d'un objet d'opération.

J'ai créé SampleUDSFOperationFactory.java comme suit.

SampleUDSFOperationFactory.java


package com.appresso.ds.dp.modules.adapter.sample;

import com.appresso.ds.common.bql.UDSFFromArgument;
import com.appresso.ds.common.bql.UDSFFromTemplate;
import com.appresso.ds.common.spi.constraint.Item;
import com.appresso.ds.common.spi.constraint.Multi;
import com.appresso.ds.common.spi.constraint.NumberFillin;
import com.appresso.ds.common.spi.param.SimpleParameter;
import com.appresso.ds.common.xmlfw.xml.XmlHandler;
import com.appresso.ds.dp.share.adapter.bql.common.BQLPluginUDSFOperationFactory;
import com.appresso.ds.dp.spi.OperationConfiguration;
import com.appresso.ds.dp.spi.OperationConfigurator;
import com.appresso.ds.dp.spi.OperationContext;
import org.xml.sax.SAXException;

import java.util.stream.Stream;

import static com.appresso.ds.common.bql.BQLSimpleParameterType.FLOAT;
import static com.appresso.ds.common.bql.BQLSimpleParameterType.STRING;

public class SampleUDSFOperationFactory extends BQLPluginUDSFOperationFactory {
	@Override
	protected String getLabel() {
		return "Sample UDSF";
	}

	@Override
	public String getPluginName() {
		return "sample_plugin";
	}

	@Override
	protected String getTypeName() {
		return "sample_udsf";
	}

	@Override
	public String getOperationName() {
		return "sample_udsf";
	}

	@Override
	protected void addArgs(UDSFFromTemplate template) {
		template.addArg(new UDSFFromArgument(STRING.toParameterKey("operator")));
		template.addArg(new UDSFFromArgument(FLOAT.toParameterKey("initial_value")));
	}

	@Override
	protected void setupOperationConfigurator(OperationConfigurator operationConfigurator) {
		setStreamConfigurationParameter(operationConfigurator);
		operationConfigurator.addSimpleParameter(createOperatorParameter());
		operationConfigurator.addSimpleParameter(createInitialValueParameter());
	}

	@Override
	protected void setupInputSchema(XmlHandler handler, OperationConfiguration conf, OperationContext context)
			throws Exception {
		handler.startElement("", "payload", "payload", EMPTY_ATTRIBUTE);
		writeElement(handler, "value");
		handler.endElement("", "payload", "payload");
	}

	@Override
	protected void setupOutputSchema(XmlHandler handler, OperationConfiguration conf, OperationContext context)
			throws Exception {
		handler.startElement("", "payload", "payload", EMPTY_ATTRIBUTE);
		writeElement(handler, "formula");
		writeElement(handler, "value");
		handler.endElement("", "payload", "payload");
	}

	protected void writeElement(XmlHandler handler, String name) throws SAXException {
		handler.startElement("", name, name, EMPTY_ATTRIBUTE);
		handler.endElement("", name, name);
	}

	static SimpleParameter createInitialValueParameter() {
		NumberFillin fillin = new NumberFillin();
		fillin.setPrecision(10);
		fillin.setDecimal(3);
		fillin.setAllowDouble(true);
		fillin.setLabel("Initial value");
		fillin.setRequired(true);
		return new SimpleParameter(FLOAT.toParameterKey("initial_value"), fillin);
	}

	static SimpleParameter createOperatorParameter(){
		Multi multi = new Multi(Operator.getItems());
		multi.setLabel("Operator");
		multi.setRequired(true);
		SimpleParameter param = new SimpleParameter(STRING.toParameterKey("operator"), multi);
		return param;
	}

	enum Operator {
		Plus("+","plus"),
		Minus("-","minus"),
		Times("*","times"),
		Divided("/","divided");

		public String getDisplayName() {
			return displayName;
		}

		public String getValue() {
			return value;
		}

		private final String displayName;

		private final String value;

		private Operator(String displayName, String value) {
			this.displayName = displayName;
			this.value=value;
		}

		Item toItem(){
			return new Item(value,displayName);
		}

		static Item[] getItems(){
			return Stream.of(Operator.values()).map(s->s.toItem()).toArray(Item[]::new);
		}
	}
}

** ・ SampleAdapterModuleComponent ** Une classe qui représente un composant (adaptateur).

J'ai créé SampleAdapterModuleComponent.java comme suit.

SampleAdapterModuleComponent.java


package com.appresso.ds.dp.modules.adapter.sample;

import java.util.ArrayList;
import java.util.List;

import com.appresso.ds.common.kernel.modules.LicenseManager;
import com.appresso.ds.common.license.LicensePackageType;
import com.appresso.ds.dp.spi.AdapterModuleComponent;
import com.appresso.ds.dp.spi.OperationFactory;
import com.appresso.ds.dp.spi.ResourceFactory;

public class SampleAdapterModuleComponent extends AdapterModuleComponent {

	private static final String MODULE_COMPONENT_NAME = "Sample Adapter";

	@Override
	public OperationFactory[] getOperationFactories() throws Exception {
		List<OperationFactory> operationFactories = new ArrayList<>();
		operationFactories.add(new SampleSourceOperationFactory());
		operationFactories.add(new SampleUDSFOperationFactory());
		operationFactories.add(new SampleSinkOperationFactory());
		return operationFactories.toArray(new OperationFactory[operationFactories.size()]);
	}

	@Override
	public ResourceFactory[] getResourceFactories() throws Exception {
		return new ResourceFactory[]{};
	}

	public void checkLicense() throws Exception {
		LicenseManager licenseManager = getContext().getProxy(LicenseManager.class);
		licenseManager.checkLicense(getModuleComponentName(), getPermittedPackageType());
	}

	private String getModuleComponentName() {
		return MODULE_COMPONENT_NAME;
	}

	private int[] getPermittedPackageType() {
		return new int[]{LicensePackageType.TYPE_BASIC_SERVER};
	}
}

finalement

Cette fois, j'ai mis en œuvre le traitement séparément pour le côté environnement d'exécution et le côté environnement de développement. Ceci termine le processus de création du plug-in. La prochaine fois, j'aimerais les construire et les exécuter.

Dans ce blog, je voudrais continuer à présenter le contenu des consultations au "Yorozu Consultation Counter" de la technologie et les astuces qui sont nées.

Veuillez continuer à le vérifier et nous suivre si vous le souhaitez.

À la prochaine!

Recommended Posts

J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming [Development] (2/3)
J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming [Execution] (3/3)
J'ai essayé de créer un plug-in avec HULFT IoT Edge Streaming [Setup] (1/3)
J'ai essayé de créer automatiquement un rapport avec la chaîne de Markov
J'ai essayé de créer un linebot (implémentation)
J'ai essayé de créer un linebot (préparation)
J'ai essayé de créer une liste de nombres premiers avec python
J'ai essayé de créer des taureaux et des vaches avec un programme shell
J'ai essayé de mettre HULFT IoT (Edge Streaming) dans la passerelle Rooster de Sun Electronics
J'ai essayé de créer un programme qui convertit les nombres hexadécimaux en nombres décimaux avec python
Je souhaite créer un type d'implémentation pouvant être branché
[Outlook] J'ai essayé de créer automatiquement un e-mail de rapport quotidien avec Python
J'ai essayé de créer un environnement de développement Mac Python avec pythonz + direnv
Quand j'ai essayé de créer un environnement virtuel avec Python, cela n'a pas fonctionné
J'ai essayé de créer facilement un système de présence entièrement automatique avec Selenium + Python
J'ai essayé de créer un bouton pour Slack avec Raspeye + Tact Switch
J'ai essayé de créer un modèle avec l'exemple d'Amazon SageMaker Autopilot
Comment créer un sous-menu avec le plug-in [Blender]
Je souhaite créer manuellement une légende avec matplotlib
J'ai essayé de créer un environnement d'apprentissage amélioré pour Othello avec Open AI gym
[Python] J'ai essayé de créer automatiquement un rapport quotidien de YWT avec la messagerie Outlook
J'ai essayé de créer une classe pour rechercher des fichiers avec la méthode Glob de Python dans VBA
J'ai essayé de créer un cadre de données pandas en grattant les informations de rappel d'aliments avec Python
J'ai essayé d'implémenter une ligne moyenne mobile de volume avec Quantx
J'ai essayé de résoudre le problème d'optimisation des combinaisons avec Qiskit
J'ai essayé de commencer avec Hy ・ Définir une classe
J'ai essayé de trier une colonne FizzBuzz aléatoire avec un tri à bulles.
J'ai essayé de créer un bot pour annoncer un événement Wiire
J'ai essayé d'écrire dans un modèle de langage profondément appris
J'ai essayé de créer un article dans Wiki.js avec SQL Alchemy
J'ai essayé de l'activer / de le désactiver en définissant "Créer un plug-in qui met en évidence les espaces pleine largeur avec Sublime Text 2".
J'ai essayé de créer l'API Quip
J'ai écrit un script pour créer rapidement un environnement de développement pour Twitter Bot avec AWS Lambda + Python 2.7
[5e] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé de créer un environnement serveur qui fonctionne sous Windows 10
J'ai essayé de créer un pointage de crédit simple avec régression logistique.
[2nd] J'ai essayé de créer un certain outil de type Authenticator avec python
Un mémorandum lors de l'acquisition automatique avec du sélénium
[Python] Un mémo que j'ai essayé de démarrer avec asyncio
J'ai essayé de faire un processus d'exécution périodique avec Selenium et Python
J'ai essayé d'enregistrer une station sur la plateforme IoT "Rimotte"
J'ai essayé de créer une application de notification de publication à 2 canaux avec Python
J'ai essayé de créer une application todo en utilisant une bouteille avec python
[4th] J'ai essayé de créer un certain outil de type Authenticator avec python
[1er] J'ai essayé de créer un certain outil de type Authenticator avec python
J'ai essayé de faire une étrange citation pour Jojo avec LSTM
J'ai essayé de créer un mécanisme de contrôle exclusif avec Go
J'ai essayé de déverrouiller l'entrée 2 lock sésame d'une simple pression sur le bouton AWS IoT
J'ai essayé de créer facilement une image 3D de haute précision avec une seule photo [2]. (Essayez de traiter la profondeur avec numpy)
J'ai essayé d'implémenter Autoencoder avec TensorFlow
J'ai essayé de commencer avec Hy
J'ai essayé un langage fonctionnel avec Python
J'ai essayé d'implémenter CVAE avec PyTorch
J'ai créé une API Web
J'ai essayé de résoudre TSP avec QAOA
J'ai essayé de communiquer avec un serveur distant par communication Socket avec Python.