// Path: src/main/java/org/nextrtc/examples/videochat_with_rest/domain/Member.java
// @Entity
// @Table(name = "Members")
// public class Member {
// 
//     @Id
//     @GeneratedValue(strategy = GenerationType.AUTO)
//     @Column(name = "member_id")
//     private int id;
// 
//     @Column(name = "member_rtc_id")
//     private String rtcId;
// 
//     @Column(name = "connected")
//     private Date connected;
// 
//     @Column(name = "disconnected")
//     private Date disconnected;
// 
//     @Column(name = "left_reason")
//     private String leftReason;
// 
//     @OneToOne(mappedBy = "member", fetch = FetchType.LAZY)
//     private Connection connection;
// 
//     @ManyToOne
//     @JoinColumn(name = "user_id")
//     private User user;
// 
//     /**
//      * for hibernate only
//      */
//     @Deprecated
//     Member() {
//     }
// 
//     public Member(String memberId, User user) {
//         this.rtcId = memberId;
//         this.user = user;
//         this.connected = now().toDate();
//     }
// 
//     public void disconnectWithReason(Optional<String> reason) {
//         disconnected = now().toDate();
//         reason.ifPresent(this::setLeftReason);
//     }
// 
//     @Override
//     public String toString() {
//         return String.format("(%s, %s)[%s - %s]", id, rtcId, connected, disconnected);
//     }
// 
//     public void leaves(Conversation conversation) {
//         if (connection.isFor(conversation)) {
//             connection.close();
//         }
//     }
// 
//     private void setLeftReason(String leftReason) {
//         this.leftReason = leftReason;
//     }
// 
//     public int startedBefore(Member p) {
//         return connected.compareTo(p.connected);
//     }
// 
//     public Call toCall() {
//         if (connection != null) {
//             List<String> members = connection.getConversationMembers().stream()
//                     .filter(m -> !m.equals(this))
//                     .map(m -> m.rtcId)
//                     .collect(toList());
//             return new Call(members, !connection.isClosed(), connection.getBegin(), connection.getDuration());
//         } else {
//             return new Call(new ArrayList<>(), false, connected, getDuration());
//         }
//     }
// 
//     private long getDuration() {
//         if (disconnected == null) {
//             return new Interval(new DateTime(connected), DateTime.now()).toDurationMillis();
//         }
//         return new Interval(new DateTime(connected), new DateTime(disconnected)).toDurationMillis();
//     }
// 
//     public String getUsername() {
//         return user.getUsername();
//     }
// }
// 
// Path: src/main/java/org/nextrtc/examples/videochat_with_rest/repo/MemberRepository.java
// @Repository
// @Transactional
// public interface MemberRepository extends JpaRepository<Member, Integer> {
// 
//     @Query("select m from Member m where m.rtcId = :rtcId and m.connected = (select max(mm.connected) from Member mm where mm.rtcId = m.rtcId)")
//     Optional<Member> findByRtcId(@Param("rtcId") String rtcId);
// 
//     @Query("select m from Member m where m.rtcId = :rtcId and m.connected = (select max(mm.connected) from Member mm where mm.rtcId = m.rtcId)")
//     Member getByRtcId(@Param("rtcId") String rtcId);
// 
// }


