Merge pull request #63 from lacerta-doc/feature/add_vcs

VCS追加(WIP)
This commit is contained in:
ろむねこ 2024-01-14 15:39:10 +09:00 committed by GitHub
commit 5837a1a2d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 941 additions and 7 deletions

View File

@ -4,7 +4,6 @@
<component name="GradleSettings"> <component name="GradleSettings">
<option name="linkedExternalProjectsSettings"> <option name="linkedExternalProjectsSettings">
<GradleProjectSettings> <GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="externalProjectPath" value="$PROJECT_DIR$" /> <option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="jbr-17" /> <option name="gradleJvm" value="jbr-17" />
<option name="modules"> <option name="modules">
@ -30,6 +29,7 @@
<option value="$PROJECT_DIR$/shared/ui" /> <option value="$PROJECT_DIR$/shared/ui" />
<option value="$PROJECT_DIR$/source" /> <option value="$PROJECT_DIR$/source" />
<option value="$PROJECT_DIR$/utils" /> <option value="$PROJECT_DIR$/utils" />
<option value="$PROJECT_DIR$/vcs" />
</set> </set>
</option> </option>
<option name="resolveExternalAnnotations" value="false" /> <option name="resolveExternalAnnotations" value="false" />

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" /> <component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" /> <output url="file://$PROJECT_DIR$/build/classes" />
</component> </component>
<component name="ProjectType"> <component name="ProjectType">

View File

@ -68,4 +68,7 @@ dependencies {
// Processor // Processor
implementation project(':processor') implementation project(':processor')
// LacertaVcs
implementation project(':vcs')
} }

View File

@ -51,6 +51,7 @@ public class DebugMenuTopFragment extends Fragment {
debugMenuListItems.add(new DebugMenuListItem("Document Tester", "placeholder", R.id.action_debugMenuTopFragment_to_debugMenuDocumentTesterTopFragment, true)); debugMenuListItems.add(new DebugMenuListItem("Document Tester", "placeholder", R.id.action_debugMenuTopFragment_to_debugMenuDocumentTesterTopFragment, true));
debugMenuListItems.add(new DebugMenuListItem("Scanner", "placeholder", R.id.action_debugMenuTopFragment_to_scannerDataManagerStubFragment, true)); debugMenuListItems.add(new DebugMenuListItem("Scanner", "placeholder", R.id.action_debugMenuTopFragment_to_scannerDataManagerStubFragment, true));
debugMenuListItems.add(new DebugMenuListItem("Document List", "placeholder", R.id.action_debugMenuTopFragment_to_debugMenuLibraryItemListPageFragment, true)); debugMenuListItems.add(new DebugMenuListItem("Document List", "placeholder", R.id.action_debugMenuTopFragment_to_debugMenuLibraryItemListPageFragment, true));
debugMenuListItems.add(new DebugMenuListItem("VCS", "placeholder", R.id.action_debugMenuTopFragment_to_debugMenuVcsGeneralFragment, true));
DebugMenuListItemAdapter adapter = new DebugMenuListItemAdapter(debugMenuListItems); DebugMenuListItemAdapter adapter = new DebugMenuListItemAdapter(debugMenuListItems);
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);

View File

@ -0,0 +1,58 @@
package one.nem.lacerta.feature.debug;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import one.nem.lacerta.vcs.LacertaVcs;
import one.nem.lacerta.vcs.factory.LacertaVcsFactory;
/**
* A simple {@link Fragment} subclass.
* Use the {@link DebugMenuVcsGeneralActionFragment#newInstance} factory method to
* create an instance of this fragment.
*/
@AndroidEntryPoint
public class DebugMenuVcsGeneralActionFragment extends Fragment {
@Inject
LacertaVcsFactory lacertaVcsFactory;
public DebugMenuVcsGeneralActionFragment() {
// Required empty public constructor
}
public static DebugMenuVcsGeneralActionFragment newInstance() {
DebugMenuVcsGeneralActionFragment fragment = new DebugMenuVcsGeneralActionFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_debug_menu_vcs_general_action, container, false);
view.findViewById(R.id.add_sample_log_rev_button).setOnClickListener(v -> {
LacertaVcs lacertaVcs = lacertaVcsFactory.create("example_id");
lacertaVcs.insertPage(1, "example_id");
});
return view;
}
}

