Можно ли запустить сценарий Xbase из Java во время выполнения?

Я хочу вызвать некоторые сценарии во время выполнения из моего приложения Java. Но я хочу скрыть внутреннюю модель от пользователя. Итак, моя идея написать DSL с использованием Xtext. И добавьте возможность пользователю писать скрипт в этом DSL, а затем выполнять его в приложении.

Является ли это возможным?

да, вы можете интерпретировать базовые модели xtext. почему именно у вас есть сомнения?

Christian Dietrich 16.10.2018 19:32

Я только начинаю узнавать о XText. Я понимаю, что моя задача выполнима. Но документацию больше всего нужно запускать в приложении XText. И я не могу найти документацию о том, как решить мою проблему.

Alexey Vashchenkov 16.10.2018 22:23

Не могли бы вы подробнее рассказать о том, что вам делать для выполнения dsl?

Christian Dietrich 17.10.2018 06:46

похоже, что кое-что потеряно из-за вашего комментария

Christian Dietrich 17.10.2018 09:34

У меня есть бизнес-модель. Например, class User{ Long id String name String tag Address homeAddress } и Address{ String city String street String house }. Я хочу получить возможность для Клиента изменять только поле "User.tag" в зависимости от homeAddress. При первом вызове оценивается только какое-то значение в скрипте. Чтобы установить его в теге в Java-коде, я хочу определить модель DSL, подобную этой entity DSLUser { ...} entity DSLAddress{ ... } . Я хочу, чтобы клиент мог написать такой код: if (user.adress.hause =='5') return 'XX'. И мог бы выполнить этот скрипт и оценить результат.

Alexey Vashchenkov 17.10.2018 09:54

Поэтому вам нужно будет написать интерпретатор для вашего dsl

Christian Dietrich 17.10.2018 09:56

Да, понял, но документации не нашел :(

Alexey Vashchenkov 17.10.2018 09:59
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
7
128
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

По этому поводу нет общего руководства. Это сильно зависит от ваших правил. В вашей среде и т. д.

вот упрощенный пример

grammar org.xtext.example.mydsl.MyDsl with org.eclipse.xtext.xbase.Xbase

generate myDsl "http://www.xtext.org/example/mydsl/MyDsl"

Model:
    "model" name=ID "{"
        expressions+=NamedExpression*
    "}"
;

NamedExpression:
    name=ID " = " body=XExpression
;

вывод

/*
 * generated by Xtext 2.16.0-SNAPSHOT
 */
package org.xtext.example.mydsl.jvmmodel

import com.google.inject.Inject
import org.eclipse.xtext.xbase.jvmmodel.AbstractModelInferrer
import org.eclipse.xtext.xbase.jvmmodel.IJvmDeclaredTypeAcceptor
import org.eclipse.xtext.xbase.jvmmodel.JvmTypesBuilder
import org.xtext.example.mydsl.myDsl.Model

/**
 * <p>Infers a JVM model from the source model.</p> 
 *
 * <p>The JVM model should contain all elements that would appear in the Java code 
 * which is generated from the source model. Other models link against the JVM model rather than the source model.</p>     
 */
class MyDslJvmModelInferrer extends AbstractModelInferrer {

    /**
     * convenience API to build and initialize JVM types and their members.
     */
    @Inject extension JvmTypesBuilder

    /**
     * The dispatch method {@code infer} is called for each instance of the
     * given element's type that is contained in a resource.
     * 
     * @param element
     *            the model to create one or more
     *            {@link org.eclipse.xtext.common.types.JvmDeclaredType declared
     *            types} from.
     * @param acceptor
     *            each created
     *            {@link org.eclipse.xtext.common.types.JvmDeclaredType type}
     *            without a container should be passed to the acceptor in order
     *            get attached to the current resource. The acceptor's
     *            {@link IJvmDeclaredTypeAcceptor#accept(org.eclipse.xtext.common.types.JvmDeclaredType)
     *            accept(..)} method takes the constructed empty type for the
     *            pre-indexing phase. This one is further initialized in the
     *            indexing phase using the lambda you pass as the last argument.
     * @param isPreIndexingPhase
     *            whether the method is called in a pre-indexing phase, i.e.
     *            when the global index is not yet fully updated. You must not
     *            rely on linking using the index if isPreIndexingPhase is
     *            <code>true</code>.
     */
    def dispatch void infer(Model element, IJvmDeclaredTypeAcceptor acceptor, boolean isPreIndexingPhase) {
        // Here you explain how your model is mapped to Java elements, by writing the actual translation code.

        // An implementation for the initial hello world example could look like this:
        acceptor.accept(element.toClass("my.company.greeting."+ element.name)) [
            for (x : element.expressions) {
                members += x.toMethod(x.name, inferredType) [
                    body = x.body
                ]
            }
        ]
    }
}

Вызов переводчика

package org.xtext.example.mydsl

import org.eclipse.emf.common.util.URI
import org.eclipse.emf.ecore.resource.ResourceSet
import org.eclipse.xtext.util.CancelIndicator
import org.eclipse.xtext.util.StringInputStream
import org.eclipse.xtext.xbase.interpreter.impl.DefaultEvaluationContext
import org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter
import org.xtext.example.mydsl.myDsl.Model

class Sample {

    def static void main(String[] args) {
        val userInput = '''
        model x {
            a = 1
            b = 1 + 2
            c = "Hello"
        }
        '''
        val injector = new MyDslStandaloneSetup().createInjectorAndDoEMFRegistration
        val resourceSet = injector.getInstance(ResourceSet)
        val resource = resourceSet.createResource(URI.createURI("dummy.mydsl"))
        resource.load(new StringInputStream(userInput), null)
        val model = resource.contents.head as Model
        val interpreter = injector.getInstance(XbaseInterpreter)
        for (g : model.expressions) {
            val ctx = new DefaultEvaluationContext
            val result = interpreter.evaluate(g.body, ctx, CancelIndicator.NullImpl)
            println(result.result)
        }
    }

}

возможно, вам придется настроить интерпретатор и дополнительно добавить что-то в контекст, чтобы он работал с вашим кодом.

Спасибо! Это круто?

Alexey Vashchenkov 17.10.2018 10:33

Это похоже на отличный код. class Sample { def static void main(String[] args) {...} }

Alexey Vashchenkov 17.10.2018 10:44

Если это не круто, поэтому я не могу понять, как я могу вызвать скрипт из кода Java, а не из Xtend

Alexey Vashchenkov 17.10.2018 10:49

Просто используйте чистую java вместо xtend

Christian Dietrich 17.10.2018 10:58

Другие вопросы по теме