diff --git a/doc/spacemedia.notation b/doc/spacemedia.notation index f894f5f3..87d9a66e 100644 --- a/doc/spacemedia.notation +++ b/doc/spacemedia.notation @@ -1,1131 +1,1135 @@
+ + + + diff --git a/doc/spacemedia.uml b/doc/spacemedia.uml index ec270542..0f9605d5 100644 --- a/doc/spacemedia.uml +++ b/doc/spacemedia.uml @@ -1,288 +1,289 @@ + - +
diff --git a/doc/spacemedia_fr_FR.properties b/doc/spacemedia_fr_FR.properties index b5aff7ff..11ae39c6 100644 --- a/doc/spacemedia_fr_FR.properties +++ b/doc/spacemedia_fr_FR.properties @@ -1 +1 @@ -#Wed May 19 01:27:08 CEST 2021 +#Thu May 20 23:49:50 CEST 2021 diff --git a/sm-backend/pom.xml b/sm-backend/pom.xml index 359bd2e5..7cb535b6 100644 --- a/sm-backend/pom.xml +++ b/sm-backend/pom.xml @@ -1,12 +1,35 @@ 4.0.0 org.wikimedia.commons.donvip spacemedia 0.5.0-SNAPSHOT sm-backend Backend application + + + + org.wikimedia.commons.donvip + sm-data + ${project.version} + + + org.wikimedia.commons.donvip + sm-commons-data + ${project.version} + + + + org.springframework.boot + spring-boot-starter + + + org.mariadb.jdbc + mariadb-java-client + + + diff --git a/sm-backend/src/main/java/org/wikimedia/commons/donvip/spacemedia/backend/BackendApplication.java b/sm-backend/src/main/java/org/wikimedia/commons/donvip/spacemedia/backend/BackendApplication.java new file mode 100644 index 00000000..54f1adef --- /dev/null +++ b/sm-backend/src/main/java/org/wikimedia/commons/donvip/spacemedia/backend/BackendApplication.java @@ -0,0 +1,13 @@ +package org.wikimedia.commons.donvip.spacemedia.backend; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Import; + +@SpringBootApplication +@Import(BackendConfiguration.class) +public class BackendApplication { + + public static void main(String[] args) { + SpringApplication.run(BackendApplication.class, args); + } +} diff --git a/sm-backend/src/main/java/org/wikimedia/commons/donvip/spacemedia/backend/BackendConfiguration.java b/sm-backend/src/main/java/org/wikimedia/commons/donvip/spacemedia/backend/BackendConfiguration.java new file mode 100644 index 00000000..efed19b2 --- /dev/null +++ b/sm-backend/src/main/java/org/wikimedia/commons/donvip/spacemedia/backend/BackendConfiguration.java @@ -0,0 +1,12 @@ +package org.wikimedia.commons.donvip.spacemedia.backend; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.wikimedia.commons.donvip.spacemedia.commons.data.CommonsDbConfiguration; +import org.wikimedia.commons.donvip.spacemedia.data.DomainDbConfiguration; + +@Configuration +@Import({CommonsDbConfiguration.class, DomainDbConfiguration.class}) +public class BackendConfiguration { + +} diff --git a/sm-backend/src/main/resources/application-dev.properties b/sm-backend/src/main/resources/application-dev.properties new file mode 100644 index 00000000..0be2dfb1 --- /dev/null +++ b/sm-backend/src/main/resources/application-dev.properties @@ -0,0 +1,5 @@ +#spring.jpa.open-in-view=true +#spring.jpa.show-sql=true +#spring.jpa.properties.hibernate.format_sql=true +#logging.level.org.hibernate.SQL=DEBUG +#logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE diff --git a/sm-backend/src/main/resources/application-toolforge.properties b/sm-backend/src/main/resources/application-toolforge.properties new file mode 100644 index 00000000..e956ed47 --- /dev/null +++ b/sm-backend/src/main/resources/application-toolforge.properties @@ -0,0 +1,12 @@ +# see https://wikitech.wikimedia.org/wiki/Help:Toolforge/Database#User_databases +domain.datasource.url= +domain.datasource.username= +domain.datasource.password= + +commons.datasource.url=jdbc:mariadb://commonswiki.analytics.db.svc.eqiad.wmflabs:3306/commonswiki_p +commons.datasource.username= +commons.datasource.password= + +#server.servlet.contextPath=/spacemedia +server.port=8000 +logging.config=classpath:logback-spring-toolforge.xml diff --git a/sm-backend/src/main/resources/application.properties b/sm-backend/src/main/resources/application.properties new file mode 100644 index 00000000..970f9098 --- /dev/null +++ b/sm-backend/src/main/resources/application.properties @@ -0,0 +1,38 @@ +# Spring + +spring.jackson.default-property-inclusion=non_empty +spring.jackson.property-naming-strategy=SNAKE_CASE + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.open-in-view=false +spring.jpa.show-sql=false +spring.jpa.properties.hibernate.format_sql=false +spring.jpa.properties.hibernate.search.default.directory_provider = filesystem +spring.jpa.properties.hibernate.search.default.indexBase = /data/project/spacemedia/index/default + +# Local database for development +domain.datasource.url=jdbc:mariadb://localhost:3306/root_spacemedia +domain.datasource.username=root +domain.datasource.password= +domain.datasource.driver-class-name=org.mariadb.jdbc.Driver +domain.datasource.hikari.maximum-pool-size=4 +domain.datasource.hikari.max-lifetime=300000 +domain.datasource.hikari.connectionInitSql = SET NAMES 'utf8mb4' + +commons.datasource.url=jdbc:mariadb://localhost:3307/commonswiki_p +commons.datasource.username= +commons.datasource.password= +commons.datasource.driver-class-name=org.mariadb.jdbc.Driver +commons.datasource.hikari.maximum-pool-size=4 +commons.datasource.hikari.max-lifetime=300000 +commons.datasource.hikari.connectionInitSql = SET NAMES 'utf8mb4' + +commons.api.url = https://commons.wikimedia.org/w/api.php +commons.api.rest.url = https://commons.wikimedia.org/w/rest.php +commons.api.account = OptimusPrimeBot +commons.api.oauth1.consumer-token = +commons.api.oauth1.consumer-secret = +commons.api.oauth1.access-token = +commons.api.oauth1.access-secret = +commons.cat.search.depth = 1 +commons.img.preview.width = 640 diff --git a/sm-backend/src/main/resources/banner.txt b/sm-backend/src/main/resources/banner.txt new file mode 100644 index 00000000..d5bc6fe0 --- /dev/null +++ b/sm-backend/src/main/resources/banner.txt @@ -0,0 +1,6 @@ + _______..______ ___ ______ _______ .___ ___. _______ _______ __ ___ + / || _ \ / \ / || ____|| \/ | | ____|| \ | | / \ + | (----`| |_) | / ^ \ | ,----'| |__ | \ / | | |__ | .--. || | / ^ \ + \ \ | ___/ / /_\ \ | | | __| | |\/| | | __| | | | || | / /_\ \ +.----) | | | / _____ \ | `----.| |____ | | | | | |____ | '--' || | / _____ \ +|_______/ | _| /__/ \__\ \______||_______||__| |__| |_______||_______/ |__|/__/ \__\ diff --git a/sm-backend/src/main/resources/logback-spring-toolforge.xml b/sm-backend/src/main/resources/logback-spring-toolforge.xml new file mode 100644 index 00000000..df02b423 --- /dev/null +++ b/sm-backend/src/main/resources/logback-spring-toolforge.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/sm-data/pom.xml b/sm-data/pom.xml index 58bd0f44..f0c3529c 100644 --- a/sm-data/pom.xml +++ b/sm-data/pom.xml @@ -1,12 +1,21 @@ 4.0.0 org.wikimedia.commons.donvip spacemedia 0.5.0-SNAPSHOT sm-data - Data classes + JPA data classes + + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + diff --git a/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/DomainDbConfiguration.java b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/DomainDbConfiguration.java new file mode 100644 index 00000000..83b6e871 --- /dev/null +++ b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/DomainDbConfiguration.java @@ -0,0 +1,64 @@ +package org.wikimedia.commons.donvip.spacemedia.data; + +import java.util.HashMap; +import java.util.Map; + +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder; +import org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy; +import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableTransactionManagement +@EnableJpaRepositories( + entityManagerFactoryRef = "domainEntityManagerFactory", + transactionManagerRef = "domainTransactionManager", + basePackageClasses = {DomainDbConfiguration.class}) +public class DomainDbConfiguration { + + @Primary + @Bean(name = "domainDataSourceProperties") + @ConfigurationProperties("domain.datasource") + public DataSourceProperties dataSourceProperties() { + return new DataSourceProperties(); + } + + @Primary + @Bean(name = "domainDataSource") + @ConfigurationProperties("domain.datasource.hikari") + public DataSource dataSource() { + return dataSourceProperties().initializeDataSourceBuilder().build(); + } + + @Primary + @Bean(name = "domainEntityManagerFactory") + public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder, Environment env) { + Map hibernateProperties = new HashMap<>(); + hibernateProperties.put("hibernate.physical_naming_strategy", new SpringPhysicalNamingStrategy()); + hibernateProperties.put("hibernate.implicit_naming_strategy", new SpringImplicitNamingStrategy()); + hibernateProperties.put("hibernate.hbm2ddl.auto", env.getProperty("spring.jpa.hibernate.ddl-auto")); + return builder.dataSource(dataSource()) + .packages(getClass().getPackage().getName()) + .properties(hibernateProperties) + .persistenceUnit("domain").build(); + } + + @Primary + @Bean(name = "domainTransactionManager") + public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) { + return new JpaTransactionManager(entityManagerFactory); + } +} diff --git a/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/Human.java b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/Human.java new file mode 100644 index 00000000..4a7a47b4 --- /dev/null +++ b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/Human.java @@ -0,0 +1,8 @@ +package org.wikimedia.commons.donvip.spacemedia.data; + +import javax.persistence.Entity; + +@Entity +public class Human extends Person { + +} diff --git a/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/HumanRepository.java b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/HumanRepository.java new file mode 100644 index 00000000..668011e1 --- /dev/null +++ b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/HumanRepository.java @@ -0,0 +1,7 @@ +package org.wikimedia.commons.donvip.spacemedia.data; + +import org.springframework.data.repository.CrudRepository; + +public interface HumanRepository extends CrudRepository { + +} diff --git a/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/Organization.java b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/Organization.java new file mode 100644 index 00000000..b0e93426 --- /dev/null +++ b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/Organization.java @@ -0,0 +1,40 @@ +package org.wikimedia.commons.donvip.spacemedia.data; + +import java.net.URL; +import java.util.Objects; + +import javax.persistence.Column; +import javax.persistence.Entity; + +@Entity +public class Organization extends Person { + + /** + * Organization website URL. + */ + @Column(nullable = true) + private URL website; + + public URL getWebsite() { + return website; + } + + public void setWebsite(URL website) { + this.website = website; + } + + @Override + public int hashCode() { + return 31 * super.hashCode() + Objects.hash(website); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj) || getClass() != obj.getClass()) + return false; + Organization other = (Organization) obj; + return Objects.equals(website, other.website); + } +} diff --git a/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/OrganizationRepository.java b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/OrganizationRepository.java new file mode 100644 index 00000000..6b0b8d7f --- /dev/null +++ b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/OrganizationRepository.java @@ -0,0 +1,7 @@ +package org.wikimedia.commons.donvip.spacemedia.data; + +import org.springframework.data.repository.CrudRepository; + +public interface OrganizationRepository extends CrudRepository { + +} diff --git a/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/Person.java b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/Person.java new file mode 100644 index 00000000..06e10559 --- /dev/null +++ b/sm-data/src/main/java/org/wikimedia/commons/donvip/spacemedia/data/Person.java @@ -0,0 +1,58 @@ +package org.wikimedia.commons.donvip.spacemedia.data; + +import java.util.Objects; + +import javax.persistence.Column; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; + +/** + * Abstract superclass of persons (organizations and humans). + */ +@MappedSuperclass +public abstract class Person { + + /** + * Unique name identifying the person. + */ + @Id + @Column(nullable = false) + protected String name; + + /** + * Optional Wikidata Q identifier (should be defined for most organizations, but few humans) + */ + @Column(nullable = true) + protected String wikidata; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getWikidata() { + return wikidata; + } + + public void setWikidata(String wikidata) { + this.wikidata = wikidata; + } + + @Override + public int hashCode() { + return Objects.hash(name, wikidata); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + Person other = (Person) obj; + return Objects.equals(name, other.name) && Objects.equals(wikidata, other.wikidata); + } +}