package com.cardence.lawshelf.cfr;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.cardence.lawshelf.cfr.CfrContentContainer.Tag;
import com.cardence.lawshelf.cfr.adapters.CfrChapterSectionAdapter;
import com.cardence.lawshelf.cfr.adapters.CfrCodeCollectionYearExtractor;
import com.cardence.lawshelf.cfr.adapters.CfrFinalSectionAdapter;
import com.cardence.lawshelf.cfr.adapters.CfrPartSectionAdapter;
import com.cardence.lawshelf.cfr.adapters.CfrSubChapterSectionAdapter;
import com.cardence.lawshelf.cfr.adapters.CfrSubPartSectionAdapter;
import com.cardence.lawshelf.cfr.adapters.CfrSubTitleSectionAdapter;
import com.cardence.lawshelf.cfr.adapters.CfrTitleCodeAdapter;
import com.cardence.lawshelf.cfr.jaxb.CFRDOC;
import com.cardence.lawshelf.cfr.jaxb.CHAPTER;
import com.cardence.lawshelf.cfr.jaxb.FMTR;
import com.cardence.lawshelf.cfr.jaxb.PART;
import com.cardence.lawshelf.cfr.jaxb.SECTION;
import com.cardence.lawshelf.cfr.jaxb.SUBCHAP;
import com.cardence.lawshelf.cfr.jaxb.SUBPART;
import com.cardence.lawshelf.cfr.jaxb.SUBTITLE;
import com.cardence.lawshelf.cfr.jaxb.TITLE;
import com.cardence.lawshelf.model.ContentFull;
import com.cardence.lawshelf.model.cfr.CfrCodeModel;
import com.cardence.lawshelf.model.cfr.CfrCollectionModel;
import com.cardence.lawshelf.model.cfr.CfrSectionModel;
import com.cardence.lawshelf.model.helper.EntityPersistenceHelper;
@Component
public class CfrJaxbToMysqlProcessor {
@Autowired
private CfrSectionTracker sectionTracker;
@Autowired
private CfrDatabaseIdTracker databaseIdTracker;
@Autowired
private EntityPersistenceHelper persistenceHelper;
private CFRDOC cfr;
private Integer collectionYear;
private Integer codeCollectionId;
private Integer codeId;
private String codeReference;
protected void beforeProcess() {
// init whatever is needed
processAndStoreCollection();
processAndStoreCode();
}
protected void afterProcess() {
// clean up after done
}
protected CFRDOC getCfr() {
return cfr;
}
public synchronized void processCfrResource(CFRDOC cfr, Integer collectionYear) {
this.cfr = cfr;
this.collectionYear = collectionYear;
beforeProcess();
beginProcess();
afterProcess();
this.cfr = null;
}
private void beginProcess() {
doTopLevelConversion();
processTitle(cfr.getTITLE());
}
private void doTopLevelConversion() {
FMTR fmtr = cfr.getFMTR();
fmtr.getTHISTITL();
// P -> summary
fmtr.getTITLEPG();
// titlenum -> title 9
// subject - name of title
// date -> as of date (future)
}
private void addCfrDatabaseIdToTracker(Integer id, String reference) {
this.databaseIdTracker.linkDatabaseIdToReference(id, reference);
}
private void addCfrSectionAndParentReferenceToTracker(CfrSection section, String parentReference) {
this.sectionTracker.addNewChildHeadingForParentReference(section, parentReference);
}
private SUBTITLE findSubtitle(TITLE title) {
return title.getSUBTITLE();
}
private CHAPTER findChapterFromSubtitle(SUBTITLE subtitle) {
return subtitle.getCHAPTER();
}
private CHAPTER findChapterFromTitle(TITLE title) {
return title.getCHAPTER();
}
private List<SUBCHAP> findSubChapter(CHAPTER chapter) {
final List<SUBCHAP> finalList = new ArrayList<SUBCHAP>();
for (Object obj : chapter.getContent()) {
if (obj.getClass().equals(SUBCHAP.class)) {
finalList.add((SUBCHAP) obj);
}
}
return finalList;
}
private List<PART> findPartFromSubChapter(SUBCHAP subchapter) {
final List<PART> finalList = new ArrayList<PART>();
for (Object obj : subchapter.getPRTPAGEOrRESERVEDOrHD()) {
if (obj.getClass().equals(PART.class)) {
finalList.add((PART) obj);
}
}
return finalList;
}
private List<PART> findPartFromChapter(CHAPTER chapter) {
final List<PART> finalList = new ArrayList<PART>();
for (Object obj : chapter.getContent()) {
if (obj.getClass().equals(PART.class)) {
finalList.add((PART) obj);
}
}
return finalList;
}
private List<SUBPART> findSubPart(PART part) {
final List<SUBPART> finalList = new ArrayList<SUBPART>();
for (Object obj : part.getContent()) {
if (obj.getClass().equals(SUBPART.class)) {
finalList.add((SUBPART) obj);
}
}
return finalList;
}
private List<SECTION> findSectionFromPart(PART part) {
final List<SECTION> finalList = new ArrayList<SECTION>();
for (Object obj : part.getContent()) {
if (obj.getClass().equals(SECTION.class)) {
finalList.add((SECTION) obj);
}
}
return finalList;
}
private List<SECTION> findSectionFromSubPart(SUBPART subpart) {
final List<SECTION> finalList = new ArrayList<SECTION>();
for (Object obj : subpart.getSECTIONOrSECTNOOrSUBJECT()) {
if (obj.getClass().equals(SECTION.class)) {
finalList.add((SECTION) obj);
}
}
return finalList;
}
private List<SECTION> findSectionFromChapter(CHAPTER chapter) {
final List<SECTION> finalList = new ArrayList<SECTION>();
for (Object obj : chapter.getContent()) {
if (obj.getClass().equals(SECTION.class)) {
finalList.add((SECTION) obj);
}
}
return finalList;
}
private List<SECTION> findSectionFromSubChapter(SUBCHAP subchapter) {
final List<SECTION> finalList = new ArrayList<SECTION>();
for (Object obj : subchapter.getPRTPAGEOrRESERVEDOrHD()) {
if (obj.getClass().equals(SECTION.class)) {
finalList.add((SECTION) obj);
}
}
return finalList;
}
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
private void didFinishProcessingTitle(TITLE title) {
final SUBTITLE subtitle = this.findSubtitle(title);
final CHAPTER chapter = this.findChapterFromTitle(title);
if (subtitle != null) {
this.processSubTitleWithParentId(subtitle, null);
}
if (chapter != null) {
this.processChapterWithParentId(chapter, null, this.codeReference);
}
}
private void didFinishProcessingSubTitle(SUBTITLE subtitle, Integer databaseSubtitleId) {
final CHAPTER chapter = this.findChapterFromSubtitle(subtitle);
if (chapter != null) {
this.processChapterWithParentId(chapter, databaseSubtitleId, null);
}
}
private void didFinishProcessingChapter(CHAPTER chapter, Integer databaseChapterId) {
final List<SECTION> section = this.findSectionFromChapter(chapter);
final List<SUBCHAP> subchapter = this.findSubChapter(chapter);
final List<PART> part = this.findPartFromChapter(chapter);
if (subchapter != null) {
this.processSubChaptersWithParentId(subchapter, databaseChapterId);
}
if (part != null) {
this.processPartsWithParentId(part, databaseChapterId);
}
if (section != null) {
this.processSectionsWithParentId(section, databaseChapterId);
}
}
private void didFinishProcessingSubChapter(SUBCHAP subchapter, Integer databaseSubchapterId) {
final List<SECTION> section = this.findSectionFromSubChapter(subchapter);
final List<PART> part = this.findPartFromSubChapter(subchapter);
if (part != null) {
this.processPartsWithParentId(part, databaseSubchapterId);
}
if (section != null) {
this.processSectionsWithParentId(section, databaseSubchapterId);
}
}
private void didFinishProcessingPart(PART part, Integer databasePartId) {
final List<SECTION> section = this.findSectionFromPart(part);
final List<SUBPART> subpart = this.findSubPart(part);
int subpartCounter = 1;
if (subpart != null) {
this.processSubPartsWithParentId(subpart, databasePartId, subpartCounter++);
}
if (section != null) {
this.processSectionsWithParentId(section, databasePartId);
}
}
private void didFinishProcessingSubPart(SUBPART subpart, Integer databaseSubpartId) {
final List<SECTION> section = this.findSectionFromSubPart(subpart);
if (section != null) {
this.processSectionsWithParentId(section, databaseSubpartId);
}
}
private void didFinishProcessingSection(SECTION section, Integer sectionId) {
processContentForSection(section, sectionId);
}
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
private void processTitle(TITLE title) {
// already stored in db... move on to the next important elements
this.didFinishProcessingTitle(title);
}
private void processSubTitleWithParentId(SUBTITLE subtitle, Integer parentId) {
final CfrSection cfrSection = new CfrSubTitleSectionAdapter(subtitle, this.codeReference);
final Integer newID = storeSectionInDatabaseWithParentId(cfrSection, parentId);
this.didFinishProcessingSubTitle(subtitle, newID);
}
private void processChaptersWithParentId(List<CHAPTER> chapters, Integer parentId, String parentReference) {
for (CHAPTER item : chapters) {
processChapterWithParentId(item, parentId, parentReference);
}
}
private void processChapterWithParentId(CHAPTER chapter, Integer parentId, String parentReference) {
final CfrSection cfrSection = new CfrChapterSectionAdapter(chapter, parentReference);
final Integer newID = storeSectionInDatabaseWithParentId(cfrSection, parentId);
this.didFinishProcessingChapter(chapter, newID);
}
private void processSubChaptersWithParentId(List<SUBCHAP> subchapters, Integer parentId) {
for (SUBCHAP item : subchapters) {
processSubChapterWithParentId(item, parentId);
}
}
private void processSubChapterWithParentId(SUBCHAP subchapter, Integer parentId) {
final CfrSection cfrSection = new CfrSubChapterSectionAdapter(subchapter);
final Integer newID = storeSectionInDatabaseWithParentId(cfrSection, parentId);
this.didFinishProcessingSubChapter(subchapter, newID);
}
private void processPartsWithParentId(List<PART> parts, Integer parentId) {
for (PART item : parts) {
processPartWithParentId(item, parentId);
}
}
private void processPartWithParentId(PART part, Integer parentId) {
final CfrSection cfrSection = new CfrPartSectionAdapter(part);
final Integer newID = storeSectionInDatabaseWithParentId(cfrSection, parentId);
this.didFinishProcessingPart(part, newID);
}
private void processSubPartsWithParentId(List<SUBPART> subparts, Integer parentId, int subpartCounter) {
for (SUBPART item : subparts) {
processSubPartWithParentId(item, parentId, subpartCounter);
}
}
private void processSubPartWithParentId(SUBPART subpart, Integer parentId, int subpartCounter) {
final CfrSection cfrSection = new CfrSubPartSectionAdapter(subpart, subpartCounter);
final Integer newID = storeSectionInDatabaseWithParentId(cfrSection, parentId);
this.didFinishProcessingSubPart(subpart, newID);
}
private void processSectionsWithParentId(List<SECTION> sections, Integer parentId) {
for (SECTION item : sections) {
processSectionWithParentId(item, parentId);
}
}
private void processSectionWithParentId(SECTION section, Integer parentId) {
final String parentReference = this.databaseIdTracker.getReferenceForDatabaseId(parentId);
final CfrSection cfrSection = new CfrFinalSectionAdapter(section, parentReference);
final Integer newID = storeSectionInDatabaseWithParentId(cfrSection, parentId);
this.didFinishProcessingSection(section, newID);
}
private void processContentForSection(SECTION section, Integer parentId) {
CfrContentContainer content = new CfrContentContainer(Tag.DIV);
content.addContentList(section.getSUBJECTOrAUTHOrAPPRO());
ContentFull contentModel = new ContentFull();
contentModel.setSectionId(parentId);
contentModel.setContent(content.getStyledContent());
contentModel.setNotes(false);
contentModel.setFormatType("text/html");
this.persistenceHelper.storeContentFull(contentModel, true);
}
private void processNotesForSection(SECTION section, Integer parentId) {
CfrContentContainer content = new CfrContentContainer(Tag.DIV);
content.addContentList(section.getSUBJECTOrAUTHOrAPPRO());
ContentFull contentModel = new ContentFull();
contentModel.setSectionId(parentId);
contentModel.setContent(content.getStyledContent());
contentModel.setNotes(true);
contentModel.setFormatType("text/html");
this.persistenceHelper.storeContentFull(contentModel, true);
}
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
private void processAndStoreCollection() {
//final CfrCodeCollectionYearExtractor yearExtractor = new CfrCodeCollectionYearExtractor(this.cfr);
final CfrCollectionModel collectionModel = new CfrCollectionModel();
//collectionModel.setYear(yearExtractor.getYear());
collectionModel.setYear(this.collectionYear);
this.persistenceHelper.storeCodeCollection(collectionModel);
// this.sectionTracker.addNewChildHeadingForParentReference(null, null);
this.codeCollectionId = collectionModel.getId();
}
private void processAndStoreCode() {
final TITLE title = cfr.getTITLE();
final CfrCode titleCode = new CfrTitleCodeAdapter(title);
final CfrCodeModel titleCodeModel = new CfrCodeModel(titleCode);
titleCodeModel.setCodeCollectionId(this.codeCollectionId);
this.persistenceHelper.storeCode(titleCodeModel);
this.addCfrDatabaseIdToTracker(titleCodeModel.getId(), titleCode.getReference());
this.codeId = titleCodeModel.getId();
}
private Integer storeSectionInDatabaseWithParentId(CfrSection section, Integer databaseParentId) {
String parentReference = this.databaseIdTracker.getReferenceForDatabaseId(databaseParentId);
this.addCfrSectionAndParentReferenceToTracker(section, parentReference);
final CfrSectionModel sectionModel = new CfrSectionModel(section);
sectionModel.setParentSectionId(databaseParentId);
sectionModel.setCodeId(this.codeId);
this.persistenceHelper.storeSection(sectionModel);
this.addCfrDatabaseIdToTracker(sectionModel.getId(), section.getReference());
return sectionModel.getId();
}
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
}