Initial pool
This commit is contained in:
		
							
								
								
									
										21
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										21
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -20,7 +20,20 @@
 | 
			
		||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
 | 
			
		||||
hs_err_pid*
 | 
			
		||||
.gradle/4.3.1/
 | 
			
		||||
.idea/TabooLib.iml
 | 
			
		||||
.idea/misc.xml
 | 
			
		||||
.idea/modules.xml
 | 
			
		||||
.idea/workspace.xml
 | 
			
		||||
.idea
 | 
			
		||||
target/TabooLib-3.832-shaded.jar
 | 
			
		||||
target/TabooLib-3.832.jar
 | 
			
		||||
target/classes/JavaShells/
 | 
			
		||||
target/classes/Language/
 | 
			
		||||
target/classes/Language2/
 | 
			
		||||
target/classes/TLM/
 | 
			
		||||
target/classes/config.yml
 | 
			
		||||
target/classes/internalLang.yml
 | 
			
		||||
target/classes/items.yml
 | 
			
		||||
target/classes/lang/
 | 
			
		||||
target/classes/module.yml
 | 
			
		||||
target/classes/plugin.yml
 | 
			
		||||
target/generated-sources/
 | 
			
		||||
target/maven-archiver/
 | 
			
		||||
target/maven-status/
 | 
			
		||||
target/original-TabooLib-3.832.jar
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								.idea/inspectionProfiles/Project_Default.xml
									
									
									
										generated
									
									
									
								
							@@ -10,6 +10,7 @@
 | 
			
		||||
    <inspection_tool class="AlibabaClassNamingShouldBeCamel" enabled="false" level="MAJOR" enabled_by_default="false" />
 | 
			
		||||
    <inspection_tool class="AlibabaConstantFieldShouldBeUpperCase" enabled="false" level="CRITICAL" enabled_by_default="false" />
 | 
			
		||||
    <inspection_tool class="AlibabaEnumConstantsMustHaveComment" enabled="false" level="CRITICAL" enabled_by_default="false" />
 | 
			
		||||
    <inspection_tool class="AlibabaThreadPoolCreation" enabled="false" level="BLOCKER" enabled_by_default="false" />
 | 
			
		||||
    <inspection_tool class="AlibabaUndefineMagicConstant" enabled="false" level="MAJOR" enabled_by_default="false" />
 | 
			
		||||
    <inspection_tool class="JavaDoc" enabled="true" level="WARNING" enabled_by_default="true">
 | 
			
		||||
      <option name="TOP_LEVEL_CLASS_OPTIONS">
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								.idea/libraries/Maven__com_h2database_h2_1_4_197.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.idea/libraries/Maven__com_h2database_h2_1_4_197.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
<component name="libraryTable">
 | 
			
		||||
  <library name="Maven: com.h2database:h2:1.4.197">
 | 
			
		||||
    <CLASSES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/com/h2database/h2/1.4.197/h2-1.4.197.jar!/" />
 | 
			
		||||
    </CLASSES>
 | 
			
		||||
    <JAVADOC>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/com/h2database/h2/1.4.197/h2-1.4.197-javadoc.jar!/" />
 | 
			
		||||
    </JAVADOC>
 | 
			
		||||
    <SOURCES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/com/h2database/h2/1.4.197/h2-1.4.197-sources.jar!/" />
 | 
			
		||||
    </SOURCES>
 | 
			
		||||
  </library>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										13
									
								
								.idea/libraries/Maven__javax_servlet_servlet_api_2_5.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.idea/libraries/Maven__javax_servlet_servlet_api_2_5.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
<component name="libraryTable">
 | 
			
		||||
  <library name="Maven: javax.servlet:servlet-api:2.5">
 | 
			
		||||
    <CLASSES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/javax/servlet/servlet-api/2.5/servlet-api-2.5.jar!/" />
 | 
			
		||||
    </CLASSES>
 | 
			
		||||
    <JAVADOC>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/javax/servlet/servlet-api/2.5/servlet-api-2.5-javadoc.jar!/" />
 | 
			
		||||
    </JAVADOC>
 | 
			
		||||
    <SOURCES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/javax/servlet/servlet-api/2.5/servlet-api-2.5-sources.jar!/" />
 | 
			
		||||
    </SOURCES>
 | 
			
		||||
  </library>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										13
									
								
								.idea/libraries/Maven__org_codehaus_jackson_jackson_core_asl_1_9_13.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.idea/libraries/Maven__org_codehaus_jackson_jackson_core_asl_1_9_13.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
<component name="libraryTable">
 | 
			
		||||
  <library name="Maven: org.codehaus.jackson:jackson-core-asl:1.9.13">
 | 
			
		||||
    <CLASSES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/codehaus/jackson/jackson-core-asl/1.9.13/jackson-core-asl-1.9.13.jar!/" />
 | 
			
		||||
    </CLASSES>
 | 
			
		||||
    <JAVADOC>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/codehaus/jackson/jackson-core-asl/1.9.13/jackson-core-asl-1.9.13-javadoc.jar!/" />
 | 
			
		||||
    </JAVADOC>
 | 
			
		||||
    <SOURCES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/codehaus/jackson/jackson-core-asl/1.9.13/jackson-core-asl-1.9.13-sources.jar!/" />
 | 
			
		||||
    </SOURCES>
 | 
			
		||||
  </library>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										13
									
								
								.idea/libraries/Maven__org_codehaus_jackson_jackson_mapper_asl_1_9_13.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.idea/libraries/Maven__org_codehaus_jackson_jackson_mapper_asl_1_9_13.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
