Search in sources :

Example 1 with InCol

use of org.knime.base.node.jsnippet.util.field.InCol in project knime-core by knime.

the class InFieldsTable method updateData.

/**
 * Set the table data.
 *
 * @param fields the fields
 * @param spec the input spec might be null
 * @param flowVars the flow variables
 */
void updateData(final JavaSnippetFields fields, final DataTableSpec spec, final Map<String, FlowVariable> flowVars) {
    m_spec = spec;
    m_flowVars = flowVars;
    m_model.clear();
    for (int r = 0; r < fields.getInColFields().size(); r++) {
        InCol field = fields.getInColFields().get(r);
        m_model.addRow();
        String colName = field.getKnimeName();
        DataColumnSpec colSpec = spec.getColumnSpec(colName);
        Object value = null != colSpec ? colSpec : colName;
        m_model.setValueAt(value, r, Column.COLUMN);
        m_model.setValueAt(field.getJavaName(), r, Column.JAVA_FIELD);
        Optional<?> factory = ConverterUtil.getDataCellToJavaConverterFactory(field.getConverterFactoryId());
        if (!factory.isPresent()) {
            // seems to be missing.
            if (field.getJavaType() != null) {
                factory = ConverterUtil.getConverterFactory(field.getDataType(), field.getJavaType());
            }
        }
        if (factory.isPresent()) {
            m_model.setValueAt(factory.get(), r, Column.JAVA_TYPE);
        } else {
            final Class<?> type = field.getJavaType();
            if (type != null) {
                m_model.setValueAt(type, r, Column.JAVA_TYPE);
            } else {
                m_model.setValueAt(field.getJavaTypeName(), r, Column.JAVA_TYPE);
            }
        }
    }
    int offset = m_model.getRowCount();
    for (int r = 0; r < fields.getInVarFields().size(); r++) {
        InVar field = fields.getInVarFields().get(r);
        m_model.addRow();
        String name = field.getKnimeName();
        FlowVariable flowVar = m_flowVars.get(name);
        Object value = null != flowVar ? flowVar : name;
        m_model.setValueAt(value, offset + r, Column.COLUMN);
        m_model.setValueAt(field.getJavaName(), offset + r, Column.JAVA_FIELD);
        m_model.setValueAt(field.getJavaType(), offset + r, Column.JAVA_TYPE);
    }
    JTable table = getTable();
    final TableColumnModel columnModel = table.getColumnModel();
    columnModel.getColumn(m_model.getIndex(Column.COLUMN)).setCellRenderer(new InputTableCellRenderer());
    columnModel.getColumn(m_model.getIndex(Column.COLUMN)).setCellEditor(createInputCellEditor());
    columnModel.getColumn(m_model.getIndex(Column.JAVA_FIELD)).setCellRenderer(FieldsTableUtil.createJavaFieldTableCellRenderer());
    columnModel.getColumn(m_model.getIndex(Column.JAVA_TYPE)).setCellRenderer(FieldsTableUtil.createJavaTypeTableCellRenderer());
    columnModel.getColumn(m_model.getIndex(Column.JAVA_TYPE)).setCellEditor(FieldsTableUtil.createJavaTypeTableCellEditor());
}
Also used : DataColumnSpec(org.knime.core.data.DataColumnSpec) JTable(javax.swing.JTable) TableColumnModel(javax.swing.table.TableColumnModel) InVar(org.knime.base.node.jsnippet.util.field.InVar) InCol(org.knime.base.node.jsnippet.util.field.InCol) FlowVariable(org.knime.core.node.workflow.FlowVariable)

Example 2 with InCol

use of org.knime.base.node.jsnippet.util.field.InCol in project knime-core by knime.

the class JavaSnippet method getAdditionalBuildPaths.

@Override
public File[] getAdditionalBuildPaths() {
    final Set<File> result = new LinkedHashSet<>();
    for (InCol colField : m_fields.getInColFields()) {
        final String factoryId = colField.getConverterFactoryId();
        final Collection<? extends File> buildPath = getBuildPathFromCache(factoryId);
        if (buildPath != null) {
            result.addAll(buildPath);
        }
    }
    for (OutCol colField : m_fields.getOutColFields()) {
        final String factoryId = colField.getConverterFactoryId();
        final Collection<? extends File> buildPath = getBuildPathFromCache(factoryId);
        if (buildPath != null) {
            result.addAll(buildPath);
        }
    }
    return result.toArray(new File[result.size()]);
}
Also used : LinkedHashSet(java.util.LinkedHashSet) OutCol(org.knime.base.node.jsnippet.util.field.OutCol) InCol(org.knime.base.node.jsnippet.util.field.InCol) File(java.io.File) BundleFile(org.eclipse.osgi.storage.bundlefile.BundleFile)

