001package org.dcm4che3.conf.api.upgrade; 002 003import org.dcm4che3.conf.core.api.ConfigurationException; 004import org.slf4j.Logger; 005import org.slf4j.LoggerFactory; 006 007import java.lang.reflect.Method; 008import java.util.Map; 009import java.util.TreeMap; 010 011public class VersionDrivenUpgradeScript implements UpgradeScript { 012 013 private static Logger log = LoggerFactory.getLogger(VersionDrivenUpgradeScript.class); 014 015 016 private UpgradeContext upgradeContext; 017 018 protected UpgradeContext getUpgradeContext() { 019 return upgradeContext; 020 } 021 022 @Override 023 public void upgrade(UpgradeContext upgradeContext) throws ConfigurationException { 024 025 init(upgradeContext); 026 027 if (firstTimeRun()) { 028 Method firstRunMethod = getFirstRunMethod(); 029 log.info("Running upgrade script " + this.getClass().getName() + " for the first time - invoking method " + firstRunMethod.getName()); 030 invokeMethod(firstRunMethod); 031 032 } else 033 runFixUps(MMPVersion.fromStringVersion(getUpgradeContext().getUpgradeScriptMetadata().getLastVersionExecuted())); 034 } 035 036 public void init(UpgradeContext upgradeContext) { 037 this.upgradeContext = upgradeContext; 038 } 039 040 private void runFixUps(MMPVersion lastExVer) { 041 TreeMap<MMPVersion, Method> methods = getFixUpMethods(lastExVer); 042 043 for (Map.Entry<MMPVersion, Method> methodEntry : methods.entrySet()) { 044 log.info("[" + this.getClass().getName() + "] Invoking fix-up method " + methodEntry.getValue().getName() + " (fixUpTo " + methodEntry.getKey() + ")"); 045 invokeMethod(methodEntry.getValue()); 046 } 047 } 048 049 050 public Method getFirstRunMethod() { 051 for (Method method : this.getClass().getDeclaredMethods()) { 052 if (method.getAnnotation(UpgradeGoalFromScratch.class) != null) { 053 return method; 054 } 055 } 056 throw new RuntimeException("Method annotated with 'UpgradeGoalFromScratch' not found in " + this.getClass().getName()); 057 } 058 059 public TreeMap<MMPVersion, Method> getFixUpMethods(MMPVersion lastExVer) { 060 // Fix-ups are ran ordered according to @FixUpTo's values thus TreeMap 061 TreeMap<MMPVersion, Method> methods = new TreeMap<MMPVersion, Method>(); 062 063 for (Method method : this.getClass().getDeclaredMethods()) { 064 FixUpTo annotation = method.getAnnotation(FixUpTo.class); 065 066 if (annotation != null) { 067 068 MMPVersion mmpVersion = MMPVersion.fromFixUpToAnno(annotation); 069 070 if (mmpVersion.compareTo(lastExVer) <= 0) 071 methods.put(mmpVersion, method); 072 } 073 } 074 return methods; 075 } 076 077 private void invokeMethod(Method m) { 078 try { 079 m.invoke(this); 080 } catch (Exception e) { 081 throw new RuntimeException("Cannot invoke a method of an upgrade script " + this.getClass().getName() + " . " + m.getName(), e); 082 } 083 } 084 085 private boolean firstTimeRun() { 086 try { 087 return getUpgradeContext().getUpgradeScriptMetadata().getLastVersionExecuted().equals(NO_VERSION); 088 } catch (NullPointerException e) { 089 return true; 090 } 091 } 092 093}