<component name="libraryTable">
 | 
			
		||||
  <library name="Maven: org.codehaus.jackson:jackson-mapper-asl:1.9.13">
 | 
			
		||||
    <CLASSES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/codehaus/jackson/jackson-mapper-asl/1.9.13/jackson-mapper-asl-1.9.13.jar!/" />
 | 
			
		||||
    </CLASSES>
 | 
			
		||||
    <JAVADOC>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/codehaus/jackson/jackson-mapper-asl/1.9.13/jackson-mapper-asl-1.9.13-javadoc.jar!/" />
 | 
			
		||||
    </JAVADOC>
 | 
			
		||||
    <SOURCES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/codehaus/jackson/jackson-mapper-asl/1.9.13/jackson-mapper-asl-1.9.13-sources.jar!/" />
 | 
			
		||||
    </SOURCES>
 | 
			
		||||
  </library>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										13
									
								
								.idea/libraries/Maven__org_javalite_activejdbc_2_0.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.idea/libraries/Maven__org_javalite_activejdbc_2_0.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
<component name="libraryTable">
 | 
			
		||||
  <library name="Maven: org.javalite:activejdbc:2.0">
 | 
			
		||||
    <CLASSES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/javalite/activejdbc/2.0/activejdbc-2.0.jar!/" />
 | 
			
		||||
    </CLASSES>
 | 
			
		||||
    <JAVADOC>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/javalite/activejdbc/2.0/activejdbc-2.0-javadoc.jar!/" />
 | 
			
		||||
    </JAVADOC>
 | 
			
		||||
    <SOURCES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/javalite/activejdbc/2.0/activejdbc-2.0-sources.jar!/" />
 | 
			
		||||
    </SOURCES>
 | 
			
		||||
  </library>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										13
									
								
								.idea/libraries/Maven__org_javalite_app_config_2_0.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.idea/libraries/Maven__org_javalite_app_config_2_0.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
<component name="libraryTable">
 | 
			
		||||
  <library name="Maven: org.javalite:app-config:2.0">
 | 
			
		||||
    <CLASSES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/javalite/app-config/2.0/app-config-2.0.jar!/" />
 | 
			
		||||
    </CLASSES>
 | 
			
		||||
    <JAVADOC>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/javalite/app-config/2.0/app-config-2.0-javadoc.jar!/" />
 | 
			
		||||
    </JAVADOC>
 | 
			
		||||
    <SOURCES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/javalite/app-config/2.0/app-config-2.0-sources.jar!/" />
 | 
			
		||||
    </SOURCES>
 | 
			
		||||
  </library>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										13
									
								
								.idea/libraries/Maven__org_javalite_javalite_common_2_0.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.idea/libraries/Maven__org_javalite_javalite_common_2_0.xml
									
									
									
										generated
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
<component name="libraryTable">
 | 
			
		||||
  <library name="Maven: org.javalite:javalite-common:2.0">
 | 
			
		||||
    <CLASSES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/javalite/javalite-common/2.0/javalite-common-2.0.jar!/" />
 | 
			
		||||
    </CLASSES>
 | 
			
		||||
    <JAVADOC>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/javalite/javalite-common/2.0/javalite-common-2.0-javadoc.jar!/" />
 | 
			
		||||
    </JAVADOC>
 | 
			
		||||
    <SOURCES>
 | 
			
		||||
      <root url="jar://$MAVEN_REPOSITORY$/org/javalite/javalite-common/2.0/javalite-common-2.0-sources.jar!/" />
 | 
			
		||||
    </SOURCES>
 | 
			
		||||
  </library>
 | 
			
		||||
</component>
 | 
			
		||||
							
								
								
									
										16
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								pom.xml
									
									
									
									
									
								
							@@ -67,6 +67,22 @@
 | 
			
		||||
            <artifactId>HikariCP</artifactId>
 | 
			
		||||
            <version>3.1.0</version>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.javalite</groupId>
 | 
			
		||||
            <artifactId>activejdbc</artifactId>
 | 
			
		||||
            <version>2.0</version>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>javax.servlet</groupId>
 | 
			
		||||
            <artifactId>servlet-api</artifactId>
 | 
			
		||||
            <version>2.5</version>
 | 
			
		||||
            <scope>provided</scope>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.h2database</groupId>
 | 
			
		||||
            <artifactId>h2</artifactId>
 | 
			
		||||
            <version>1.4.197</version>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.ilummc.eagletdl</groupId>
 | 
			
		||||
            <artifactId>EagletCore</artifactId>
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package com.ilummc.tlib;
 | 
			
		||||
import com.ilummc.tlib.annotations.Dependency;
 | 
			
		||||
import com.ilummc.tlib.compat.PlaceholderHook;
 | 
			
		||||
import com.ilummc.tlib.config.TLibConfig;
 | 
			
		||||
import com.ilummc.tlib.db.Pool;
 | 
			
		||||
import com.ilummc.tlib.filter.TLoggerFilter;
 | 
			
		||||
import com.ilummc.tlib.inject.TConfigWatcher;
 | 
			
		||||
import com.ilummc.tlib.inject.TDependencyInjector;
 | 
			
		||||
@@ -25,6 +26,16 @@ import java.nio.charset.Charset;
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.ow2.asm:asm:6.1.1")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "com.zaxxer:HikariCP:3.1.0")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.slf4j:slf4j-api:1.7.25")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.javalite:activejdbc:2.0")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.javalite:javalite-common:2.0")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.javalite:app-config:2.0")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.codehaus.jackson:jackson-mapper-asl:1.9.13")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.codehaus.jackson:jackson-core-asl:1.9.13")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "jaxen:jaxen:1.1.6")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "dom4j:dom4j:1.6.1")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "xml-apis:xml-apis:1.0.b2")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "org.ehcache:ehcache:3.5.2")
 | 
			
		||||
@Dependency(type = Dependency.Type.LIBRARY, maven = "com.h2database:h2:1.4.197")
 | 
			
		||||