import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.nextrtc.examples.videochat_with_rest.domain.Member;
import org.nextrtc.examples.videochat_with_rest.repo.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.util.Properties;
        ds.setMaxIdleTime(30 * 60); // 30 minutes
        ds.setMaxStatements(10);
        ds.setMaxStatementsPerConnection(10);
        ds.setAutoCommitOnClose(true);

        ds.setDriverClass(environment.getRequiredProperty("nextrtc.db.driverClassName"));
        ds.setJdbcUrl(environment.getRequiredProperty("nextrtc.db.url"));
        ds.setUser(environment.getRequiredProperty("nextrtc.db.username"));
        ds.setPassword(environment.getRequiredProperty("nextrtc.db.password"));
        return ds;
    }

    private Properties hibernateProperties() {
        Properties props = new Properties();
        props.setProperty("hibernate.dialect", environment.getRequiredProperty("nextrtc.db.dialect"));
        props.setProperty("hibernate.hbm2ddl.auto", environment.getProperty("nextrtc.db.hbm2ddl", "validate"));
        props.setProperty("hibernate.show_sql", "false");
        props.setProperty("hibernate.format_sql", "true");
        props.setProperty("hibernate.ejb.naming_strategy", "org.hibernate.cfg.DefaultNamingStrategy");
        props.setProperty("hibernate.cache.use_second_level_cache", "false");
        props.setProperty("jadira.usertype.autoRegisterUserTypes", "true");
        return props;
    }

    @Bean(name = "NextRTCEntityMangerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws Exception {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factoryBean.setJpaProperties(hibernateProperties());
        factoryBean.setDataSource(datasource());
// Path: src/main/java/org/nextrtc/examples/videochat_with_rest/domain/Member.java
// @Entity
// @Table(name = "Members")
// public class Member {
// 
//     @Id
//     @GeneratedValue(strategy = GenerationType.AUTO)
//     @Column(name = "member_id")
//     private int id;
// 
//     @Column(name = "member_rtc_id")
//     private String rtcId;
// 
//     @Column(name = "connected")
//     private Date connected;
// 
//     @Column(name = "disconnected")
//     private Date disconnected;
// 
//     @Column(name = "left_reason")
//     private String leftReason;
// 
//     @OneToOne(mappedBy = "member", fetch = FetchType.LAZY)
//     private Connection connection;
// 
//     @ManyToOne
//     @JoinColumn(name = "user_id")
//     private User user;
// 
//     /**
//      * for hibernate only
//      */
//     @Deprecated
//     Member() {
//     }
// 
//     public Member(String memberId, User user) {
//         this.rtcId = memberId;
//         this.user = user;
//         this.connected = now().toDate();
//     }
// 
//     public void disconnectWithReason(Optional<String> reason) {
//         disconnected = now().toDate();
//         reason.ifPresent(this::setLeftReason);
//     }
// 
//     @Override
//     public String toString() {
//         return String.format("(%s, %s)[%s - %s]", id, rtcId, connected, disconnected);
//     }
// 
//     public void leaves(Conversation conversation) {
//         if (connection.isFor(conversation)) {
//             connection.close();
//         }
//     }
// 
//     private void setLeftReason(String leftReason) {
//         this.leftReason = leftReason;
//     }
// 
//     public int startedBefore(Member p) {
//         return connected.compareTo(p.connected);
//     }
// 
//     public Call toCall() {
//         if (connection != null) {
//             List<String> members = connection.getConversationMembers().stream()
//                     .filter(m -> !m.equals(this))
//                     .map(m -> m.rtcId)
//                     .collect(toList());
//             return new Call(members, !connection.isClosed(), connection.getBegin(), connection.getDuration());
//         } else {
//             return new Call(new ArrayList<>(), false, connected, getDuration());
//         }
//     }
// 
//     private long getDuration() {
//         if (disconnected == null) {
//             return new Interval(new DateTime(connected), DateTime.now()).toDurationMillis();
//         }
//         return new Interval(new DateTime(connected), new DateTime(disconnected)).toDurationMillis();
//     }
// 
//     public String getUsername() {
//         return user.getUsername();
//     }
// }
// 
// Path: src/main/java/org/nextrtc/examples/videochat_with_rest/repo/MemberRepository.java
// @Repository
// @Transactional
// public interface MemberRepository extends JpaRepository<Member, Integer> {
// 
//     @Query("select m from Member m where m.rtcId = :rtcId and m.connected = (select max(mm.connected) from Member mm where mm.rtcId = m.rtcId)")
//     Optional<Member> findByRtcId(@Param("rtcId") String rtcId);
// 
//     @Query("select m from Member m where m.rtcId = :rtcId and m.connected = (select max(mm.connected) from Member mm where mm.rtcId = m.rtcId)")
//     Member getByRtcId(@Param("rtcId") String rtcId);
// 
// }


// Path: src/main/java/org/nextrtc/examples/videochat_with_rest/config/DBConfig.java
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.nextrtc.examples.videochat_with_rest.domain.Member;
import org.nextrtc.examples.videochat_with_rest.repo.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.util.Properties;

        ds.setMaxIdleTime(30 * 60); // 30 minutes
        ds.setMaxStatements(10);
        ds.setMaxStatementsPerConnection(10);
        ds.setAutoCommitOnClose(true);

        ds.setDriverClass(environment.getRequiredProperty("nextrtc.db.driverClassName"));
        ds.setJdbcUrl(environment.getRequiredProperty("nextrtc.db.url"));
        ds.setUser(environment.getRequiredProperty("nextrtc.db.username"));
        ds.setPassword(environment.getRequiredProperty("nextrtc.db.password"));
        return ds;
    }

    private Properties hibernateProperties() {
        Properties props = new Properties();
        props.setProperty("hibernate.dialect", environment.getRequiredProperty("nextrtc.db.dialect"));
        props.setProperty("hibernate.hbm2ddl.auto", environment.getProperty("nextrtc.db.hbm2ddl", "validate"));
        props.setProperty("hibernate.show_sql", "false");
        props.setProperty("hibernate.format_sql", "true");
        props.setProperty("hibernate.ejb.naming_strategy", "org.hibernate.cfg.DefaultNamingStrategy");
        props.setProperty("hibernate.cache.use_second_level_cache", "false");
        props.setProperty("jadira.usertype.autoRegisterUserTypes", "true");
        return props;
    }

    @Bean(name = "NextRTCEntityMangerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws Exception {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        factoryBean.setJpaProperties(hibernateProperties());
        factoryBean.setDataSource(datasource());
        factoryBean.setPackagesToScan(Member.class.getPackage().getName());