Example 3 with InCol

use of org.knime.base.node.jsnippet.util.field.InCol in project knime-core by knime.

the class JavaSnippet method createFieldsSection.

/**
 * Create the system variable (input and output) section of the snippet.
 */
private String createFieldsSection() {
    StringBuilder out = new StringBuilder();
    out.append("// system variables\n");
    out.append("public class JSnippet extends AbstractJSnippet {\n");
    if (m_fields.getInColFields().size() > 0) {
        out.append("  // Fields for input columns\n");
        for (InCol field : m_fields.getInColFields()) {
            out.append("/** Input column: \"");
            out.append(field.getKnimeName());
            out.append("\" */\n");
            appendFields(out, field);
        }
    }
    if (m_fields.getInVarFields().size() > 0) {
        out.append("  // Fields for input flow variables\n");
        for (InVar field : m_fields.getInVarFields()) {
            out.append("/** Input flow variable: \"");
            out.append(field.getKnimeName());
            out.append("\" */\n");
            appendFields(out, field);
        }
    }
    out.append("\n");
    if (m_fields.getOutColFields().size() > 0) {
        out.append("  // Fields for output columns\n");
        for (OutCol field : m_fields.getOutColFields()) {
            out.append("/** Output column: \"");
            out.append(field.getKnimeName());
            out.append("\" */\n");
            appendFields(out, field);
        }
    }
    if (m_fields.getOutVarFields().size() > 0) {
        out.append("  // Fields for output flow variables\n");
        for (OutVar field : m_fields.getOutVarFields()) {
            out.append("/** Output flow variable: \"");
            out.append(field.getKnimeName());
            out.append("\" */\n");
            appendFields(out, field);
        }
    }
    out.append("\n");
    return out.toString();
}
Also used : OutCol(org.knime.base.node.jsnippet.util.field.OutCol) InVar(org.knime.base.node.jsnippet.util.field.InVar) InCol(org.knime.base.node.jsnippet.util.field.InCol) OutVar(org.knime.base.node.jsnippet.util.field.OutVar)

Example 4 with InCol

use of org.knime.base.node.jsnippet.util.field.InCol in project knime-core by knime.

the class JavaSnippet method createSnippetClass.

/**
 * Create the class file of the snippet.
 *
 * Creates a URLClassLoader which may open jar files referenced by the Java Snippet class. Make sure to match every
 * call to this method with a call to {@link #close()} in order for KNIME to be able to clean up .jar files that
 * were downloaded from URLs.
 *
 * @return the compiled snippet
 */