public class TLib {
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
@@ -34,7 +45,7 @@ public class TLib {
 | 
			
		||||
    private TLogger logger = new TLogger("§8[§3§lTabooLib§8][§r{1}§8] §f{2}", Main.getInst(), TLogger.FINE);
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private TLibConfig config;
 | 
			
		||||
    private TLibConfig config = new TLibConfig();
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private TConfigWatcher configWatcher = new TConfigWatcher();
 | 
			
		||||
@@ -66,9 +77,18 @@ public class TLib {
 | 
			
		||||
        PlaceholderHook.init();
 | 
			
		||||
        TLocaleLoader.load(Main.getInst(), false);
 | 
			
		||||
        TDependencyInjector.inject(Main.getInst(), tLib);
 | 
			
		||||
 | 
			
		||||
        // init database
 | 
			
		||||
        try {
 | 
			
		||||
            Pool.init();
 | 
			
		||||
        } catch (Throwable e) {
 | 
			
		||||
            e.printStackTrace();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void unload() {
 | 
			
		||||
        Pool.unload();
 | 
			
		||||
        tLib.getConfigWatcher().unregisterAll();
 | 
			
		||||
        TDependencyInjector.eject(Main.getInst(), tLib);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,10 @@
 | 
			
		||||
package com.ilummc.tlib.config;
 | 
			
		||||
 | 
			
		||||
import com.ilummc.tlib.annotations.Config;
 | 
			
		||||
import lombok.Getter;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @author sky
 | 
			
		||||
@@ -9,9 +13,28 @@ import com.ilummc.tlib.annotations.Config;
 | 
			
		||||
@Config(name = "tlib.yml", listenChanges = true, readOnly = false)
 | 
			
		||||
public class TLibConfig {
 | 
			
		||||
 | 
			
		||||
    private boolean enablePlaceholderHookByDefault = false;
 | 
			
		||||
    @Getter
 | 
			
		||||
    private String dataSourceClassName;
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private String jdbcUrl = "jdbc:h2:file:~/plugins/TabooLib/h2";
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private String driverClassName;
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private String username = "";
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private String password = "";
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private int maximumPoolSize = 4;
 | 
			
		||||
 | 
			
		||||
    @Getter
 | 
			
		||||
    private Map<String, Object> settings = new HashMap<String, Object>() {{
 | 
			
		||||
        put("cachePrepStmts", true);
 | 
			
		||||
        put("useServerPrepStmts", true);
 | 
			
		||||
    }};
 | 
			
		||||
 | 
			
		||||
    public boolean isEnablePlaceholderHookByDefault() {
 | 
			
		||||
        return enablePlaceholderHookByDefault;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										61
									
								
								src/main/java/com/ilummc/tlib/db/Pool.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/main/java/com/ilummc/tlib/db/Pool.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
package com.ilummc.tlib.db;
 | 
			
		||||
 | 
			
		||||
import com.ilummc.tlib.TLib;
 | 
			
		||||
import com.ilummc.tlib.resources.TLocale;
 | 
			
		||||
import org.javalite.activejdbc.Base;
 | 
			
		||||
 | 
			
		||||
import java.util.concurrent.LinkedBlockingQueue;
 | 
			
		||||
import java.util.concurrent.ThreadPoolExecutor;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
import java.util.concurrent.atomic.AtomicInteger;
 | 
			
		||||
 | 
			
		||||
public final class Pool extends ThreadPoolExecutor {
 | 
			
		||||
 | 
			
		||||
    private static final AtomicInteger number = new AtomicInteger(1);
 | 
			
		||||
 | 
			
		||||
    private static final Pool singleton = new Pool();
 | 
			
		||||
 | 
			
		||||
    private final TLibDataSource dataSource;
 | 
			
		||||
 | 
			
		||||
    private Pool() {
 | 
			
		||||
        super(TLib.getTLib().getConfig().getMaximumPoolSize(),
 | 
			
		||||
                TLib.getTLib().getConfig().getMaximumPoolSize(),
 | 
			
		||||
                0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
 | 
			
		||||
        try {
 | 
			
		||||
            dataSource = new TLibDataSource();
 | 
			
		||||
            this.setThreadFactory(r -> new Thread(() -> {
 | 
			
		||||
                Base.open(dataSource.getDataSource());
 | 
			
		||||
                r.run();
 | 
			
		||||
            }, "TabooLib-DbPool-" + number.getAndIncrement()));
 | 
			
		||||
            prestartAllCoreThreads();
 | 
			
		||||
            TLocale.sendToConsole("DATABASE.CONNECTION-ESTABLISHED", dataSource.getDataSource().getConnection().getMetaData().getDatabaseProductName(),
 | 
			
		||||
                    String.valueOf(TLib.getTLib().getConfig().getMaximumPoolSize()));
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            TLocale.sendToConsole("DATABASE.CONNECTION-ERROR", e.toString());
 | 
			
		||||
            throw new RuntimeException();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void run(Runnable runnable) {
 | 
			
		||||
        instance().execute(runnable);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void init() {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void unload() {
 | 
			
		||||
        instance().dataSource.disconnect();
 | 
			
		||||
        instance().shutdown();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Pool instance() {
 | 
			
		||||
        return singleton;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    protected void afterExecute(Runnable r, Throwable t) {
 | 
			
		||||
        if (t != null) Base.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										35
									
								
								src/main/java/com/ilummc/tlib/db/TLibDataSource.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/main/java/com/ilummc/tlib/db/TLibDataSource.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
package com.ilummc.tlib.db;
 | 
			
		||||
 | 
			
		||||
import com.ilummc.tlib.TLib;
 | 
			
		||||
import com.zaxxer.hikari.HikariConfig;
 | 
			
		||||
import com.zaxxer.hikari.HikariDataSource;
 | 
			
		||||
import org.javalite.activejdbc.Base;
 | 
			
		||||
 | 
			
		||||
import javax.sql.DataSource;
 | 
			
		||||
import java.util.Properties;
 | 
			
		||||
 | 
			
		||||
public class TLibDataSource {
 | 
			
		||||
 | 
			
		||||
    private final HikariDataSource dataSource;
 | 
			
		||||
 | 
			
		||||
    TLibDataSource() {
 | 
			
		||||
        Properties properties = new Properties();
 | 
			
		||||
        properties.put("jdbcUrl", TLib.getTLib().getConfig().getJdbcUrl());
 | 
			
		||||
        properties.put("username", TLib.getTLib().getConfig().getUsername());
 | 
			
		||||
        properties.put("password", TLib.getTLib().getConfig().getPassword());
 | 
			
		||||
        properties.put("dataSourceClassName", TLib.getTLib().getConfig().getDataSourceClassName());
 | 
			
		||||
        properties.put("driverClassName", TLib.getTLib().getConfig().getDriverClassName());
 | 
			
		||||
        TLib.getTLib().getConfig().getSettings().forEach((k, v) -> properties.put("dataSource." + k, v));
 | 
			
		||||
        dataSource = new HikariDataSource(new HikariConfig(properties));
 | 
			
		||||
        Base.open(dataSource);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public DataSource getDataSource() {
 | 
			
		||||
        return dataSource;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void disconnect() {
 | 
			
		||||
        Base.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
package com.ilummc.tlib.inject;
 | 
			
		||||
 | 
			
		||||
import com.google.common.io.Files;
 | 
			
		||||
import com.google.gson.Gson;
 | 
			
		||||
import com.google.gson.GsonBuilder;
 | 
			
		||||
import com.ilummc.tlib.annotations.Config;
 | 
			
		||||
import com.ilummc.tlib.resources.TLocale;
 | 
			
		||||
import me.skymc.taboolib.fileutils.ConfigUtils;
 | 
			
		||||
@@ -14,6 +16,7 @@ import java.io.File;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.lang.reflect.Field;
 | 
			
		||||
import java.nio.charset.Charset;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
public class TConfigInjector {
 | 
			
		||||
@@ -55,7 +58,8 @@ public class TConfigInjector {
 | 
			
		||||
            File file = new File(plugin.getDataFolder(), config.name());
 | 
			
		||||
            if (!file.exists()) if (config.fromJar()) plugin.saveResource(config.name(), true);
 | 
			
		||||
            else saveConfig(plugin, clazz.newInstance());
 | 
			
		||||
            Object obj = unserialize(plugin, clazz);
 | 
			
		||||
            Gson gson = new GsonBuilder().disableHtmlEscaping().create();
 | 
			
		||||
            Object obj = gson.fromJson(gson.toJson(new Yaml().load(Files.toString(file, Charset.forName(config.charset())))), clazz);
 | 
			
		||||
            if (!config.readOnly()) saveConfig(plugin, obj);
 | 
			
		||||
            return obj;
 | 
			
		||||
        } catch (NullPointerException e) {
 | 
			
		||||
@@ -106,7 +110,7 @@ public class TConfigInjector {
 | 
			
		||||
        try {
 | 
			
		||||
            Config config = object.getClass().getAnnotation(Config.class);
 | 
			
		||||
            Validate.notNull(config);
 | 
			
		||||
            return ConfigUtils.objToConf(object).getValues(false);
 | 
			
		||||
            return ConfigUtils.objToMap(ConfigUtils.objToConf(object).getValues(false), config.excludeModifiers());
 | 
			
		||||
        } catch (NullPointerException e) {
 | 
			
		||||
            TLocale.Logger.warn("CONFIG.SAVE-FAIL-NO-ANNOTATION", plugin.toString(), object.getClass().getSimpleName());
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
@@ -118,16 +122,12 @@ public class TConfigInjector {
 | 
			
		||||
    public static void saveConfig(Plugin plugin, Object object) throws IOException, NullPointerException {
 | 
			
		||||
        Config config = object.getClass().getAnnotation(Config.class);
 | 
			
		||||
        Validate.notNull(config);
 | 
			
		||||
        Object obj = serialize(plugin, object);
 | 
			
		||||
        Validate.notNull(obj);
 | 
			
		||||
        Gson gson = new GsonBuilder().disableHtmlEscaping().create();
 | 
			
		||||
        Map map = gson.fromJson(gson.toJson(object), HashMap.class);
 | 
			
		||||
        YamlConfiguration configuration = (YamlConfiguration) ConfigUtils.mapToConf(map);
 | 
			
		||||
        File target = new File(plugin.getDataFolder(), config.name());
 | 
			
		||||
        if (!target.exists()) target.createNewFile();
 | 
			
		||||
        DumperOptions options = new DumperOptions();
 | 
			
		||||
        options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
 | 
			
		||||
        options.setAllowUnicode(false);
 | 
			
		||||
        Yaml yaml = new Yaml(options);
 | 
			
		||||
        String str = yaml.dump(obj);
 | 
			
		||||
        byte[] arr = str.getBytes(config.charset());
 | 
			
		||||
        byte[] arr = configuration.saveToString().getBytes(config.charset());
 | 
			
		||||
        Files.write(arr, target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,8 @@ public class TDependencyInjector {
 | 
			
		||||
        injectConfig(plugin, o);
 | 
			
		||||
        injectPluginInstance(plugin, o);
 | 
			
		||||
        TLocaleLoader.load(plugin, true);
 | 
			
		||||
        if (o != TLib.getTLib())
 | 
			
		||||
            injectDatabase(plugin, o);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static void injectOnEnable(Plugin plugin) {
 | 
			
		||||
@@ -55,6 +57,10 @@ public class TDependencyInjector {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void injectDatabase(Plugin plugin, Object o) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void injectConfig(Plugin plugin, Object o) {
 | 
			
		||||
        for (Field field : Ref.getDeclaredFields(o.getClass())) {
 | 
			
		||||
            try {
 | 
			
		||||
 
 | 
			
		||||
@@ -67,7 +67,7 @@ public class ConfigUtils {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static MemoryConfiguration mapToConf(Map<String, Object> map) {
 | 
			
		||||
        MemoryConfiguration configuration = new MemoryConfiguration();
 | 
			
		||||
        YamlConfiguration configuration = new YamlConfiguration();
 | 
			
		||||
        convertMapsToSections(map, configuration);
 | 
			
		||||
        return configuration;
 | 
			
		||||
    }
 | 
			
		||||
@@ -111,13 +111,24 @@ public class ConfigUtils {
 | 
			
		||||
        return objToMap(object, Modifier.TRANSIENT & Modifier.STATIC & Ref.ACC_SYNTHETIC);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @SuppressWarnings("unchecked")
 | 
			
		||||
    public static Map<String, Object> objToMap(Object object, int excludedModifiers) {
 | 
			
		||||
        Map<String, Object> map = Maps.newHashMap();
 | 
			
		||||
        if (object instanceof Map) {
 | 
			
		||||
            ((Map<String, ?>) object).forEach((k, v) -> map.put(k, objToMap(v, excludedModifiers)));
 | 
			
		||||
            return map;
 | 
			
		||||
        }
 | 
			
		||||
        if (object instanceof ConfigurationSection) {
 | 
			
		||||
            map.putAll(objToMap(((ConfigurationSection) object).getValues(false), excludedModifiers));
 | 
			
		||||
            return map;
 | 
			
		||||
        }
 | 
			
		||||
        for (Field field : Ref.getDeclaredFields(object.getClass(), excludedModifiers, false)) {
 | 
			
		||||
            try {
 | 
			
		||||
                if (!field.isAccessible()) field.setAccessible(true);
 | 
			
		||||
                Object obj = field.get(object);
 | 
			
		||||
                if (obj instanceof Property) obj = ((Property) obj).get();
 | 
			
		||||
                if (obj instanceof ConfigurationSection)
 | 
			
		||||
                    obj = objToMap(((ConfigurationSection) obj).getValues(false), excludedModifiers);
 | 
			
		||||
                map.put(Ref.getSerializedName(field), obj);
 | 
			
		||||
            } catch (IllegalAccessException ignored) {
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										509
									
								
								src/main/java/org/javalite/activejdbc/MetaModel.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										509
									
								
								src/main/java/org/javalite/activejdbc/MetaModel.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,509 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2009-2018 Igor Polevoy
 | 
			
		||||
 | 
			
		||||
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.javalite.activejdbc;
 | 
			
		||||
 | 
			
		||||
import org.bukkit.plugin.Plugin;
 | 
			
		||||
import org.javalite.activejdbc.annotations.*;
 | 
			
		||||
import org.javalite.activejdbc.associations.Many2ManyAssociation;
 | 
			
		||||
import org.javalite.activejdbc.associations.OneToManyAssociation;
 | 
			
		||||
import org.javalite.activejdbc.associations.OneToManyPolymorphicAssociation;
 | 
			
		||||
import org.javalite.activejdbc.dialects.Dialect;
 | 
			
		||||
import org.javalite.activejdbc.logging.LogFilter;
 | 
			
		||||
import org.javalite.activejdbc.logging.LogLevel;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
import java.io.Serializable;
 | 
			
		||||
import java.lang.reflect.Field;
 | 
			
		||||
import java.util.*;
 | 
			
		||||
import java.util.Map.Entry;
 | 
			
		||||
 | 
			
		||||
import static org.javalite.common.Inflector.singularize;
 | 
			
		||||
import static org.javalite.common.Inflector.tableize;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public class MetaModel implements Serializable {
 | 
			
		||||
    private static final Logger LOGGER = LoggerFactory.getLogger(MetaModel.class);
 | 
			
		||||
    private static final ThreadLocal<HashMap<Class, String>> shardingTableNamesTL = new ThreadLocal<>();
 | 
			
		||||
    private final List<Association> associations = new ArrayList<>();
 | 
			
		||||
    private final String idName;
 | 
			
		||||
    private final String[] compositeKeys;
 | 
			
		||||
    private final String tableName, dbType, dbName;
 | 
			
		||||
    private final Class<? extends Model> modelClass;
 | 
			
		||||
    private final boolean cached;
 | 
			
		||||
    private final String idGeneratorCode;
 | 
			
		||||
    private final String versionColumn;
 | 
			
		||||
    private Map<String, ColumnMetadata> columnMetadata;
 | 
			
		||||
    private Set<String> attributeNamesNoId;
 | 
			
		||||
    private String[] partitionIDs = null;
 | 
			
		||||
 | 
			
		||||
    protected MetaModel(String dbName, Class<? extends Model> modelClass, String dbType) {
 | 
			
		||||
        this.modelClass = modelClass;
 | 
			
		||||
        this.idName = findIdName(modelClass);
 | 
			
		||||
        this.compositeKeys = findCompositeKeys(modelClass);
 | 
			
		||||
        this.tableName = findTableName(modelClass);
 | 
			
		||||
        this.dbType = dbType;
 | 
			
		||||
        this.cached = isCached(modelClass);
 | 
			
		||||
        this.dbName = dbName;
 | 
			
		||||
        this.idGeneratorCode = findIdGeneratorCode(modelClass);
 | 
			
		||||
        this.versionColumn = findVersionColumn(modelClass);
 | 
			
		||||
        this.partitionIDs = findPartitionIDs();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static Map<Class, String> getTableNamesMap() {
 | 
			
		||||
        if (shardingTableNamesTL.get() == null)
 | 
			
		||||
            shardingTableNamesTL.set(new HashMap<>());
 | 
			
		||||
        return shardingTableNamesTL.get();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected static String getDbName(Class<? extends Model> modelClass) {
 | 
			
		||||
        DbName dbNameAnnotation = modelClass.getAnnotation(DbName.class);
 | 
			
		||||
        return dbNameAnnotation == null ? DB.DEFAULT_NAME : dbNameAnnotation.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String[] findPartitionIDs() {
 | 
			
		||||
        PartitionIDs partitionIDs = modelClass.getAnnotation(PartitionIDs.class);
 | 
			
		||||
        return partitionIDs != null ? partitionIDs.value() : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean hasPartitionIDs() {
 | 
			
		||||
        return partitionIDs != null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String[] getPartitionIDs() {
 | 
			
		||||
        return partitionIDs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * <p>
 | 
			
		||||
     * <strong>This feature is for sharding!</strong>
 | 
			
		||||
     * <br>
 | 
			
		||||
     * Do not use it to set table names <em>willy-nilly</em>!
 | 
			
		||||
     * </p>
 | 
			
		||||
     *
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Sets a table name for this model. The table name is attached to a current thread and will remain there
 | 
			
		||||
     * until it is set with a different value or cleared with {@link #clearShardTableName()} method.
 | 
			
		||||
     * Table name set with this method overrides a table name naturally mapped to this model.
 | 
			
		||||
     * </p>
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Method {@link #getTableName()} will return this value for all operations related to this table.
 | 
			
		||||
     * </p>
 | 
			
		||||
     *
 | 
			
		||||
     * @param tableName name of a table this model will read from current thread.
 | 
			
		||||
     */
 | 
			
		||||
    public void setShardTableName(String tableName) {
 | 
			
		||||
        getTableNamesMap().put(modelClass, tableName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Clears sharding name of table attached to current thread.
 | 
			
		||||
     * The name was supposedly attached by the {@link #setShardTableName(String)}
 | 
			
		||||
     * method. After execution of this class, the method {@link #getTableName()} will be
 | 
			
		||||
     * returning the value this {@link MetaModel} was initialized with during teh bootstrap phase.
 | 
			
		||||
     */
 | 
			
		||||
    public void clearShardTableName() {
 | 
			
		||||
        getTableNamesMap().remove(modelClass);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean isCached(Class<? extends Model> modelClass) {
 | 
			
		||||
        return null != modelClass.getAnnotation(Cached.class);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String findIdName(Class<? extends Model> modelClass) {
 | 
			
		||||
        IdName idNameAnnotation = modelClass.getAnnotation(IdName.class);
 | 
			
		||||
        return idNameAnnotation == null ? "id" : idNameAnnotation.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String[] findCompositeKeys(Class<? extends Model> modelClass) {
 | 
			
		||||
        CompositePK compositeKeysAnnotation = modelClass.getAnnotation(CompositePK.class);
 | 
			
		||||
        return compositeKeysAnnotation == null ? null : compositeKeysAnnotation.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Table name with plugin name prefix
 | 
			
		||||
     *
 | 
			
		||||
     * @return table name
 | 
			
		||||
     */
 | 
			
		||||
    private String findTableName(Class<? extends Model> modelClass) {
 | 
			
		||||
        Table tableAnnotation = modelClass.getAnnotation(Table.class);
 | 
			
		||||
        String prefix = "";
 | 
			
		||||
        try {
 | 
			
		||||
            Field field = modelClass.getClassLoader().getClass().getDeclaredField("plugin");
 | 
			
		||||
            field.setAccessible(true);
 | 
			
		||||
            Plugin plugin = (Plugin) field.get(modelClass.getClassLoader());
 | 
			
		||||
            prefix = tableize(plugin.getName()) + "_";
 | 
			
		||||
        } catch (Throwable ignored) {
 | 
			
		||||
        }
 | 
			
		||||
        return prefix + (tableAnnotation == null ? tableize(modelClass.getSimpleName()) : tableAnnotation.value());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String findIdGeneratorCode(Class<? extends Model> modelClass) {
 | 
			
		||||
        IdGenerator idGenerator = modelClass.getAnnotation(IdGenerator.class);
 | 
			
		||||
        return idGenerator == null ? null : idGenerator.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private String findVersionColumn(Class<? extends Model> modelClass) {
 | 
			
		||||
        VersionColumn vc = modelClass.getAnnotation(VersionColumn.class);
 | 
			
		||||
        return vc == null ? "record_version" : vc.value();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @return name of the column for optimistic locking record version
 | 
			
		||||
     */
 | 
			
		||||
    public String getVersionColumn() {
 | 
			
		||||
        return versionColumn;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getIdGeneratorCode() {
 | 
			
		||||
        return idGeneratorCode;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getDbName() {
 | 
			
		||||
        return dbName;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean cached() {
 | 
			
		||||
        return cached;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Class<? extends Model> getModelClass() {
 | 
			
		||||
        return modelClass;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns table name currently associated with this model.
 | 
			
		||||
     * Table name can be modified for sharding using {@link #setShardTableName(String)}
 | 
			
		||||
     *
 | 
			
		||||
     * @return table name currently associated with this model.
 | 
			
		||||
     */
 | 
			
		||||
    public String getTableName() {
 | 
			
		||||
        return getTableNamesMap().getOrDefault(modelClass, tableName);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected boolean tableExists() {
 | 
			
		||||
        return columnMetadata != null && columnMetadata.isEmpty();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Finds all attribute names except for id.
 | 
			
		||||
     *
 | 
			
		||||
     * @return all attribute names except for id.
 | 
			
		||||
     */
 | 
			
		||||
    public Set<String> getAttributeNamesSkipId() {
 | 
			
		||||
        if (attributeNamesNoId == null) {//no one cares about unfortunate multi-threading timing with 2 instances created
 | 
			
		||||
            //if someone does, use DCL with volatile
 | 
			
		||||
            Set<String> attributesNames = new CaseInsensitiveSet(getAttributeNames());
 | 
			
		||||
            attributesNames.remove(getIdName());
 | 
			
		||||
            attributeNamesNoId = attributesNames;
 | 
			
		||||
        }
 | 
			
		||||
        return attributeNamesNoId;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Convenience method. Calls {@link #getAttributeNamesSkipGenerated(boolean)} and passes <code>true</code> as argument.
 | 
			
		||||
     *
 | 
			
		||||
     * @return list of all attributes except id, created_at, updated_at and record_version.
 | 
			
		||||
     */
 | 
			
		||||
    public Set<String> getAttributeNamesSkipGenerated() {
 | 
			
		||||
        return getAttributeNamesSkipGenerated(true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Finds all attribute names except managed like <code>id</code>,
 | 
			
		||||
     * <code>created_at</code>, <code>updated_at</code> and <code>record_version</code>, depending on argument.
 | 
			
		||||
     *
 | 
			
		||||
     * @param managed if true, time managed attributes <code>created_at</code> and <code>updated_at</code> will not be included (they are managed automatically).
 | 
			
		||||
     *                If false (not managed) <code>created_at</code> and <code>updated_at</code> will be included in output.
 | 
			
		||||
     * @return list of all attributes except <code>id</code>, <code>created_at</code>, <code>updated_at</code> and
 | 
			
		||||
     * <code>record_version</code>, depending on argument.
 | 
			
		||||
     */
 | 
			
		||||
    public Set<String> getAttributeNamesSkipGenerated(boolean managed) {
 | 
			
		||||
        //TODO: can cache this, but will need a cache for managed=true an another for managed=false
 | 
			
		||||
        Set<String> attributesNames = new CaseInsensitiveSet(getAttributeNamesSkipId());
 | 
			
		||||
 | 
			
		||||
        if (managed) {
 | 
			
		||||
            attributesNames.remove("created_at");
 | 
			
		||||
            attributesNames.remove("updated_at");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        attributesNames.remove(versionColumn);
 | 
			
		||||
        return attributesNames;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Finds all attribute names except those provided as arguments.
 | 
			
		||||
     *
 | 
			
		||||
     * @return list of all attributes except those provided as arguments.
 | 
			
		||||
     */
 | 
			
		||||
    public Set<String> getAttributeNamesSkip(String... names) {
 | 
			
		||||
        Set<String> attributes = new CaseInsensitiveSet(getAttributeNames());
 | 
			
		||||
        for (String name : names) {
 | 
			
		||||
            attributes.remove(name);
 | 
			
		||||
        }
 | 
			
		||||
        return attributes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns true if this model supports optimistic locking, false if not
 | 
			
		||||
     *
 | 
			
		||||
     * @return true if this model supports optimistic locking, false if not
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isVersioned() {
 | 
			
		||||
        return columnMetadata != null && columnMetadata.containsKey(versionColumn);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieves all attribute names.
 | 
			
		||||
     *
 | 
			
		||||
     * @return all attribute names.
 | 
			
		||||
     */
 | 
			
		||||
    protected Set<String> getAttributeNames() {
 | 
			
		||||
        if (columnMetadata == null || columnMetadata.isEmpty())
 | 
			
		||||
            throw new InitException("Failed to find table: " + getTableName());
 | 
			
		||||
        return Collections.unmodifiableSet(columnMetadata.keySet());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getIdName() {
 | 
			
		||||
        return idName;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns optional composite primary key class
 | 
			
		||||
     *
 | 
			
		||||
     * @return composite primary key class
 | 
			
		||||
     */
 | 
			
		||||
    public String[] getCompositeKeys() {
 | 
			
		||||
        return compositeKeys;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns association of this table with the target table. Will return null if there is no association.
 | 
			
		||||
     *
 | 
			
		||||
     * @param targetModelClass association of this model and the target model.
 | 
			
		||||
     * @param associationClass class of association in requested.
 | 
			
		||||
     * @return association of this table with the target table. Will return null if there is no association with target
 | 
			
		||||
     * table and specified type.
 | 
			
		||||
     */
 | 
			
		||||
    public <A extends Association> A getAssociationForTarget(Class<? extends Model> targetModelClass, Class<A> associationClass) {
 | 
			
		||||
        Association result = null;
 | 
			
		||||
        for (Association association : associations) {
 | 
			
		||||
            if (association.getClass().equals(associationClass) && association.getTargetClass().equals(targetModelClass)) {
 | 
			
		||||
                result = association;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return (A) result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns association of this table with the target table. Will return null if there is no association.
 | 
			
		||||
     *
 | 
			
		||||
     * @param targetClass association of this model and the target model.
 | 
			
		||||
     * @return association of this table with the target table. Will return null if there is no association with target
 | 
			
		||||
     * table and specified type.
 | 
			
		||||
     */
 | 
			
		||||
    public <A extends Association> A getAssociationForTarget(Class<? extends Model> targetClass) {
 | 
			
		||||
        Association result = null;
 | 
			
		||||
        for (Association association : associations) {
 | 
			
		||||
            if (association.getTargetClass().equals(targetClass)) {
 | 
			
		||||
                result = association;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return (A) result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns associations of this table with the target table. It is possible
 | 
			
		||||
     * to have more than one association to a target table if a target table is the same as source. Usually this
 | 
			
		||||
     * happens when tree structures are stored in the same table (category has many categories).
 | 
			
		||||
     *
 | 
			
		||||
     * @param targetModelClass association of this model and the target model.
 | 
			
		||||
     * @return list of associations of this table with the target table. Will return empty list if none found.
 | 
			
		||||
     * table and specified type.
 | 
			
		||||
     */
 | 
			
		||||
    public List<Association> getAssociationsForTarget(Class<? extends Model> targetModelClass) {
 | 
			
		||||
        List<Association> result = new ArrayList<>();
 | 
			
		||||
 | 
			
		||||
        for (Association association : associations) {
 | 
			
		||||
            if (association.getTargetClass().equals(targetModelClass)) {
 | 
			
		||||
                result.add(association);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void addAssociation(Association association) {
 | 
			
		||||
        if (!associations.contains(association)) {
 | 
			
		||||
            LogFilter.log(LOGGER, LogLevel.INFO, "Association found: {}", association);
 | 
			
		||||
            associations.add(association);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * returns true if this attribute is present in this meta model. This method i case insensitive.
 | 
			
		||||
     *
 | 
			
		||||
     * @param attribute attribute name, case insensitive.
 | 
			
		||||
     * @return true if this attribute is present in this meta model, false of not.
 | 
			
		||||
     */
 | 
			
		||||
    boolean hasAttribute(String attribute) {
 | 
			
		||||
        if (columnMetadata != null) {
 | 
			
		||||
            if (columnMetadata.containsKey(attribute)) {
 | 
			
		||||
                return true;
 | 
			
		||||
            } else if (attribute.startsWith("\"") && attribute.endsWith("\"")) {
 | 
			
		||||
                return columnMetadata.containsKey(attribute.substring(1, attribute.length() - 1));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected boolean hasAssociation(Class<? extends Model> targetClass, Class<? extends Association> associationClass) {
 | 
			
		||||
        for (Association association : associations) {
 | 
			
		||||
            if (association.getTargetClass().equals(targetClass) &&
 | 
			
		||||
                    association.getClass().equals(associationClass)) return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public String toString() {
 | 
			
		||||
        final StringBuilder t = new StringBuilder();
 | 
			
		||||
        t.append("MetaModel: ").append(tableName).append(", ").append(modelClass).append("\n");
 | 
			
		||||
        if (columnMetadata != null) {
 | 
			
		||||
            for (Entry<String, ColumnMetadata> metadata : columnMetadata.entrySet()) {
 | 
			
		||||
                t.append(metadata.getValue()).append(", ");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return t.toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * FK name is a foreign key name used in relationships as a foreign key column in a child table (table represented by this
 | 
			
		||||
     * instance is a parent table).
 | 
			
		||||
     * The FK name is derived using {@link org.javalite.common.Inflector}: It is a singular version of this table name plus "_id".
 | 
			
		||||
     *
 | 
			
		||||
     * @return foreign key name used in relationships as a foreign key column in a child table.
 | 
			
		||||
     */
 | 
			
		||||
    public String getFKName() {
 | 
			
		||||
        return singularize(getTableName()).toLowerCase() + "_id";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected List<OneToManyAssociation> getOneToManyAssociations(List<Association> exclusions) {
 | 
			
		||||
        List<OneToManyAssociation> one2Manies = new ArrayList<>();
 | 
			
		||||
        for (Association association : associations) {
 | 
			
		||||
            if (association.getClass().equals(OneToManyAssociation.class) && !exclusions.contains(association)) {
 | 
			
		||||
                one2Manies.add((OneToManyAssociation) association);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return one2Manies;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected List<OneToManyPolymorphicAssociation> getPolymorphicAssociations(List<Association> exclusions) {
 | 
			
		||||
        List<OneToManyPolymorphicAssociation> one2Manies = new ArrayList<>();
 | 
			
		||||
        for (Association association : associations) {
 | 
			
		||||
            if (association.getClass().equals(OneToManyPolymorphicAssociation.class) && !exclusions.contains(association)) {
 | 
			
		||||
                one2Manies.add((OneToManyPolymorphicAssociation) association);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return one2Manies;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected List<Many2ManyAssociation> getManyToManyAssociations(List<Association> excludedAssociations) {
 | 
			
		||||
        List<Many2ManyAssociation> many2Manies = new ArrayList<>();
 | 
			
		||||
        for (Association association : associations) {
 | 
			
		||||
            if (association.getClass().equals(Many2ManyAssociation.class) && !excludedAssociations.contains(association)) {
 | 
			
		||||
                many2Manies.add((Many2ManyAssociation) association);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return many2Manies;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public String getDbType() {
 | 
			
		||||
        return dbType;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Dialect getDialect() {
 | 
			
		||||
        return Registry.instance().getConfiguration().getDialect(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected List<Association> getAssociations() {
 | 
			
		||||
        return Collections.unmodifiableList(associations);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if this model has a named attribute that has the same name as argument.
 | 
			
		||||
     * <p>
 | 
			
		||||
     * Throws <code>IllegalArgumentException</code> in case it does not find it.
 | 
			
		||||
     *
 | 
			
		||||
     * @param attribute name  of attribute or association target.
 | 
			
		||||
     */
 | 
			
		||||
    protected void checkAttribute(String attribute) {
 | 
			
		||||
        if (!hasAttribute(attribute)) {
 | 
			
		||||
            String sb = "Attribute: '" + attribute + "' is not defined in model: '" + getModelClass() + ". "
 | 
			
		||||
                    + "Available attributes: " + getAttributeNames();
 | 
			
		||||
            throw new IllegalArgumentException(sb);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Provides column metadata map, keyed by attribute names.
 | 
			
		||||
     * Table columns correspond to ActiveJDBC model attributes.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Provides column metadata map, keyed by attribute names.
 | 
			
		||||
     */
 | 
			
		||||
    public Map<String, ColumnMetadata> getColumnMetadata() {
 | 
			
		||||
        if (columnMetadata == null || columnMetadata.isEmpty())
 | 
			
		||||
            throw new InitException("Failed to find table: " + getTableName());
 | 
			
		||||
        return Collections.unmodifiableMap(columnMetadata);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void setColumnMetadata(Map<String, ColumnMetadata> columnMetadata) {
 | 
			
		||||
        this.columnMetadata = columnMetadata;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Checks if there is association to the target model class.,
 | 
			
		||||
     *
 | 
			
		||||
     * @param targetModelClass class of a model that will be checked for association from current model.
 | 
			
		||||
     * @return true if any association exists such that the current model is a source and targetModelClass is a target.
 | 
			
		||||
     */
 | 
			
		||||
    public boolean isAssociatedTo(Class<? extends Model> targetModelClass) {
 | 
			
		||||
 | 
			
		||||
        if (targetModelClass == null) {
 | 
			
		||||
            throw new NullPointerException();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (Association association : associations) {
 | 
			
		||||
            if (association.getTargetClass().equals(targetModelClass)) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void removeAssociationForTarget(Class<? extends Model> modelClass) {
 | 
			
		||||
        Association association = getAssociationForTarget(modelClass);
 | 
			
		||||
        if (association != null) {
 | 
			
		||||
            associations.remove(association);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -32,3 +32,6 @@ LOCALE:
 | 
			
		||||
MISC:
 | 
			
		||||
  FIELD-COPY-FAILED: '拷贝 {0} 对象失败'
 | 
			
		||||
  FIELD-COPY-ERROR: '拷贝 {0} 对象出错:{1}'
 | 
			
		||||
DATABASE:
 | 
			
		||||
  CONNECTION-ESTABLISHED: '成功连接到 {0} 数据库,连接池大小 {1}'
 | 
			
		||||
  CONNECTION-ERROR: '连接到数据库错误:{0}'
 | 
			
		||||
		Reference in New Issue
	
	Block a user