Kendi Knime Eklentinizi Oluşturma Rehberi: Node Diyaloğunun Oluşturulması [2. Bölüm]
Kendi Knime Eklentinizi Oluşturma Rehberi serisinin ikinci yazısında tekrar birlikteyiz. Bir önceki yazıda geliştirme ortamını hazırlamıştık. Bu yazıda ise işin görsel tarafı olan diyalog penceresini tasarlayıp implemente edeceğiz. Bu uygulamada “ve”, “veya” gibi mantıksal işlemleri yapabilecek örnek bir node oluşturacağız. Daha açık anlatmak gerekirse aşağıdaki tabloya, örneğin “ve” mantıksal işlemini yaptığımızda…
A B
1 1
1 0
0 1
0 0
Sonuç aşağıdaki gibi olacaktır.
A B A_and_B
1 1 1
1 0 0
0 1 0
0 0 0
Şimdi bir önceki yazıda yaptığımız gibi bir node projesi oluşturalım. Projeyi oluşturmak için File + New + Other‘a tıklayın. Açılan pencerede Other dizininin altında Create a new KNIME Node-Extension seçeneğini seçip devam edin. Açılan pencerede projeniz ile ilgili bilgileri aşağıdaki şekilde (Ekran Görüntüsü-1) doldurabilirsiniz:
Burada (Ekran Görüntüsü-1) bir öncekinden farklı olarak Include sample code in generated classes seçeneğini kaldırıyoruz. Çünkü nodu sıfırdan kendimiz oluşturacağız.
Projeyi oluşturduktan sonra org.vbo.logicgate/src/org.vbo.logicgate dizini altında kullanacağımız dosyaları görebilirsiniz. Burada en çok kullanacağımız dosyalardan Dialog ile dosya biten node diyaloğunu tasarlamak için kullanacağımız dosya olacak, Model ile biten dosya ise mantıksal işlemleri yerine getiren fonksiyonları yazacağımız dosya olacak.
1- Node Diyaloğunun Tasarlanması
Bu aşamada aşağıda (Ekran Görüntüsü-2) son hali görünen pencereyi oluşturacağız.
Öncelikle burada (Ekran Görüntüsü-2) kullandığımız input sınıflarını tanıyalım:
Gate Type için: DialogComponentStringSelection
Input A ve Input B için: DialogComponentColumnNameSelection
Burada Options sekmesi altındaki pencereyi Logic Gate ve Input Columns olarak ikiye bölmüşüz. İlk kısım olan Logic Gate kısmına Gate Type isminde bir input objesi koymuşuz. Bu obje kullanıcının hangi mantıksal işlemi yapacağını seçmesini sağlıyor. İkinci kısım olan Input Columns kısmında ise bu noda girdi olarak verilen tablodaki hangi iki sütun arasında bu mantıksal işlemin yapılacağını seçmeye yarıyor.
Şimdi kodlamaya başlayalım. Öncelikle Model ile biten dosya içerisine inputların ayarlarını ekleyeceğiz. Bunun için dosyayı aşağıdaki şekilde düzenlemeniz yeterli olacaktır.
public class LogicGateNodeModel extends NodeModel { private static final NodeLogger LOGGER = NodeLogger.getLogger(LogicGateNodeModel.class); private static final String KEY_GATE_TYPE = "gate_type"; private static final String DEFAULT_GATE_TYPE = "AND"; private final SettingsModelString m_logicGateSettings = createGateTypeSettingsModel(); private static final String KEY_INPUT_A = "input_a"; private static final String DEFAULT_INPUT_A = ""; private final SettingsModelString m_inputASettings = createInputASettingsModel(); private static final String KEY_INPUT_B = "input_b"; private static final String DEFAULT_INPUT_B = ""; private final SettingsModelString m_inputBSettings = createInputBSettingsModel(); /** * Constructor for the node model. */ protected LogicGateNodeModel() { // TODO: Specify the amount of input and output ports needed. super(1, 1); } static SettingsModelString createGateTypeSettingsModel() { return new SettingsModelString(KEY_GATE_TYPE, DEFAULT_GATE_TYPE); } static SettingsModelString createInputASettingsModel() { return new SettingsModelString(KEY_INPUT_A, DEFAULT_INPUT_A); } static SettingsModelString createInputBSettingsModel() { return new SettingsModelString(KEY_INPUT_B, DEFAULT_INPUT_B); }
Burada Gate Type inputu için oluşturduğumuz KEY_GATE_TYPE değişkeni node diyaloğundaki Flow Variables sekmesi içerisinde bu inputun hangi isimle görüleceğini tutuyor. DEFAULT_GATE_TYPE değişkeni inputların ön tanımlı değerlerinin ne olacağını tutuyor. Son olarak m_logicGateSettings değişkeni ise inputa ait SettingsModelString üreten fonksiyonu tutuyor.
private static final String KEY_GATE_TYPE = "gate_type"; private static final String DEFAULT_GATE_TYPE = "AND"; private final SettingsModelString m_logicGateSettings = createGateTypeSettingsModel();
Bu değişkenleri ihtiyacımız olan tüm inputlar için oluşturuyoruz. Bunu yaptıktan sonra da aşağıda Gate Type inputu için örnek olarak verdiğim SettingsModelString üreten fonksiyonu tüm inputlar için oluşturuyoruz.
static SettingsModelString createGateTypeSettingsModel() { return new SettingsModelString(KEY_GATE_TYPE, DEFAULT_GATE_TYPE); }
Model dosyası içerisinde yapacaklarımızı tamamladık. Şimdi sıra arayüzün nasıl görüneceğini kodlamakta. Bunun için Dialog ile biten dosyayı aşağıdaki gibi düzenleyeceğiz.
@SuppressWarnings("unchecked") protected LogicGateNodeDialog() { super(); createNewGroup("Logic Gate"); SettingsModelString gateTypeSettings = LogicGateNodeModel.createGateTypeSettingsModel(); addDialogComponent(new DialogComponentStringSelection(gateTypeSettings, "Gate Type", "AND", "OR")); createNewGroup("Input Columns"); SettingsModelString inputASettings = LogicGateNodeModel.createInputASettingsModel(); addDialogComponent(new DialogComponentColumnNameSelection(inputASettings, "Input A", 0, true, IntValue.class)); SettingsModelString inputBSettings = LogicGateNodeModel.createInputBSettingsModel(); addDialogComponent(new DialogComponentColumnNameSelection(inputBSettings, "Input B", 0, true, IntValue.class)); }
Burada createNewGroup fonksiyonu pencere içerisindeki input bölmelerini bu örnekteki şekliyle Logic Gate input grubu ve Input Columns input grubu olarak pencereyi ikiye ayırmak için kullanıyoruz. Fonksiyon parametresi olarak input grubunun başlığı olarak görmek istediğimiz şekilde bir String veriyoruz. Daha sonra Gate Type inputu için aşağıdaki şekilde önceden Model dosyasında oluşturduğumuz SettingsModel‘i çağırıyoruz.
SettingsModelString gateTypeSettings = LogicGateNodeModel.createGateTypeSettingsModel();
Daha sonra da aşağıdaki şekilde input komponentini oluşturuyoruz.
addDialogComponent(new DialogComponentStringSelection(gateTypeSettings, "Gate Type", "AND", "OR"));
Burada ilk parametre olarak SettingsModel‘i veriyoruz, ikinci parametre olarak input başlığında görülecek String‘i veriyoruz, son olarak da kullanıcının seçebileceği seçenekleri istediğimiz kadar String şeklinde örnekteki gibi virgüllerle ayırarak veriyoruz. Burada örnek olarak “AND” ve “OR” seçeneklerini eklemiş olduk. Diğer inputlar için de hemen hemen aynı şeyleri yapmamız gerekiyor. Tek farklılık StringSelection yerine ColumnNameSelection komponenti kullanmamız. Burada ColumnNameSelection komponentinin parametreleri sırayla yine SettingsModel, input ismi, bu inputun girilmesinin zorunlu olup olmadığını belirleyen Boolean tipte bir değer ve bu örneğe özel olarak yalnızca tamsayı içeren sütunların seçilebilmesi sınırlamasını sağlayan IntValue.class objesi.
Yukarıda anlattığım işlemleri adım adım takip ederek en başta hedeflediğimiz node diğaloğunu oluşturabilirsiniz. Projeyi bir Knime Analytics Platform olarak çalıştırıp Node Repository içerisinden oluşturduğumuz nodu görebilirsiniz. Bu nodun üzerine çift tıklayarak aşağıdaki şekilde (Ekran Görüntüsü-3) tasarladığımız diğaloğu da kontrol edebilirsiniz. Eğer kodlarda bir hata yaşarsanız bu linkten üzerinde değişiklik yaptığımız dosyalara erişebilirsiniz.
Bu bölümün de sonuna geldik. Bir sonraki bölümde oluşturduğumuz nodun işlevsel tarafını kodlayacağız. Konuyla ilgili yaşadığınız sıkıntı ve önerileri benimle paylaşabilirsiniz.
Keyifli uygulamalar.