@SuppressWarnings("unchecked")
private Class<? extends AbstractJSnippet> createSnippetClass() {
    JavaSnippetCompiler compiler = new JavaSnippetCompiler(this);
    /* Recompile/Reload either if the code changed or the class loader has been closed since */
    if (m_classLoader != null && m_snippetCache.isValid(getDocument())) {
        if (!m_snippetCache.hasCustomFields()) {
            return m_snippetCache.getSnippetClass();
        }
    } else {
        // recompile
        m_snippetCache.invalidate();
        StringWriter log = new StringWriter();
        DiagnosticCollector<JavaFileObject> digsCollector = new DiagnosticCollector<>();
        CompilationTask compileTask = null;
        try {
            compileTask = compiler.getTask(log, digsCollector);
        } catch (IOException e) {
            throw new IllegalStateException("Compile with errors: " + e.getMessage(), e);
        }
        boolean success = compileTask.call();
        if (!success) {
            StringBuilder msg = new StringBuilder();
            msg.append("Compile with errors:\n");
            for (Diagnostic<? extends JavaFileObject> d : digsCollector.getDiagnostics()) {
                boolean isSnippet = this.isSnippetSource(d.getSource());
                if (isSnippet && d.getKind().equals(javax.tools.Diagnostic.Kind.ERROR)) {
                    long line = d.getLineNumber();
                    if (line != Diagnostic.NOPOS) {
                        msg.append("Error in line " + line + ": ");
                    } else {
                        msg.append("Error: ");
                    }
                    msg.append(d.getMessage(Locale.US));
                    msg.append('\n');
                }
            }
            throw new IllegalStateException(msg.toString());
        }
    }
    try {
        close();
        final LinkedHashSet<ClassLoader> customTypeClassLoaders = new LinkedHashSet<>();
        customTypeClassLoaders.add(JavaSnippet.class.getClassLoader());
        for (final InCol col : m_fields.getInColFields()) {
            customTypeClassLoaders.addAll(getClassLoadersFor(col.getConverterFactoryId()));
        }
        for (final OutCol col : m_fields.getOutColFields()) {
            customTypeClassLoaders.addAll(getClassLoadersFor(col.getConverterFactoryId()));
        }
        /* Add class loaders of additional bundles */
        customTypeClassLoaders.addAll(getAdditionalBundlesClassLoaders());
        // remove core class loader:
        // (a) it's referenced via JavaSnippet.class classloader and
        // (b) it would collect buddies when used directly (see support ticket #1943)
        customTypeClassLoaders.remove(DataCellToJavaConverterRegistry.class.getClassLoader());
        final MultiParentClassLoader customTypeLoader = new MultiParentClassLoader(customTypeClassLoaders.stream().toArray(ClassLoader[]::new));
        // TODO (Next version bump) change return value of createClassLoader instead of cast
        m_classLoader = (URLClassLoader) compiler.createClassLoader(customTypeLoader);
        Class<? extends AbstractJSnippet> snippetClass = (Class<? extends AbstractJSnippet>) m_classLoader.loadClass("JSnippet");
        m_snippetCache.update(getDocument(), snippetClass, m_settings);
        return snippetClass;
    } catch (ClassNotFoundException e) {
        throw new IllegalStateException("Could not load class file.", e);
    } catch (IOException e) {
        throw new IllegalStateException("Could not load jar files.", e);
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) DataCellToJavaConverterRegistry(org.knime.core.data.convert.java.DataCellToJavaConverterRegistry) OutCol(org.knime.base.node.jsnippet.util.field.OutCol) MultiParentClassLoader(org.knime.core.data.convert.util.MultiParentClassLoader) IOException(java.io.IOException) InCol(org.knime.base.node.jsnippet.util.field.InCol) CompilationTask(javax.tools.JavaCompiler.CompilationTask) JavaFileObject(javax.tools.JavaFileObject) StringWriter(java.io.StringWriter) AbstractJSnippet(org.knime.base.node.jsnippet.expression.AbstractJSnippet) URLClassLoader(java.net.URLClassLoader) MultiParentClassLoader(org.knime.core.data.convert.util.MultiParentClassLoader) ModuleClassLoader(org.eclipse.osgi.internal.loader.ModuleClassLoader) DiagnosticCollector(javax.tools.DiagnosticCollector) JavaSnippetCompiler(org.knime.base.node.jsnippet.util.JavaSnippetCompiler)

Example 5 with InCol

use of org.knime.base.node.jsnippet.util.field.InCol in project knime-core by knime.

the class JavaSnippet method validateSettings.

/**
 * Validate settings which is typically called in the configure method of a node.
 *
 * What is checked:
 * <ul>
 * <li>Whether converter factories matching the ids from the settings exist</li>
 * <li>Whether the code compiles</li>
 * <li>Whether columns required by input mappings still exist.</li>
 * </ul>
 *
 * @param spec the spec of the data table at the inport
 * @param flowVariableRepository the flow variables at the inport
 * @return the validation results
 */
public ValidationReport validateSettings(final DataTableSpec spec, final FlowVariableRepository flowVariableRepository) {
    List<String> errors = new ArrayList<>();
    List<String> warnings = new ArrayList<>();
    // check input fields
    for (final InCol field : m_fields.getInColFields()) {
        final int index = spec.findColumnIndex(field.getKnimeName());
        if (index < 0) {
            errors.add("The column \"" + field.getKnimeName() + "\" is not found in the input table.");
        } else {
            final DataColumnSpec colSpec = spec.getColumnSpec(index);
            final DataType type = colSpec.getType();
            if (!type.equals(field.getDataType())) {
                // Input column type changed, try to find new converter
                final Optional<?> factory = ConverterUtil.getConverterFactory(type, field.getJavaType());
                if (factory.isPresent()) {
                    warnings.add("The type of the column \"" + field.getKnimeName() + "\" has changed but is compatible.");
                    field.setConverterFactory(type, (DataCellToJavaConverterFactory<?, ?>) factory.get());
                } else {
                    errors.add("The type of the column \"" + field.getKnimeName() + "\" has changed.");
                }
            }
        }
        if (!field.getConverterFactory().isPresent()) {
            errors.add(String.format("Missing converter for column '%s' to java field '%s' (converter id: '%s')", field.getKnimeName(), field.getJavaName(), field.getConverterFactoryId()));
        }
    }
    // check input variables
    for (InVar field : m_fields.getInVarFields()) {
        FlowVariable var = flowVariableRepository.getFlowVariable(field.getKnimeName());
        if (var != null) {
            if (!var.getType().equals(field.getFlowVarType())) {
                errors.add("The type of the flow variable \"" + field.getKnimeName() + "\" has changed.");
            }
        } else {
            errors.add("The flow variable \"" + field.getKnimeName() + "\" is not found in the input.");
        }
    }
    // check output fields
    for (OutCol field : m_fields.getOutColFields()) {
        if (field.getJavaType() == null) {
            errors.add("Java type could not be loaded. Providing plugin may be missing.");
        }
        int index = spec.findColumnIndex(field.getKnimeName());
        if (field.getReplaceExisting() && index < 0) {
            errors.add("The output column \"" + field.getKnimeName() + "\" is marked to be a replacement, " + "but an input with this name does not exist.");
        }
        if (!field.getReplaceExisting() && index > 0) {
            errors.add("The output column \"" + field.getKnimeName() + "\" is marked to be new, " + "but an input with this name does exist.");
        }
        if (!field.getConverterFactory().isPresent()) {
            errors.add(String.format("Missing converter for java field '%s' to column '%s' (converter id: '%s')", field.getJavaName(), field.getKnimeName(), field.getConverterFactoryId()));
        }
    }
    // check output variables
    for (OutVar field : m_fields.getOutVarFields()) {
        FlowVariable var = flowVariableRepository.getFlowVariable(field.getKnimeName());
        if (field.getReplaceExisting() && var == null) {
            errors.add("The output flow variable \"" + field.getKnimeName() + "\" is marked to be a replacement, " + "but an input with this name does not exist.");
        }
        if (!field.getReplaceExisting() && var != null) {
            errors.add("The output flow variable \"" + field.getKnimeName() + "\" is marked to be new, " + "but an input with this name does exist.");
        }
    }
    // Check additional bundles
    for (final String bundleName : m_settings.getBundles()) {
        final Bundle bundle = Platform.getBundle(bundleName);
        if (bundle == null) {
            errors.add("Bundle \"" + bundleName + "\" required by this snippet was not found.");
        } else {
        // TODO Version warning?
        }
    }
    try {
        // test if snippet compiles and if the file can be created
        createSnippetClass();
    } catch (Exception e) {
        errors.add(e.getMessage());
    } finally {
        close();
    }
    return new ValidationReport(errors.toArray(new String[errors.size()]), warnings.toArray(new String[warnings.size()]));
}
Also used : Bundle(org.osgi.framework.Bundle) OutCol(org.knime.base.node.jsnippet.util.field.OutCol) ArrayList(java.util.ArrayList) InCol(org.knime.base.node.jsnippet.util.field.InCol) OutVar(org.knime.base.node.jsnippet.util.field.OutVar) CanceledExecutionException(org.knime.core.node.CanceledExecutionException) BadLocationException(javax.swing.text.BadLocationException) IOException(java.io.IOException) FlowVariableException(org.knime.base.node.jsnippet.expression.FlowVariableException) InvalidSettingsException(org.knime.core.node.InvalidSettingsException) ColumnException(org.knime.base.node.jsnippet.expression.ColumnException) TypeException(org.knime.base.node.jsnippet.expression.TypeException) MalformedURLException(java.net.MalformedURLException) DataColumnSpec(org.knime.core.data.DataColumnSpec) ValidationReport(org.knime.base.node.jsnippet.util.ValidationReport) DataType(org.knime.core.data.DataType) InVar(org.knime.base.node.jsnippet.util.field.InVar) FlowVariable(org.knime.core.node.workflow.FlowVariable)

Aggregations

InCol (org.knime.base.node.jsnippet.util.field.InCol)7 OutCol (org.knime.base.node.jsnippet.util.field.OutCol)5 InVar (org.knime.base.node.jsnippet.util.field.InVar)4 OutVar (org.knime.base.node.jsnippet.util.field.OutVar)3 DataColumnSpec (org.knime.core.data.DataColumnSpec)3 FlowVariable (org.knime.core.node.workflow.FlowVariable)3 IOException (java.io.IOException)2 ArrayList (java.util.ArrayList)2 LinkedHashSet (java.util.LinkedHashSet)2 TypeException (org.knime.base.node.jsnippet.expression.TypeException)2 DataType (org.knime.core.data.DataType)2 DataCellToJavaConverterFactory (org.knime.core.data.convert.java.DataCellToJavaConverterFactory)2 Closeable (java.io.Closeable)1 File (java.io.File)1 StringWriter (java.io.StringWriter)1 Field (java.lang.reflect.Field)1 MalformedURLException (java.net.MalformedURLException)1 URLClassLoader (java.net.URLClassLoader)1 JTable (javax.swing.JTable)1 TableColumnModel (javax.swing.table.TableColumnModel)1