All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.plasma.runtime.ProfileVersionFinder Maven / Gradle / Ivy

/**
 * Copyright 2017 TerraMeta Software, Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.plasma.runtime;

import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;

import javanet.staxutils.events.EventAllocator;
import javanet.staxutils.events.NamespaceEvent;

import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLResolver;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.util.XMLEventAllocator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.plasma.profile.ProfileConfig;
import org.plasma.profile.ProfileURN;
import org.plasma.profile.adapter.ProfileArtifactAdapter;

public class ProfileVersionFinder {
  private static Log log = LogFactory.getLog(ProfileVersionFinder.class);

  public static final String ELEM_XMI = "XMI";
  public static final String ATTR_OPF_VERSION = "";

  private XMLEventAllocator allocator = null;
  private XMLInputFactory factory;
  private String currentNamespaceUri = null;
  private boolean abort = false;

  private ProfileArtifactAdapter result;

  public ProfileArtifactAdapter getVersion(String artifactURN, InputStream stream) {
    try {
      setup();
      read(stream);
    } catch (XMLStreamException e) {
      throw new ConfigurationException(e);
    } finally {
      try {
        stream.close();
      } catch (IOException e) {
      }
    }
    if (this.result == null) {
      StringBuilder buf = new StringBuilder();
      ProfileURN[] v = ProfileURN.values();
      for (int i = 0; i < v.length; i++) {
        if (i > 0)
          buf.append(", ");
        buf.append(v[i].value());
      }
      throw new ProfileVersionDetectionException(
          "no profile version detected for artifact '"
              + artifactURN
              + "' - all UML artifacts are required to be annotated with one of the following versions "
              + "of the PlasmaSDO UML Profile [" + buf.toString() + "]");
    }

    return result;
  }

  private void read(InputStream stream) throws XMLStreamException {
    XMLStreamReader streamReader = factory.createXMLStreamReader(stream);
    int eventType;

    while (streamReader.hasNext() && !abort) {
      eventType = streamReader.next();
      XMLEvent event = allocateXMLEvent(streamReader);
      // logEventInfo(event);
      switch (eventType) {
      case XMLEvent.START_ELEMENT:
        StartElement start = event.asStartElement();
        QName name = start.getName();
        String uri = name.getNamespaceURI();
        if (uri != null && uri.trim().length() > 0)
          this.currentNamespaceUri = uri.trim();
        if (isRoot(name)) {
          Iterator iter = start.getNamespaces();
          while (iter.hasNext()) {
            NamespaceEvent namespaceEvent = iter.next();
            String value = namespaceEvent.getValue();
            ProfileArtifactAdapter version = findVersion(value);
            if (version != null) {
              this.result = version;
              this.abort = true;
              break;
            }
          }
        }
        break;
      case XMLEvent.END_ELEMENT:
        name = event.asEndElement().getName();
        uri = name.getNamespaceURI();
        break;
      case XMLEvent.CHARACTERS:
        String data = event.asCharacters().getData();
        if (data == null || data.trim().length() == 0) {
          break; // ignore newlines and such
        }
        data = data.trim();
        if (data.contains(">")) {
          Location loc = event.getLocation();
          String msg = "line:col[" + loc.getLineNumber() + ":" + loc.getColumnNumber() + "]";
          msg += " - document is not well-formed";
          throw new XMLStreamException(msg);
        }
        break;
      default:
      }
    }
  }

  private boolean isRoot(QName name) {
    if (ELEM_XMI.equals(name.getLocalPart())) {
      return true;
    }
    return false;
  }

  private ProfileArtifactAdapter findVersion(String value) {
    return ProfileConfig.getInstance().findArtifactByUri(value);
  }

  private void setup() {
    this.factory = XMLInputFactory.newInstance();
    factory.setXMLResolver(new XMLResolver() {
      public Object resolveEntity(String publicID, String systemID, String baseURI, String namespace)
          throws XMLStreamException {
        log.info("resolve: " + publicID + ":" + systemID + ":" + baseURI + ":" + namespace);
        return null;
      }
    });
    factory.setEventAllocator(new EventAllocator());
    factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, Boolean.FALSE);
    factory.setProperty(XMLInputFactory.IS_VALIDATING, Boolean.FALSE);
    factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
    factory.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);

    // set the IS_COALESCING property to true , if application desires to
    // get whole text data as one event.
    // factory.setProperty(XMLInputFactory.IS_COALESCING , Boolean.TRUE);

    allocator = factory.getEventAllocator();
  }

  /**
   * Get the immutable XMLEvent from given XMLStreamReader using
   * XMLEventAllocator
   */
  private XMLEvent allocateXMLEvent(XMLStreamReader reader) throws XMLStreamException {
    return this.allocator.allocate(reader);
  }

  private void logEventInfo(XMLEvent event) {
    if (log.isDebugEnabled()) {
      Location loc = event.getLocation();
      String msg = getEventTypeString(event.getEventType());
      msg += " line:col[" + loc.getLineNumber() + ":" + loc.getColumnNumber() + "] - ";
      msg += event.toString();
      log.debug(msg);
    }
  }

  /**
   * Returns the String representation of the given integer constant.
   *
   * @param eventType
   *          Type of event.
   * @return String representation of the event
   */
  public final static String getEventTypeString(int eventType) {
    switch (eventType) {
    case XMLEvent.START_ELEMENT:
      return "START_ELEMENT";
    case XMLEvent.END_ELEMENT:
      return "END_ELEMENT";
    case XMLEvent.PROCESSING_INSTRUCTION:
      return "PROCESSING_INSTRUCTION";
    case XMLEvent.CHARACTERS:
      return "CHARACTERS";
    case XMLEvent.COMMENT:
      return "COMMENT";
    case XMLEvent.START_DOCUMENT:
      return "START_DOCUMENT";
    case XMLEvent.END_DOCUMENT:
      return "END_DOCUMENT";
    case XMLEvent.ENTITY_REFERENCE:
      return "ENTITY_REFERENCE";
    case XMLEvent.ATTRIBUTE:
      return "ATTRIBUTE";
    case XMLEvent.DTD:
      return "DTD";
    case XMLEvent.CDATA:
      return "CDATA";
    case XMLEvent.SPACE:
      return "SPACE";
    }
    return "UNKNOWN_EVENT_TYPE , " + eventType;
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy