001package org.kuali.ole.docstore.common.util;
002
003import org.kuali.ole.docstore.common.document.config.DocumentSearchConfig;
004import org.kuali.ole.docstore.common.document.content.bib.marc.BibMarcRecord;
005import org.kuali.ole.docstore.common.document.content.bib.marc.DataField;
006import org.kuali.ole.docstore.common.document.content.bib.marc.SubField;
007import org.slf4j.Logger;
008import org.slf4j.LoggerFactory;
009
010import java.util.*;
011
012/**
013 * Created by sambasivam on 17/10/14.
014 */
015public class BibMarcUtil {
016
017    private static final String SEPERATOR_DATA_FIELD = ", ";
018    private static final String SEPERATOR_SUB_FIELD = " ";
019    private static final String PATTERN_CHAR = "*";
020    private static final String SEPERATOR_HYPHEN = " - ";
021    private static final String SEPERATOR_DOUBLE_HYPHEN = " -- ";
022
023    public static DocumentSearchConfig documentSearchConfig = DocumentSearchConfig.getDocumentSearchConfig();
024
025    public static String TITLE_DISPLAY = "Title_display";
026    public static String AUTHOR_DISPLAY = "Author_display";
027    public static String PUBLISHER_DISPLAY = "Publisher_display";
028    public static String ISBN_DISPLAY = "ISBN_display";
029    public static String ISSN_DISPLAY = "ISSN_display";
030
031
032    static {
033        List<String> fieldsNames = new ArrayList<>();
034        fieldsNames.add(TITLE_DISPLAY);
035        fieldsNames.add(AUTHOR_DISPLAY);
036        fieldsNames.add(PUBLISHER_DISPLAY);
037        fieldsNames.add(ISBN_DISPLAY);
038        fieldsNames.add(ISSN_DISPLAY);
039
040        documentSearchConfig.buildIncludeAndExcludeMapping(fieldsNames);
041    }
042
043
044    private static final Logger LOG = LoggerFactory.getLogger(BibMarcUtil.class);
045
046    /**
047     * Method to give data field value of a given include tags and exclude tags
048     *
049     * @param includeTags
050     * @param excludeTags
051     * @param record
052     * @param isHyphenSeperatorFirst - Pass 'false' by default (if it is not a subject field (Currently)).
053     *                               - Pass 'true' if it has to get encoded first subfield values with " - ".
054     * @param fieldName
055     * @return
056     */
057    private String getDataFieldValue(String includeTags, String excludeTags, BibMarcRecord record,
058                                     boolean isHyphenSeperatorFirst, String fieldName) {
059        List<String> fieldValues = new ArrayList<String>();
060        StringTokenizer includeTagsTokenizer = new StringTokenizer(includeTags, ",");
061
062        while (includeTagsTokenizer.hasMoreElements()) {
063            String tag = includeTagsTokenizer.nextToken();
064            tag = tag.trim();
065            int subFieldIdx = tag.indexOf('-');
066            String tagNum = (subFieldIdx == -1) ? tag : tag.substring(0, subFieldIdx);
067
068            for (int i = 0; i < record.getDataFields().size(); i++) {
069                DataField dataField = record.getDataFields().get(i);
070                if (isValidTag(dataField.getTag(), tagNum)) {
071                    StringBuilder fieldValue = new StringBuilder();
072                    List<SubField> subFields = dataField.getSubFields();
073                    if (subFieldIdx != -1) { // Includes only one Sub Field of a main Data Field.
074                        if (excludeTags != null && !excludeTags.contains(tag)) {
075                            String subFieldCodes = tag.substring(subFieldIdx + 1, tag.length());
076                            boolean isHyphenCodedOnce = false;
077                            for (SubField subField : subFields) {
078                                if (subFieldCodes.contains(subField.getCode())) {
079                                    if (fieldValue.length() != 0) {
080                                        if (!isHyphenSeperatorFirst || isHyphenCodedOnce || (
081                                                dataField.getTag().endsWith("00") || dataField.getTag().endsWith("10")
082                                                        || dataField.getTag().endsWith("11"))) {
083                                            fieldValue.append(SEPERATOR_SUB_FIELD);
084                                        } else {
085                                            fieldValue.append(SEPERATOR_HYPHEN);
086                                            isHyphenCodedOnce = true;
087                                        }
088                                    }
089                                    fieldValue.append(subField.getValue());
090                                }
091                            }
092                        }
093                    } else { // Includes whole Data Field i.e includes All Sub Fields in a datafield
094                        boolean isHyphenCodedOnce = false;
095                        boolean isFirstSubField = false;
096                        for (SubField subField : subFields) {
097                            if (excludeTags != null &&  !excludeTags.contains(dataField.getTag() + "-" + subField.getCode()) && !excludeTags
098                                    .contains(tagNum + "-" + subField.getCode())) {
099                                if (fieldValue.length() != 0) {
100                                    if (!isHyphenSeperatorFirst || isHyphenCodedOnce || (
101                                            dataField.getTag().endsWith("00") || dataField.getTag().endsWith("10")
102                                                    || dataField.getTag().endsWith("11"))) {
103                                        fieldValue.append(SEPERATOR_SUB_FIELD);
104                                    } else {
105
106                                        fieldValue.append(SEPERATOR_HYPHEN);
107                                        isHyphenCodedOnce = true;
108                                    }
109                                }
110                                fieldValue.append(subField.getValue());
111                            }
112                        }
113                    }
114                    if ((dataField.getTag().equalsIgnoreCase("650") || dataField.getTag().equalsIgnoreCase("651"))
115                            && fieldValue != null && fieldValue.length() > 1 && fieldValue.toString().trim().length() > 1) {
116                        String fieldVal = fieldValue.toString().trim();
117                        String lastChar = String.valueOf(fieldVal.charAt(fieldVal.length() - 1));
118                        if (!lastChar.equalsIgnoreCase(".")) {
119                            fieldValue.append(".");
120                        }
121                    }
122                    fieldValues.add(fieldValue.toString().trim());
123                }
124            }
125        }
126        if (fieldValues.size() == 1) {
127            return fieldValues.get(0);
128        } else if (fieldValues.size() > 0) {
129            return fieldValues.get(0);
130        } else {
131            return null;
132        }
133    }
134
135    /**
136     * Method to validate tag with given allowed tag format supplied.
137     *
138     * @param tag
139     * @param tagFormat
140     * @return
141     */
142    private boolean isValidTag(String tag, String tagFormat) {
143        try {
144            if (!tagFormat.contains(PATTERN_CHAR)) {
145                return tagFormat.equals(tag);
146            } else {
147                int idx = tagFormat.lastIndexOf(PATTERN_CHAR);
148                return isValidTag(tag.substring(0, idx) + tag.substring(idx + PATTERN_CHAR.length(), tag.length()), tagFormat.substring(0, idx)
149                        + tagFormat.substring(idx + PATTERN_CHAR.length(), tagFormat.length()));
150            }
151        } catch (Exception e) {
152            LOG.info("Exception :", e);
153            return false;
154        }
155    }
156
157
158    public Map<String, String> buildDataValuesForBibInfo(BibMarcRecord bibMarcRecord) {
159        Map<String, String> dataFields = new HashMap<>();
160
161
162        String titleInclude = documentSearchConfig.FIELDS_TO_TAGS_2_INCLUDE_MAP_SELECTED.get(TITLE_DISPLAY);
163        String titleExclude = documentSearchConfig.FIELDS_TO_TAGS_2_EXCLUDE_MAP_SELECTED.get(TITLE_DISPLAY);
164        String title = this.getDataFieldValue(titleInclude, titleExclude, bibMarcRecord, false, TITLE_DISPLAY);
165
166        String authorInclude = documentSearchConfig.FIELDS_TO_TAGS_2_INCLUDE_MAP_SELECTED.get(AUTHOR_DISPLAY);
167        String authorExclude = documentSearchConfig.FIELDS_TO_TAGS_2_EXCLUDE_MAP_SELECTED.get(AUTHOR_DISPLAY);
168        String author = this.getDataFieldValue(authorInclude, authorExclude, bibMarcRecord, false, AUTHOR_DISPLAY);
169
170        String publisherInclude = documentSearchConfig.FIELDS_TO_TAGS_2_INCLUDE_MAP_SELECTED.get(PUBLISHER_DISPLAY);
171        String publisherExclude = documentSearchConfig.FIELDS_TO_TAGS_2_EXCLUDE_MAP_SELECTED.get(PUBLISHER_DISPLAY);
172        String publisher = this.getDataFieldValue(publisherInclude, publisherExclude, bibMarcRecord, false, PUBLISHER_DISPLAY);
173
174        String isbnInclude = documentSearchConfig.FIELDS_TO_TAGS_2_INCLUDE_MAP_SELECTED.get(ISBN_DISPLAY);
175        String isbnExclude = documentSearchConfig.FIELDS_TO_TAGS_2_EXCLUDE_MAP_SELECTED.get(ISBN_DISPLAY);
176        String isbn = this.getDataFieldValue(isbnInclude, isbnExclude, bibMarcRecord, false, ISBN_DISPLAY);
177
178
179        String issnInclude = documentSearchConfig.FIELDS_TO_TAGS_2_INCLUDE_MAP_SELECTED.get(ISSN_DISPLAY);
180        String issnExclude = documentSearchConfig.FIELDS_TO_TAGS_2_EXCLUDE_MAP_SELECTED.get(ISSN_DISPLAY);
181        String issn = this.getDataFieldValue(issnInclude, issnExclude, bibMarcRecord, false, ISSN_DISPLAY);
182
183
184        dataFields.put(TITLE_DISPLAY, title);
185        dataFields.put(AUTHOR_DISPLAY, author);
186        dataFields.put(PUBLISHER_DISPLAY, publisher);
187        dataFields.put(ISBN_DISPLAY, isbn);
188        dataFields.put(ISSN_DISPLAY, issn);
189
190        return dataFields;
191    }
192
193
194}