View File

@ -0,0 +1,59 @@
package one.nem.lacerta.feature.debug;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import one.nem.lacerta.feature.debug.common.adapter.DebugMenuListItemAdapter;
import one.nem.lacerta.feature.debug.common.model.DebugMenuListItem;
/**
* A simple {@link Fragment} subclass.
* Use the {@link DebugMenuVcsGeneralFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class DebugMenuVcsGeneralFragment extends Fragment {
public DebugMenuVcsGeneralFragment() {
// Required empty public constructor
}
public static DebugMenuVcsGeneralFragment newInstance() {
DebugMenuVcsGeneralFragment fragment = new DebugMenuVcsGeneralFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_debug_menu_vcs_general, container, false);
RecyclerView recyclerView = view.findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new androidx.recyclerview.widget.LinearLayoutManager(getContext()));
List<DebugMenuListItem> debugMenuListItems = new ArrayList<>();
debugMenuListItems.add(new DebugMenuListItem("General Action", "placeholder", R.id.action_debugMenuVcsGeneralFragment_to_debugMenuVcsGeneralActionFragment, true));
debugMenuListItems.add(new DebugMenuListItem("Log Record", "placeholder", R.id.action_debugMenuVcsGeneralFragment_to_debugMenuVcsLogRecordFragment, true));
debugMenuListItems.add(new DebugMenuListItem("Rev Record", "placeholder", R.id.action_debugMenuVcsGeneralFragment_to_debugMenuVcsRevRecordFragment, true));
DebugMenuListItemAdapter adapter = new DebugMenuListItemAdapter(debugMenuListItems);
recyclerView.setAdapter(adapter);
return view;
}
}

View File

@ -0,0 +1,42 @@
package one.nem.lacerta.feature.debug;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
* Use the {@link DebugMenuVcsLogRecordFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class DebugMenuVcsLogRecordFragment extends Fragment {
public DebugMenuVcsLogRecordFragment() {
// Required empty public constructor
}
public static DebugMenuVcsLogRecordFragment newInstance() {
DebugMenuVcsLogRecordFragment fragment = new DebugMenuVcsLogRecordFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_debug_menu_vcs_log_record, container, false);
return view;
}
}

View File

@ -0,0 +1,41 @@
package one.nem.lacerta.feature.debug;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* A simple {@link Fragment} subclass.
* Use the {@link DebugMenuVcsRevRecordFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class DebugMenuVcsRevRecordFragment extends Fragment {
public DebugMenuVcsRevRecordFragment() {
// Required empty public constructor
}
public static DebugMenuVcsRevRecordFragment newInstance() {
DebugMenuVcsRevRecordFragment fragment = new DebugMenuVcsRevRecordFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_debug_menu_vcs_rev_record, container, false);
return view;
}
}

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DebugMenuVcsGeneralFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DebugMenuVcsGeneralActionFragment">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<Button
android:id="@+id/add_sample_log_rev_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add Sample log/Rev" />
</LinearLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DebugMenuVcsGeneralFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/log_recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DebugMenuVcsGeneralFragment">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rev_recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -19,6 +19,9 @@
<action <action
android:id="@+id/action_debugMenuTopFragment_to_debugMenuLibraryItemListPageFragment" android:id="@+id/action_debugMenuTopFragment_to_debugMenuLibraryItemListPageFragment"
app:destination="@id/debugMenuLibraryItemListPageFragment" /> app:destination="@id/debugMenuLibraryItemListPageFragment" />
<action
android:id="@+id/action_debugMenuTopFragment_to_debugMenuVcsGeneralFragment"
app:destination="@id/debugMenuVcsGeneralFragment" />
</fragment> </fragment>
<fragment <fragment
android:id="@+id/debugMenuDocumentTesterTopFragment" android:id="@+id/debugMenuDocumentTesterTopFragment"
@ -51,4 +54,34 @@
android:name="one.nem.lacerta.feature.debug.DebugMenuLibraryItemListPageFragment" android:name="one.nem.lacerta.feature.debug.DebugMenuLibraryItemListPageFragment"
android:label="fragment_debug_menu_library_item_list_page" android:label="fragment_debug_menu_library_item_list_page"
tools:layout="@layout/fragment_debug_menu_library_item_list_page" /> tools:layout="@layout/fragment_debug_menu_library_item_list_page" />
<fragment
android:id="@+id/debugMenuVcsGeneralFragment"
android:name="one.nem.lacerta.feature.debug.DebugMenuVcsGeneralFragment"
android:label="fragment_debug_menu_vcs_general"
tools:layout="@layout/fragment_debug_menu_vcs_general" >
<action
android:id="@+id/action_debugMenuVcsGeneralFragment_to_debugMenuVcsGeneralActionFragment"
app:destination="@id/debugMenuVcsGeneralActionFragment" />
<action
android:id="@+id/action_debugMenuVcsGeneralFragment_to_debugMenuVcsRevRecordFragment"
app:destination="@id/debugMenuVcsRevRecordFragment" />
<action
android:id="@+id/action_debugMenuVcsGeneralFragment_to_debugMenuVcsLogRecordFragment"
app:destination="@id/debugMenuVcsLogRecordFragment" />
</fragment>
<fragment
android:id="@+id/debugMenuVcsGeneralActionFragment"
android:name="one.nem.lacerta.feature.debug.DebugMenuVcsGeneralActionFragment"
android:label="fragment_debug_menu_vcs_general_action"
tools:layout="@layout/fragment_debug_menu_vcs_general_action" />
<fragment
android:id="@+id/debugMenuVcsLogRecordFragment"
android:name="one.nem.lacerta.feature.debug.DebugMenuVcsLogRecordFragment"
android:label="fragment_debug_menu_vcs_log_record"
tools:layout="@layout/fragment_debug_menu_vcs_log_record" />
<fragment
android:id="@+id/debugMenuVcsRevRecordFragment"
android:name="one.nem.lacerta.feature.debug.DebugMenuVcsRevRecordFragment"
android:label="fragment_debug_menu_vcs_rev_record"
tools:layout="@layout/fragment_debug_menu_vcs_rev_record" />
</navigation> </navigation>

View File

@ -31,3 +31,4 @@ include ':model'
include ':processor' include ':processor'
include ':shared:ui' include ':shared:ui'
include ':shared:icon' include ':shared:icon'
include ':vcs'

View File

@ -7,15 +7,21 @@ import androidx.room.RoomDatabase;
import one.nem.lacerta.source.database.entity.TagEntity; import one.nem.lacerta.source.database.entity.TagEntity;
import one.nem.lacerta.source.database.entity.DocumentEntity; import one.nem.lacerta.source.database.entity.DocumentEntity;
import one.nem.lacerta.source.database.entity.LibraryEntity; import one.nem.lacerta.source.database.entity.LibraryEntity;
import one.nem.lacerta.source.database.entity.VcsRevEntity;
import one.nem.lacerta.source.database.entity.VcsLogEntity;
// Daos // Daos
import one.nem.lacerta.source.database.dao.TagDao; import one.nem.lacerta.source.database.dao.TagDao;
import one.nem.lacerta.source.database.dao.DocumentDao; import one.nem.lacerta.source.database.dao.DocumentDao;
import one.nem.lacerta.source.database.dao.LibraryDao; import one.nem.lacerta.source.database.dao.LibraryDao;
import one.nem.lacerta.source.database.dao.VcsRevDao;
import one.nem.lacerta.source.database.dao.VcsLogDao;
@Database(entities = {TagEntity.class, DocumentEntity.class, LibraryEntity.class}, version = 1) @Database(entities = {TagEntity.class, DocumentEntity.class, LibraryEntity.class, VcsRevEntity.class, VcsLogEntity.class}, version = 2)
public abstract class LacertaDatabase extends RoomDatabase { public abstract class LacertaDatabase extends RoomDatabase {
public abstract TagDao tagDao(); public abstract TagDao tagDao();
public abstract DocumentDao documentDao(); public abstract DocumentDao documentDao();
public abstract LibraryDao libraryDao(); public abstract LibraryDao libraryDao();
public abstract VcsRevDao vcsRevDao();
public abstract VcsLogDao vcsLogDao();
} }

View File

@ -20,6 +20,8 @@ public class LacertaDatabaseModule {
LacertaDatabase.class, LacertaDatabase.class,
"lacerta.db") "lacerta.db")
.allowMainThreadQueries() // Debug .allowMainThreadQueries() // Debug
.fallbackToDestructiveMigration() // Debug Only: マイグレーションがない場合などにデータベースを再生成する
.fallbackToDestructiveMigrationOnDowngrade() // Debug Only: マイグレーションがない場合などにデータベースを再生成する
.build(); .build();
} }
} }

View File

@ -5,7 +5,7 @@ import androidx.room.TypeConverter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
public class TagArrayListConverter { public class ArrayListConverter {
@TypeConverter @TypeConverter
public static ArrayList<String> fromString(String value) { public static ArrayList<String> fromString(String value) {

View File

@ -0,0 +1,39 @@
package one.nem.lacerta.source.database.dao;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;
import one.nem.lacerta.source.database.entity.VcsLogEntity;
@Dao
public interface VcsLogDao {
// Select
@Query("SELECT * FROM vcs_log WHERE id = :id")
VcsLogEntity findById(String id);
@Query("SELECT * FROM vcs_log")
List<VcsLogEntity> findAll();
@Query("SELECT * FROM vcs_log WHERE id IN (:ids)")
List<VcsLogEntity> findByIds(List<String> ids);
@Query("SELECT * FROM vcs_log WHERE document_id = :documentId")
List<VcsLogEntity> findByDocumentId(String documentId);
// Insert
@Insert
void insertAll(VcsLogEntity... vcsLogs);
@Insert
void insertAll(List<VcsLogEntity> vcsLogs);
@Insert
void insert(VcsLogEntity vcsLog);
// TODO-rca: Update, Deleteが必要か検討
}

View File

@ -0,0 +1,44 @@
package one.nem.lacerta.source.database.dao;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import java.util.List;
import one.nem.lacerta.source.database.entity.VcsRevEntity;
@Dao
public interface VcsRevDao {
// Select
@Query("SELECT * FROM vcs_rev WHERE id = :id")
VcsRevEntity findById(String id);
@Query("SELECT * FROM vcs_rev")
List<VcsRevEntity> findAll();
@Query("SELECT * FROM vcs_rev WHERE id IN (:ids)")
List<VcsRevEntity> findByIds(List<String> ids);
@Query("SELECT * FROM vcs_rev WHERE document_id = :documentId")
List<VcsRevEntity> findByDocumentId(String documentId);
@Query("SELECT * FROM vcs_rev WHERE document_id = :documentId ORDER BY created_at DESC LIMIT 1")
VcsRevEntity findLatestByDocumentId(String documentId);
@Query("SELECT * FROM vcs_rev WHERE document_id = :documentId AND branch_name = :branchName ORDER BY created_at DESC LIMIT 1")
VcsRevEntity findLatestByDocumentIdAndBranchName(String documentId, String branchName);
@Insert
void insertAll(VcsRevEntity... vcsRevs);
@Insert
void insertAll(List<VcsRevEntity> vcsRevs);
@Insert
void insert(VcsRevEntity vcsRev);
// TODO-rca: Update, Deleteが必要か検討
}

View File

@ -8,7 +8,6 @@ import androidx.room.TypeConverter;
import androidx.room.TypeConverters; import androidx.room.TypeConverters;
import one.nem.lacerta.source.database.common.DateTypeConverter; import one.nem.lacerta.source.database.common.DateTypeConverter;
import one.nem.lacerta.source.database.common.TagArrayListConverter;
import one.nem.lacerta.source.database.common.TagListConverter; import one.nem.lacerta.source.database.common.TagListConverter;
import java.util.ArrayList; import java.util.ArrayList;
@ -40,4 +39,7 @@ public class DocumentEntity {
@ColumnInfo(name = "tag_ids") @ColumnInfo(name = "tag_ids")
public List<String> tagIds; // タグ public List<String> tagIds; // タグ
@ColumnInfo(name = "public_path")
public String publicPath; // 公開パス
} }

View File

@ -16,10 +16,12 @@ public class LibraryEntity {
@NonNull @NonNull
public String id; // ドキュメントID public String id; // ドキュメントID
@ColumnInfo(name = "root_path") // TODO-rca: 廃止
public String rootPath; // rootのパス
@ColumnInfo(name = "path") @ColumnInfo(name = "path")
public String path; // パス public String path; // パス
@ColumnInfo(name = "root_path")
public String rootPath; // ルートパス
} }

View File

@ -0,0 +1,48 @@
package one.nem.lacerta.source.database.entity;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import androidx.room.TypeConverters;
import java.util.Date;
import one.nem.lacerta.source.database.common.DateTypeConverter;
@Entity(tableName = "vcs_log")
@TypeConverters({DateTypeConverter.class})
public class VcsLogEntity {
/**
* イベントID
*/
@PrimaryKey
@ColumnInfo(name = "id")
@NonNull
public String id;
/**
* ドキュメントID
*/
@ColumnInfo(name = "document_id")
public String documentId;
/**
* ブランチ名
*/
@ColumnInfo(name = "branch_name")
public String branchName;
/**
* 発生日時
*/
@ColumnInfo(name = "created_at")
public Date createdAt;
/**
* 発生アクション
*/
@ColumnInfo(name = "action")
public String action;
}

