Package org.openhab.model.script.internal.engine

Source Code of org.openhab.model.script.internal.engine.ScriptEngineImpl

/**
* Copyright (c) 2010-2014, openHAB.org and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.model.script.internal.engine;

import static com.google.common.collect.Iterables.filter;

import java.io.IOException;
import java.util.List;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtext.diagnostics.Severity;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.resource.XtextResourceSet;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.util.StringInputStream;
import org.eclipse.xtext.validation.CheckMode;
import org.eclipse.xtext.validation.IResourceValidator;
import org.eclipse.xtext.validation.Issue;
import org.eclipse.xtext.xbase.XExpression;
import org.openhab.core.scriptengine.Script;
import org.openhab.core.scriptengine.ScriptEngine;
import org.openhab.core.scriptengine.ScriptExecutionException;
import org.openhab.core.scriptengine.ScriptParsingException;
import org.openhab.model.script.ScriptStandaloneSetup;

import com.google.common.base.Predicate;
import com.google.inject.Injector;

/**
* This is the implementation of a {@link ScriptEngine} which is made available as an OSGi service.
*
* @author Kai Kreuzer
* @since 0.9.0
*
*/
@SuppressWarnings("restriction")
public class ScriptEngineImpl implements ScriptEngine {

  protected Injector guiceInjector;
  protected XtextResourceSet resourceSet;

  public ScriptEngineImpl() {}
 
  public void activate() {
    this.guiceInjector = new ScriptStandaloneSetup().createInjectorAndDoEMFRegistration();
    this.resourceSet = guiceInjector.getInstance(XtextResourceSet.class);
    resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
  }
 
  public void deactivate() {
    this.guiceInjector = null;
    this.resourceSet = null;
  }
   
  /**
   * {@inheritDoc}
   */
  public Script newScriptFromString(String scriptAsString)
      throws ScriptParsingException {
    return newScriptFromXExpression(parseScriptIntoXTextEObject(scriptAsString));
  }

  /**
   * {@inheritDoc}
   */
  public Script newScriptFromXExpression(XExpression expression) {
    ScriptImpl script = guiceInjector.getInstance(ScriptImpl.class);
    script.setXExpression(expression);
    return script;
  }

  /**
   * {@inheritDoc}
   */
  public Object executeScript(String scriptAsString)
      throws ScriptParsingException, ScriptExecutionException {
    return newScriptFromString(scriptAsString).execute();
  }

  private XExpression parseScriptIntoXTextEObject(String scriptAsString) throws ScriptParsingException {
    Resource resource = resourceSet.createResource(computeUnusedUri(resourceSet)); // IS-A XtextResource
    try {
      resource.load(new StringInputStream(scriptAsString), resourceSet.getLoadOptions());
    } catch (IOException e) {
      throw new ScriptParsingException("Unexpected IOException; from close() of a String-based ByteArrayInputStream, no real I/O; how is that possible???", scriptAsString, e);
    }
   
    List<Diagnostic> errors = resource.getErrors();
    if (errors.size() != 0) {
      throw new ScriptParsingException("Failed to parse expression (due to managed SyntaxError/s)", scriptAsString).addDiagnosticErrors(errors);
    }
   
    EList<EObject> contents = resource.getContents();

    if (!contents.isEmpty()) {
      Iterable<Issue> validationErrors = getValidationErrors(contents.get(0));
      if(!validationErrors.iterator().hasNext()) {
        return (XExpression) contents.get(0);
      } else {
        throw new ScriptParsingException("Failed to parse expression (due to managed ValidationError/s)", scriptAsString).addValidationIssues(validationErrors);
      }
    } else {
      return null;
    }
  }

  protected URI computeUnusedUri(ResourceSet resourceSet) {
    String name = "__synthetic";
    final int MAX_TRIES=1000;
    for(int i=0; i<MAX_TRIES; i++) {
      // NOTE: The "filename extension" (".script") must match the file.extensions in the *.mwe2
      URI syntheticUri = URI.createURI(name+Math.random()+ "." + Script.SCRIPT_FILEEXT);
      if (resourceSet.getResource(syntheticUri, false)==null)
        return syntheticUri;
    }
    throw new IllegalStateException();
  }

  protected List<Issue> validate(EObject model) {
    IResourceValidator validator = ((XtextResource) model.eResource()).getResourceServiceProvider().getResourceValidator();
    return validator.validate(model.eResource(), CheckMode.ALL, CancelIndicator.NullImpl);
  }
 
  protected Iterable<Issue> getValidationErrors(final EObject model) {
    final List<Issue> validate = validate(model);
    Iterable<Issue> issues = filter(validate, new Predicate<Issue>() {
      public boolean apply(Issue input) {
        return Severity.ERROR == input.getSeverity();
      }
    });
    return issues;
  }

}
TOP

Related Classes of org.openhab.model.script.internal.engine.ScriptEngineImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.