001package io.ebeaninternal.extraddl.model;
002
003import io.ebean.annotation.Platform;
004import org.slf4j.Logger;
005import org.slf4j.LoggerFactory;
006
007import javax.xml.bind.JAXBContext;
008import javax.xml.bind.JAXBException;
009import javax.xml.bind.Unmarshaller;
010import java.io.IOException;
011import java.io.InputStream;
012
013import static io.ebeaninternal.api.PlatformMatch.matchPlatform;
014
015/**
016 * Read ExtraDdl from an XML document.
017 */
018public class ExtraDdlXmlReader {
019
020  private static final Logger logger = LoggerFactory.getLogger(ExtraDdlXmlReader.class);
021
022  /**
023   * Return the combined extra DDL that should be run given the platform name.
024   */
025  public static String buildExtra(Platform platform, boolean drops) {
026    return buildExtra(platform, drops, read("/extra-ddl.xml"));
027  }
028
029  /**
030   * Return any extra DDL for supporting partitioning given the database platform.
031   */
032  public static String buildPartitioning(Platform platform) {
033    return buildExtra(platform, false, readBuiltinTablePartitioning());
034  }
035
036  private static String buildExtra(Platform platform, boolean drops, ExtraDdl read) {
037
038    if (read == null) {
039      return null;
040    }
041
042    StringBuilder sb = new StringBuilder(300);
043    for (DdlScript script : read.getDdlScript()) {
044      if (script.isDrop() == drops && matchPlatform(platform, script.getPlatforms())) {
045        logger.debug("include script {}", script.getName());
046        String value = script.getValue();
047        sb.append(value);
048        if (value.lastIndexOf(';') == -1) {
049          // add statement terminator as we didn't find one
050          sb.append(";");
051        }
052        sb.append("\n");
053      }
054    }
055    return sb.toString();
056  }
057
058  /**
059   * Read the builtin extra ddl. (Stored procedures, tvp types etc)
060   */
061  public static ExtraDdl readBuiltin() {
062    return read("/io/ebeaninternal/dbmigration/builtin-extra-ddl.xml");
063  }
064
065  /**
066   * Read the builtin extra ddl to support table partitioning.
067   */
068  public static ExtraDdl readBuiltinTablePartitioning() {
069    return read("/io/ebeaninternal/dbmigration/builtin-extra-ddl-partitioning.xml");
070  }
071
072  /**
073   * Read the extra ddl.
074   */
075  public static ExtraDdl read() {
076    return read("/extra-ddl.xml");
077  }
078
079  /**
080   * Read and return a ExtraDdl from an xml document at the given resource path.
081   */
082  private static ExtraDdl read(String resourcePath) {
083
084    try (InputStream is = ExtraDdlXmlReader.class.getResourceAsStream(resourcePath)) {
085      if (is == null) {
086        // we expect this and check for null
087        return null;
088      }
089      return read(is);
090    } catch (IOException e) {
091      throw new IllegalStateException("Error on auto close of " + resourcePath, e);
092    }
093  }
094
095  /**
096   * Read and return a ExtraDdl from an xml document.
097   */
098  public static ExtraDdl read(InputStream is) {
099
100    try {
101      JAXBContext jaxbContext = JAXBContext.newInstance(ExtraDdl.class);
102      Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
103      return (ExtraDdl) unmarshaller.unmarshal(is);
104
105    } catch (JAXBException e) {
106      throw new RuntimeException(e);
107    }
108  }
109}