View File

@ -0,0 +1,58 @@
package one.nem.lacerta.source.database.entity;
import androidx.annotation.NonNull;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import androidx.room.TypeConverters;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import one.nem.lacerta.source.database.common.ArrayListConverter;
import one.nem.lacerta.source.database.common.DateTypeConverter;
@Entity(tableName = "vcs_rev")
@TypeConverters({DateTypeConverter.class, ArrayListConverter.class})
public class VcsRevEntity {
/**
* リビジョンID
*/
@PrimaryKey
@ColumnInfo(name = "id")
@NonNull
public String id;
/**
* ドキュメントID
*/
@ColumnInfo(name = "document_id")
public String documentId;
/**
* ブランチ名
*/
@ColumnInfo(name = "branch_name")
public String branchName;
/**
* コミットメッセージ
*/
@ColumnInfo(name = "commit_message")
public String commitMessage;
/**
* コミット日時
*/
@ColumnInfo(name = "created_at")
public Date createdAt;
/**
* 含まれるLogのID
*/
@ColumnInfo(name = "log_ids")
public ArrayList<String> logIds;
}

1
vcs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

59
vcs/build.gradle Normal file
View File

@ -0,0 +1,59 @@
plugins {
alias(libs.plugins.com.android.library)
}
android {
namespace 'one.nem.lacerta.vcs'
compileSdk 34
defaultConfig {
minSdk 26
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation libs.androidx.appcompat
implementation libs.com.google.android.material
testImplementation libs.junit
androidTestImplementation libs.androidx.test.ext.junit
androidTestImplementation libs.androidx.test.espresso.core
// Hilt (DI)
implementation libs.com.google.dagger.hilt.android
annotationProcessor libs.com.google.dagger.hilt.compiler
implementation project(':model')
implementation project(':source')
implementation project(':utils')
// Jackson
// TODO-rca:
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
implementation 'com.fasterxml.jackson.core:jackson-core:2.16.1'
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
implementation 'com.fasterxml.jackson.core:jackson-databind:2.16.1'
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations
implementation 'com.fasterxml.jackson.core:jackson-annotations:2.16.1'
// Room
implementation libs.androidx.room.runtime
annotationProcessor libs.androidx.room.compiler
}

0
vcs/consumer-rules.pro Normal file
View File

21
vcs/proguard-rules.pro vendored Normal file
View File

@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@ -0,0 +1,26 @@
package one.nem.lacerta.vcs;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("one.nem.lacerta.vcs.test", appContext.getPackageName());
}
}

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@ -0,0 +1,48 @@
package one.nem.lacerta.vcs;
public enum ActionType {
INSERT_PAGE("insert_page"),
UPDATE_PAGE("update_page"),
DELETE_PAGE("delete_page"),
// TODO-rca: 実装----------------------------------------
UPDATE_PAGE_ORDER("update_page_order"),
INSERT_PAGE_CONTENT("insert_page_content"),
UPDATE_PAGE_CONTENT("update_page_content"),
DELETE_PAGE_CONTENT("delete_page_content"),
CREATE_BRANCH("create_branch"),
DROP_BRANCH("drop_branch"),
REBASE_BRANCH("rebase_branch"),
// -----------------------------------------------------
CREATE_DOCUMENT("create_document"),
DROP_DOCUMENT("drop_document"),
// TODO-rca: 実装----------------------------------------
UPDATE_DOCUMENT_META("update_document_meta"),
// -----------------------------------------------------
OTHER("other");
private final String value;
ActionType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static ActionType fromValue(String value) {
for (ActionType actionType : ActionType.values()) {
if (actionType.getValue().equals(value)) {
return actionType;
}
}
return ActionType.OTHER;
}
}

View File

@ -0,0 +1,15 @@
package one.nem.lacerta.vcs;
public interface LacertaVcs {
// Actions
public void updatePage(int index, String fileName);
public void insertPage(int index, String fileName);
public void deletePage(int index);
// debug
public void printLog();
}

View File

@ -0,0 +1,10 @@
package one.nem.lacerta.vcs.factory;
import dagger.assisted.AssistedFactory;
import one.nem.lacerta.vcs.impl.LacertaVcsImpl;
@AssistedFactory
public interface LacertaVcsFactory {
LacertaVcsImpl create(String documentId);
}

View File

@ -0,0 +1,62 @@
package one.nem.lacerta.vcs.impl;
import java.util.UUID;
import javax.inject.Inject;
import dagger.assisted.Assisted;
import dagger.assisted.AssistedInject;
import one.nem.lacerta.source.database.LacertaDatabase;
import one.nem.lacerta.source.database.entity.VcsLogEntity;
import one.nem.lacerta.utils.LacertaLogger;
import one.nem.lacerta.vcs.LacertaVcs;
public class LacertaVcsImpl implements LacertaVcs {
// TAG
private static final String TAG = LacertaVcsImpl.class.getSimpleName();
String documentId;
LacertaDatabase database;
LacertaLogger logger;
@AssistedInject
public LacertaVcsImpl(LacertaLogger logger, LacertaDatabase database, @Assisted String documentId) {
this.logger = logger;
this.database = database;
this.documentId = documentId;
logger.debug(TAG, "LacertaVcsImpl constructor");
}
@Override
public void updatePage(int index, String fileName) {
}
@Override
public void insertPage(int index, String fileName) {
logger.debug(TAG, "insertPage");
VcsLogEntity vcsLogEntity = new VcsLogEntity();
vcsLogEntity.id = UUID.randomUUID().toString();
vcsLogEntity.documentId = documentId;
vcsLogEntity.branchName = "master";
vcsLogEntity.createdAt = new java.util.Date();
vcsLogEntity.action = "placeholder";
database.vcsLogDao().insert(vcsLogEntity);
}
@Override
public void deletePage(int index) {
}
@Override
public void printLog() {
logger.debug(TAG, "printLog");
database.vcsLogDao().findAll().forEach(vcsLog -> {
logger.debug(TAG, vcsLog.id);
});
}
}

View File

@ -0,0 +1,65 @@
package one.nem.lacerta.vcs.internal;
import android.provider.ContactsContract;
import one.nem.lacerta.vcs.ActionType;
import one.nem.lacerta.vcs.model.action.DeletePage;
import one.nem.lacerta.vcs.model.action.InsertPage;
import one.nem.lacerta.vcs.model.action.UpdatePage;
import one.nem.lacerta.vcs.model.action.common.ActionBase;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JsonUtils {
// TODO-rca: Injectionで実装しなおす
// Public methods
public static String toJson(Object object) {
ActionBase converted;
if (object == null) {
return null;
} else if (object instanceof ActionBase) {
ObjectMapper mapper = new ObjectMapper();
switch (((ActionBase) object).getActionType()) {
case INSERT_PAGE:
converted = (InsertPage) object;
break;
case UPDATE_PAGE:
converted = (UpdatePage) object;
break;
case DELETE_PAGE:
converted = (DeletePage) object;
break;
default:
throw new IllegalArgumentException("Unknown action type");
}
try {
return mapper.writeValueAsString(converted);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
throw new IllegalArgumentException("Unknown object type");
}
public static Object fromJson(String json, ActionType actionType) {
ObjectMapper mapper = new ObjectMapper();
try {
switch (actionType) {
case INSERT_PAGE:
return mapper.readValue(json, InsertPage.class);
case UPDATE_PAGE:
return mapper.readValue(json, UpdatePage.class);
case DELETE_PAGE:
return mapper.readValue(json, DeletePage.class);
default:
throw new IllegalArgumentException("Unknown action type");
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,19 @@
package one.nem.lacerta.vcs.model.action;
import one.nem.lacerta.vcs.model.action.common.ActionBase;
public class DeletePage extends ActionBase {
private int index;
public DeletePage() {
}
public DeletePage(int index) {
this.index = index;
}
public int getIndex() {
return index;
}
}

View File

@ -0,0 +1,25 @@
package one.nem.lacerta.vcs.model.action;
import one.nem.lacerta.vcs.model.action.common.ActionBase;
public class InsertPage extends ActionBase {
private int index;
private String fileName;
public InsertPage() {
}
public InsertPage(int index, String fileName) {
this.index = index;
this.fileName = fileName;
}
public int getIndex() {
return index;
}
public String getFileName() {
return fileName;
}
}

View File

@ -0,0 +1,25 @@
package one.nem.lacerta.vcs.model.action;
import one.nem.lacerta.vcs.model.action.common.ActionBase;
public class UpdatePage extends ActionBase {
private int index;
private String fileName;
public UpdatePage() {
}
public UpdatePage(int index, String fileName) {
this.index = index;
this.fileName = fileName;
}
public int getIndex() {
return index;
}
public String getFileName() {
return fileName;
}
}

View File

@ -0,0 +1,22 @@
package one.nem.lacerta.vcs.model.action.common;
import one.nem.lacerta.vcs.ActionType;
public class ActionBase {
private ActionType actionType;
public ActionBase() {
}
public ActionBase(ActionType actionType) {
this.actionType = actionType;
}
public ActionType getActionType() {
return actionType;
}
public void setActionType(ActionType actionType) {
this.actionType = actionType;
}
}

View File

@ -0,0 +1,17 @@
package one.nem.lacerta.vcs;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}