001package org.kuali.ole.batch.helper;
002
003import org.apache.commons.lang.StringUtils;
004import org.apache.log4j.Logger;
005import org.kuali.ole.OLEConstants;
006import org.kuali.ole.batch.bo.OLEBatchProcessProfileBo;
007import org.kuali.ole.batch.bo.OLEBatchProcessProfileDataMappingOptionsBo;
008import org.kuali.ole.docstore.common.document.HoldingsTree;
009import org.kuali.ole.docstore.common.document.content.instance.*;
010import org.kuali.ole.docstore.common.document.content.instance.xstream.HoldingOlemlRecordProcessor;
011import org.kuali.ole.docstore.common.document.content.bib.marc.DataField;
012import org.kuali.ole.docstore.common.document.content.bib.marc.SubField;
013import org.springframework.util.CollectionUtils;
014
015import java.util.*;
016
017import static org.kuali.ole.OLEConstants.OLEBatchProcess.*;
018import static org.kuali.ole.OLEConstants.OLEBatchProcess.lineSeparator;
019
020/**
021 * Created with IntelliJ IDEA.
022 * User: meenrajd
023 * Date: 9/2/13
024 * Time: 5:12 PM
025 * To change this template use File | Settings | File Templates.
026 */
027public class EInstanceMappingHelper {
028    private List<DataField> dataFieldList = new ArrayList<DataField>();
029    private StringBuilder errBuilder;
030
031    private static final Logger LOG = Logger.getLogger(InstanceMappingHelper.class);
032    private HoldingOlemlRecordProcessor workEHoldingOlemlRecordProcessor = new HoldingOlemlRecordProcessor();
033    
034    /*public List<DataField> generateDataField(InstanceCollection instanceCollection, OLEBatchProcessProfileBo profile, StringBuilder errBuilder) throws Exception {
035        dataFieldList.clear();
036        this.errBuilder = errBuilder;
037        if (instanceCollection != null && instanceCollection.getInstance() != null) {
038            OleHoldings oleHoldings;
039            String dataFieldInstance = null;
040            List<OLEBatchProcessProfileDataMappingOptionsBo> mappingOptionsBoList = profile.getOleBatchProcessProfileMappingOptionsList().get(0).getOleBatchProcessProfileDataMappingOptionsBoList();
041
042            for (OLEBatchProcessProfileDataMappingOptionsBo mappingOptionsBo : mappingOptionsBoList) {
043                if (mappingOptionsBo.getDataType().equalsIgnoreCase(OLEConstants.OLEBatchProcess.BATCH_PROCESS_PROFILE_DATATYPE_EHOLDINGS)) {
044                    dataFieldInstance = getTag(mappingOptionsBo.getDestinationField());
045                }
046            }
047            if (dataFieldInstance == null) return Collections.EMPTY_LIST; //no subfields would be created for the bib
048
049            for (int i = 0; i < instanceCollection.getInstance().size(); i++) {
050                if ((oleHoldings = instanceCollection.getInstance().get(i)) == null) continue;
051                if (oleHoldings == null) continue;
052                DataField dataField = new DataField();
053                dataField.setTag(dataFieldInstance);
054                dataField.setInd1(" ");
055                dataField.setInd2(" ");
056                generateSubFields(mappingOptionsBoList, oleHoldings, dataField);
057                if (!dataField.getSubFields().isEmpty())
058                    dataFieldList.add(dataField);
059
060            }
061        }
062        return dataFieldList;
063    }*/
064
065    public List<DataField> generateDataFieldForEHolding(HoldingsTree holdingsTree, OLEBatchProcessProfileBo profile, StringBuilder errBuilder) throws Exception {
066        dataFieldList.clear();
067        this.errBuilder = errBuilder;        
068        if (holdingsTree != null) {
069            OleHoldings oleHoldings = null;
070            if (holdingsTree.getHoldings().getContentObject() != null) {
071                oleHoldings= holdingsTree.getHoldings().getContentObject();
072            } else {
073                oleHoldings = workEHoldingOlemlRecordProcessor.fromXML(holdingsTree.getHoldings().getContent());
074            }
075            Map<String, String> dataFieldEHoldingMap = new HashMap<>();
076            Map<String, String> dataFieldCoverageMap = new HashMap<>();
077            Map<String, String> dataFieldsDonorMap = new HashMap<>();
078            List<OLEBatchProcessProfileDataMappingOptionsBo> mappingOptionsBoList = profile.getOleBatchProcessProfileMappingOptionsList().get(0).getOleBatchProcessProfileDataMappingOptionsBoList();
079            for (OLEBatchProcessProfileDataMappingOptionsBo mappingOptionsBo : mappingOptionsBoList) {
080                if (mappingOptionsBo.getDataType().equalsIgnoreCase(OLEConstants.OLEBatchProcess.BATCH_PROCESS_PROFILE_DATATYPE_EHOLDINGS)) {
081                    if (mappingOptionsBo.getSourceField().equalsIgnoreCase(DESTINATION_FIELD_COVERAGE_START_DATE)
082                            || mappingOptionsBo.getSourceField().equalsIgnoreCase(DESTINATION_FIELD_COVERAGE_END_DATE)
083                            || mappingOptionsBo.getSourceField().equalsIgnoreCase(DESTINATION_FIELD_COVERAGE_START_ISSUE)
084                            || mappingOptionsBo.getSourceField().equalsIgnoreCase(DESTINATION_FIELD_COVERAGE_END_ISSUE)
085                            || mappingOptionsBo.getSourceField().equalsIgnoreCase(DESTINATION_FIELD_COVERAGE_START_VOLUME)
086                            || mappingOptionsBo.getSourceField().equalsIgnoreCase(DESTINATION_FIELD_COVERAGE_END_VOLUME)) {
087                        dataFieldCoverageMap.put(mappingOptionsBo.getDestinationField(), mappingOptionsBo.getSourceField());
088                    } else if (mappingOptionsBo.getSourceField().equalsIgnoreCase(DESTINATION_FIELD_DONOR_PUBLIC_DISPLAY)
089                            || mappingOptionsBo.getSourceField().equalsIgnoreCase(DESTINATION_FIELD_DONOR_NOTE)
090                            || mappingOptionsBo.getSourceField().equalsIgnoreCase(DESTINATION_FIELD_DONOR_CODE)) {
091                        dataFieldsDonorMap.put(mappingOptionsBo.getDestinationField(), mappingOptionsBo.getSourceField());
092                    } else {
093                        dataFieldEHoldingMap.put(mappingOptionsBo.getDestinationField(), mappingOptionsBo.getSourceField());
094                    }
095                }
096            }
097            if (!CollectionUtils.isEmpty(dataFieldEHoldingMap) || !CollectionUtils.isEmpty(dataFieldCoverageMap) || !CollectionUtils.isEmpty(dataFieldsDonorMap)) {
098                generateSubFieldsForEHolding(oleHoldings, dataFieldEHoldingMap, dataFieldCoverageMap, dataFieldsDonorMap);
099            } else {
100                return Collections.EMPTY_LIST;
101            }
102        }
103        return dataFieldList;
104    }
105
106    protected void generateSubFieldsForEHolding(OleHoldings oleHoldings, Map<String, String> dataFieldEHoldingMap, Map<String, String> dataFieldCoverageMap, Map<String, String> dataFieldsDonorMap) throws Exception {
107        List<DataField> linkList = new ArrayList<>();    
108        try {
109            for (Map.Entry<String, String> entry : dataFieldEHoldingMap.entrySet()) {
110                DataField dataField;
111                if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_CALL_NUMBER)) {
112                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
113                    if (dataField == null) {
114                        dataField = getDataField(entry);
115                        generateCallNumber(oleHoldings, getCode(entry.getKey()), dataField);
116                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
117                    } else {
118                        generateCallNumber(oleHoldings, getCode(entry.getKey()), dataField);
119                    }
120                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_HOLDING_CALL_NUMBER_TYPE)) {
121                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
122                    if (dataField == null) {
123                        dataField = getDataField(entry);
124                        generateCallNumberType(oleHoldings, getCode(entry.getKey()), dataField);
125                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
126                    } else {
127                        generateCallNumberType(oleHoldings, getCode(entry.getKey()), dataField);
128                    }
129                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LOCATION_LEVEL_1)) {
130                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
131                    if (dataField == null) {
132                        dataField = getDataField(entry);
133                        generateLocationLevel1(oleHoldings, getCode(entry.getKey()), dataField);
134                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
135                    } else {
136                        generateLocationLevel1(oleHoldings, getCode(entry.getKey()), dataField);
137                    }
138                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LOCATION_LEVEL_2)) {
139                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
140                    if (dataField == null) {
141                        dataField = getDataField(entry);
142                        generateLocationLevel2(oleHoldings, getCode(entry.getKey()), dataField);
143                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
144                    } else {
145                        generateLocationLevel2(oleHoldings, getCode(entry.getKey()), dataField);
146                    }
147                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LOCATION_LEVEL_3)) {
148                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
149                    if (dataField == null) {
150                        dataField = getDataField(entry);
151                        generateLocationLevel3(oleHoldings, getCode(entry.getKey()), dataField);
152                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
153                    } else {
154                        generateLocationLevel3(oleHoldings, getCode(entry.getKey()), dataField);
155                    }
156                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LOCATION_LEVEL_4)) {
157                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
158                    if (dataField == null) {
159                        dataField = getDataField(entry);
160                        generateLocationLevel4(oleHoldings, getCode(entry.getKey()), dataField);
161                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
162                    } else {
163                        generateLocationLevel4(oleHoldings, getCode(entry.getKey()), dataField);
164                    }
165                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LOCATION_LEVEL_5)) {
166                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
167                    if (dataField == null) {
168                        dataField = getDataField(entry);
169                        generateLocationLevel5(oleHoldings, getCode(entry.getKey()), dataField);
170                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
171                    } else {
172                        generateLocationLevel5(oleHoldings, getCode(entry.getKey()), dataField);
173                    }
174                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_CALL_NUMBER_TYPE_PREFIX)) {
175                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
176                    if (dataField == null) {
177                        dataField = getDataField(entry);
178                        generateCallNumberPrefix(oleHoldings, getCode(entry.getKey()), dataField);
179                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
180                    } else {
181                        generateCallNumberPrefix(oleHoldings, getCode(entry.getKey()), dataField);
182                    }
183                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LINK_URL)) {
184                    for (Link link : oleHoldings.getLink()) {
185                        DataField dataField1 = getDataField(entry);
186                        generateLink(oleHoldings, link, getCode(entry.getKey()), dataField1);
187                        if (!dataField1.getSubFields().isEmpty()) linkList.add(dataField1);
188                    }
189                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_PERSISTENTLINK)) {
190                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
191                    if (dataField == null) {
192                        dataField = getDataField(entry);
193                        generatePersistentLink(oleHoldings, getCode(entry.getKey()), dataField);
194                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
195                    } else {
196                        generatePersistentLink(oleHoldings, getCode(entry.getKey()), dataField);
197                    }
198                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LINK_TEXT)) {
199                    for (Link link : oleHoldings.getLink()) {
200                        DataField dataField1 = getDataField(entry);
201                        generateLinkText(oleHoldings, link, getCode(entry.getKey()), dataField1);
202                        if (!dataField1.getSubFields().isEmpty()) linkList.add(dataField1);
203                    }
204                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_STATISTICAL_CODE)) {
205                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
206                    if (dataField == null) {
207                        dataField = getDataField(entry);
208                        generateStatisticalCode(oleHoldings, getCode(entry.getKey()), dataField);
209                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
210                    } else {
211                        generateStatisticalCode(oleHoldings, getCode(entry.getKey()), dataField);
212                    }
213                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_ACCESS_STATUS_CODE)) {
214                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
215                    if (dataField == null) {
216                        dataField = getDataField(entry);
217                        generateAccessStatus(oleHoldings, getCode(entry.getKey()), dataField);
218                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
219                    } else {
220                        generateAccessStatus(oleHoldings, getCode(entry.getKey()), dataField);
221                    }
222                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_PLATFORM)) {
223                    dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
224                    if (dataField == null) {
225                        dataField = getDataField(entry);
226                        generatePlatform(oleHoldings, getCode(entry.getKey()), dataField);
227                        if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
228                    } else {
229                        generatePlatform(oleHoldings, getCode(entry.getKey()), dataField);
230                    }
231                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_PUBLIC_DISPLAY_NOTE)) {
232                    for (Note note : oleHoldings.getNote()) {
233                        if (note.getType().equalsIgnoreCase(OLEConstants.NOTE_TYPE)) {
234                            dataField = checkDataField(dataFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
235                            if (dataField == null) {
236                                dataField = getDataField(entry);
237                                generatePublicDisplayNote(oleHoldings, note, getCode(entry.getKey()), dataField);
238                                if (!dataField.getSubFields().isEmpty()) dataFieldList.add(dataField);
239                            } else {
240                                generatePublicDisplayNote(oleHoldings, note, getCode(entry.getKey()), dataField);
241                            }
242                        }
243                    }
244                }
245            }
246            if (!CollectionUtils.isEmpty(dataFieldCoverageMap)) {
247                generateCoverageFields(oleHoldings, dataFieldCoverageMap);
248            }
249            if (!CollectionUtils.isEmpty(linkList)) {
250                dataFieldList.addAll(linkList);
251            }
252            if (!CollectionUtils.isEmpty(dataFieldsDonorMap)) {
253                generateDonorFields(oleHoldings, dataFieldsDonorMap);
254            }
255        } catch (Exception ex) {
256            LOG.error("Error while mapping oleHoldings data ::" + oleHoldings.getHoldingsIdentifier(), ex);
257            buildError(ERR_INSTANCE, oleHoldings.getHoldingsIdentifier(), ERR_CAUSE, ex.getMessage(), TIME_STAMP, new Date().toString());
258            throw ex;
259        }
260    }
261
262    private void generateCoverageFields(OleHoldings oleHoldings, Map<String, String> dataFieldCoverageMap) throws Exception {
263        List<DataField> coverageFieldList = new ArrayList<>();
264        try {
265            if (!CollectionUtils.isEmpty(oleHoldings.getExtentOfOwnership())) {
266                for (ExtentOfOwnership extentOfOwnership : oleHoldings.getExtentOfOwnership()) {
267                    if (null != extentOfOwnership.getCoverages() && !CollectionUtils.isEmpty(extentOfOwnership.getCoverages().getCoverage())) {
268                        for (Coverage coverage : extentOfOwnership.getCoverages().getCoverage()) {
269                            for (Map.Entry<String, String> entry : dataFieldCoverageMap.entrySet()) {
270                                DataField dataField;
271                                if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_COVERAGE_START_DATE)) {
272                                    dataField = checkDataField(coverageFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
273                                    if (dataField == null) {
274                                        dataField = getDataField(entry);
275                                        generateCoverageStartDate(oleHoldings, coverage, getCode(entry.getKey()), dataField);
276                                        if (!dataField.getSubFields().isEmpty()) coverageFieldList.add(dataField);
277                                    } else {
278                                        generateCoverageStartDate(oleHoldings, coverage, getCode(entry.getKey()), dataField);
279                                    }
280                                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_COVERAGE_END_DATE)) {
281                                    dataField = checkDataField(coverageFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
282                                    if (dataField == null) {
283                                        dataField = getDataField(entry);
284                                        generateCoverageEndDate(oleHoldings, coverage, getCode(entry.getKey()), dataField);
285                                        if (!dataField.getSubFields().isEmpty()) coverageFieldList.add(dataField);
286                                    } else {
287                                        generateCoverageEndDate(oleHoldings, coverage, getCode(entry.getKey()), dataField);
288                                    }
289                                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_COVERAGE_START_ISSUE)) {
290                                    dataField = checkDataField(coverageFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
291                                    if (dataField == null) {
292                                        dataField = getDataField(entry);
293                                        generateCoverageStartIssue(oleHoldings, coverage, getCode(entry.getKey()), dataField);
294                                        if (!dataField.getSubFields().isEmpty()) coverageFieldList.add(dataField);
295                                    } else {
296                                        generateCoverageStartIssue(oleHoldings, coverage, getCode(entry.getKey()), dataField);
297                                    }
298                                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_COVERAGE_END_ISSUE)) {
299                                    dataField = checkDataField(coverageFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
300                                    if (dataField == null) {
301                                        dataField = getDataField(entry);
302                                        generateCoverageEndIssue(oleHoldings, coverage, getCode(entry.getKey()), dataField);
303                                        if (!dataField.getSubFields().isEmpty()) coverageFieldList.add(dataField);
304                                    } else {
305                                        generateCoverageEndIssue(oleHoldings, coverage, getCode(entry.getKey()), dataField);
306                                    }
307                                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_COVERAGE_START_VOLUME)) {
308                                    dataField = checkDataField(coverageFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
309                                    if (dataField == null) {
310                                        dataField = getDataField(entry);
311                                        generateCoverageStartVolume(oleHoldings, coverage, getCode(entry.getKey()), dataField);
312                                        if (!dataField.getSubFields().isEmpty()) coverageFieldList.add(dataField);
313                                    } else {
314                                        generateCoverageStartVolume(oleHoldings, coverage, getCode(entry.getKey()), dataField);
315                                    }
316                                } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_COVERAGE_END_VOLUME)) {
317                                    dataField = checkDataField(coverageFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
318                                    if (dataField == null) {
319                                        dataField = getDataField(entry);
320                                        generateCoverageEndVolume(oleHoldings, coverage, getCode(entry.getKey()), dataField);
321                                        if (!dataField.getSubFields().isEmpty()) coverageFieldList.add(dataField);
322                                    } else {
323                                        generateCoverageEndVolume(oleHoldings, coverage, getCode(entry.getKey()), dataField);
324                                    }
325                                }
326                            }
327                            dataFieldList.addAll(coverageFieldList);
328                            coverageFieldList.clear();
329                        }
330                    }
331                }
332            }
333        } catch (Exception ex) {
334            LOG.error("Error while mapping oleHoldings data ::" + oleHoldings.getHoldingsIdentifier(), ex);
335            buildError(ERR_INSTANCE, oleHoldings.getHoldingsIdentifier(), ERR_CAUSE, ex.getMessage(), TIME_STAMP, new Date().toString());
336            throw ex;
337        }
338
339    }
340
341    private void generateDonorFields(OleHoldings oleHoldings, Map<String, String> dataFieldsDonorMap) throws Exception {
342        List<DataField> donorFieldList = new ArrayList<>();
343        try {
344            if (!CollectionUtils.isEmpty(oleHoldings.getDonorInfo())) {
345                for (DonorInfo donorInfo : oleHoldings.getDonorInfo()) {
346                    for (Map.Entry<String, String> entry : dataFieldsDonorMap.entrySet()) {
347                        DataField dataField;
348                        if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_DONOR_PUBLIC_DISPLAY)) {
349                            dataField = checkDataField(donorFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
350                            if (dataField == null) {
351                                dataField = getDataField(entry);
352                                generateDonorPublicDisplay(oleHoldings, donorInfo, getCode(entry.getKey()), dataField);
353                                if (!dataField.getSubFields().isEmpty()) donorFieldList.add(dataField);
354                            } else {
355                                generateDonorPublicDisplay(oleHoldings, donorInfo, getCode(entry.getKey()), dataField);
356                            }
357                        } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_DONOR_NOTE)) {
358                            dataField = checkDataField(donorFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
359                            if (dataField == null) {
360                                dataField = getDataField(entry);
361                                generateDonorNote(oleHoldings, donorInfo, getCode(entry.getKey()), dataField);
362                                if (!dataField.getSubFields().isEmpty()) donorFieldList.add(dataField);
363                            } else {
364                                generateDonorNote(oleHoldings, donorInfo, getCode(entry.getKey()), dataField);
365                            }
366                        } else if (entry.getValue().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_DONOR_CODE)) {
367                            dataField = checkDataField(donorFieldList, StringUtils.trim(entry.getKey()).substring(0, 3));
368                            if (dataField == null) {
369                                dataField = getDataField(entry);
370                                generateDonorCode(oleHoldings, donorInfo, getCode(entry.getKey()), dataField);
371                                if (!dataField.getSubFields().isEmpty()) donorFieldList.add(dataField);
372                            } else {
373                                generateDonorCode(oleHoldings, donorInfo, getCode(entry.getKey()), dataField);
374                            }
375                        }
376                    }
377                    dataFieldList.addAll(donorFieldList);
378                    donorFieldList.clear();
379                }
380            }
381        } catch (Exception ex) {
382            LOG.error("Error while mapping oleHoldings data ::" + oleHoldings.getHoldingsIdentifier(), ex);
383            buildError(ERR_INSTANCE, oleHoldings.getHoldingsIdentifier(), ERR_CAUSE, ex.getMessage(), TIME_STAMP, new Date().toString());
384            throw ex;
385        }
386    }
387
388    protected DataField checkDataField(List<DataField> dataFieldList, String dataField) {
389        for (DataField field : dataFieldList) {
390            if (dataField.equals(field.getTag())) {
391                return field;
392            }
393        }
394        return null;
395    }
396
397    protected DataField getDataField(Map.Entry<String, String> entry) {
398        DataField dataField = new DataField();
399        dataField.setTag(StringUtils.trim(entry.getKey()).substring(0, 3));
400        dataField.setInd1(" ");
401        dataField.setInd2(" ");
402        return dataField;
403    }
404
405    /**
406     * generates the subfields for the given oleHoldings and mapping options
407     *
408     * @param mappingOptionsBoList
409     * @param oleHoldings
410     * @param dataField
411     */
412    protected void generateSubFields(List<OLEBatchProcessProfileDataMappingOptionsBo> mappingOptionsBoList, OleHoldings oleHoldings, DataField dataField) throws Exception {
413        try {
414            for (OLEBatchProcessProfileDataMappingOptionsBo mappingField : mappingOptionsBoList) {
415                if (!mappingField.getDataType().equalsIgnoreCase(OLEConstants.OLEBatchProcess.BATCH_PROCESS_PROFILE_DATATYPE_EHOLDINGS)) continue;
416                if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_CALL_NUMBER)) {
417                    generateCallNumber(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
418                } else if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_HOLDING_CALL_NUMBER_TYPE)) {
419                    generateCallNumberType(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
420                } else if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LOCATION_LEVEL_1)) {
421                    generateLocationLevel1(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
422                } else if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LOCATION_LEVEL_2)) {
423                    generateLocationLevel2(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
424                } else if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LOCATION_LEVEL_3)) {
425                    generateLocationLevel3(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
426                } else if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LOCATION_LEVEL_4)) {
427                    generateLocationLevel4(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
428                } else if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LOCATION_LEVEL_5)) {
429                    generateLocationLevel5(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
430                } else if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_CALL_NUMBER_TYPE_PREFIX)) {
431                    generateCallNumberPrefix(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
432                } else if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LINK_URL)) {
433                    //generateLink(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
434                } else if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_PERSISTENTLINK)) {
435                    generatePersistentLink(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
436                } else if (mappingField.getSourceField().equalsIgnoreCase(OLEConstants.OLEBatchProcess.DESTINATION_FIELD_LINK_TEXT)) {
437                    //generateLinkText(oleHoldings, getCode(mappingField.getDestinationField()), dataField);
438                }
439            }
440        } catch (Exception ex) {
441            LOG.error("Error while mapping oleHoldings data ::" + oleHoldings.getHoldingsIdentifier(), ex);
442            buildError(ERR_INSTANCE, oleHoldings.getHoldingsIdentifier(), ERR_CAUSE, ex.getMessage(), TIME_STAMP, new Date().toString());
443            throw ex;
444        }
445    }
446
447    private void addDataField(DataField dataField, SubField subField) {
448        if (StringUtils.isEmpty(subField.getValue())) return;
449        dataField.getSubFields().add(subField);
450    }
451
452    protected String getTag(String mappingField) {
453        return StringUtils.trim(StringUtils.substringBefore(mappingField, "$"));
454    }
455
456    private String getCode(String mappingField) {
457        return StringUtils.trim(StringUtils.substringAfter(mappingField, "$"));
458    }
459
460    /**
461     * generates the subfields for call number for the given oleHoldings
462     *
463     * @param oleHoldings
464     * @param code
465     * @param dataField
466     */
467    private void generateCallNumber(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
468        SubField subField = new SubField();
469        subField.setCode(code);
470        try {
471            if (oleHoldings != null && oleHoldings.getCallNumber() != null && StringUtils.isNotEmpty(oleHoldings.getCallNumber().getNumber())) {
472                subField.setValue(oleHoldings.getCallNumber().getNumber());
473                addDataField(dataField, subField);
474            }
475        } catch (Exception ex) {
476            logError(oleHoldings, ex, "generateCallNumber()");
477        }
478
479    }
480    /**
481     * generates the call number prefix for the given oleHoldings
482     * @param oleHoldings
483     * @param code
484     * @param dataField
485     * @throws Exception
486     */
487    private void generateCallNumberPrefix(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
488        SubField subField = new SubField();
489        subField.setCode(code);
490        try {
491            if (oleHoldings != null && oleHoldings.getCallNumber() != null && StringUtils.isNotEmpty(oleHoldings.getCallNumber().getPrefix())) {
492                subField.setValue(oleHoldings.getCallNumber().getPrefix());
493                addDataField(dataField, subField);
494            }
495        } catch (Exception ex) {
496            logError(oleHoldings, ex, "generateCallNumberPrefix()");
497        }
498
499    }
500
501    /**
502     * generates the Link for the given oleHoldings
503     * @param oleHoldings
504     * @param code
505     * @param dataField
506     * @throws Exception
507     */
508    private void generateLink(OleHoldings oleHoldings, Link link, String code, DataField dataField) throws Exception {
509        SubField subField = new SubField();
510        subField.setCode(code);
511        try {
512            if (link != null && null != link.getUrl()) {
513                subField.setValue(link.getUrl());
514                addDataField(dataField, subField);
515            }
516        } catch (Exception ex) {
517            logError(oleHoldings, ex, "generateLink()");
518        }
519
520    }
521
522    /**
523     * generates the persistent link for the given oleHoldings
524     * @param oleHoldings
525     * @param code
526     * @param dataField
527     * @throws Exception
528     */
529    private void generatePersistentLink(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
530        SubField subField = new SubField();
531        subField.setCode(code);
532        try {
533            if (oleHoldings != null && oleHoldings.getLocalPersistentLink() != null && StringUtils.isNotEmpty(oleHoldings.getLocalPersistentLink())) {
534                subField.setValue(oleHoldings.getLocalPersistentLink());
535                addDataField(dataField, subField);
536            }
537        } catch (Exception ex) {
538            logError(oleHoldings, ex, "generatePersistentLink()");
539        }
540
541    }
542
543    /**
544     * generates the Link Text for the given oleHoldings
545     * @param oleHoldings
546     * @param code
547     * @param dataField
548     * @throws Exception
549     */
550    private void generateLinkText(OleHoldings oleHoldings,Link link, String code, DataField dataField) throws Exception {
551        SubField subField = new SubField();
552        subField.setCode(code);
553        try {
554            if (link != null && null != link.getText()) {
555                subField.setValue(link.getText());
556                addDataField(dataField, subField);
557            }
558        } catch (Exception ex) {
559            logError(oleHoldings, ex, "generateLinkText()");
560        }
561
562    }
563
564    /**
565     * generates the subfield for the call number type for the given oleHoldings
566     *
567     * @param oleHoldings
568     * @param code
569     * @param dataField
570     */
571    private void generateCallNumberType(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
572        SubField subField = new SubField();
573        subField.setCode(code);
574        try {
575            if (oleHoldings != null && oleHoldings.getCallNumber() != null && oleHoldings.getCallNumber().getShelvingScheme() != null && oleHoldings.getCallNumber().getShelvingScheme().getCodeValue() != null) {
576                subField.setValue(oleHoldings.getCallNumber().getShelvingScheme().getCodeValue());
577                addDataField(dataField, subField);
578            }
579        } catch (Exception ex) {
580            logError(oleHoldings, ex, "generateCallNumberType()");
581        }
582    }
583
584    /**
585     * gets the locationlevel name for the given level and locationlevel
586     *
587     * @param locationLevel
588     * @param level
589     * @return
590     */
591    private String getLocationLevelName(LocationLevel locationLevel, String level) {
592        if (locationLevel == null || StringUtils.isEmpty(locationLevel.getLevel())) return null;
593        if (locationLevel.getLevel().toUpperCase().startsWith(level)) return locationLevel.getName();
594        return getLocationLevelName(locationLevel.getLocationLevel(), level);
595    }
596
597    /**
598     * generates subfield for location level 3 - LIBRARY for the given oleHoldings
599     *
600     * @param oleHoldings
601     * @param code
602     * @param dataField
603     */
604    private void generateLocationLevel3(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
605        String locationLevelName;
606        try {
607            if (oleHoldings != null && oleHoldings.getLocation() != null
608                    && (locationLevelName = getLocationLevelName(oleHoldings.getLocation().getLocationLevel(), "LIBRARY")) != null) {
609                SubField subField = new SubField();
610                subField.setCode(code);
611                subField.setValue(locationLevelName);
612                addDataField(dataField, subField);
613            }
614        } catch (Exception ex) {
615            logError(oleHoldings, ex, "generateLocationLevel3()");
616        }
617    }
618
619    /**
620     * generates subfield for location level 2 - CAMPUS for the given oleHoldings
621     *
622     * @param oleHoldings
623     * @param code
624     * @param dataField
625     * @throws Exception
626     */
627    private void generateLocationLevel2(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
628        String locationLevelName;
629        try {
630            if (oleHoldings != null && oleHoldings.getLocation() != null
631                    && (locationLevelName = getLocationLevelName(oleHoldings.getLocation().getLocationLevel(), "CAMPUS")) != null) {
632                SubField subField = new SubField();
633                subField.setCode(code);
634                subField.setValue(locationLevelName);
635                addDataField(dataField, subField);
636            }
637        } catch (Exception ex) {
638            logError(oleHoldings, ex, "generateLocationLevel2()");
639        }
640    }
641
642    /**
643     * generates subfield for location level 1 - INSTITUTION for the given oleHoldings
644     *
645     * @param oleHoldings
646     * @param code
647     * @param dataField
648     * @throws Exception
649     */
650    private void generateLocationLevel1(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
651        String locationLevelName;
652        try {
653            if (oleHoldings != null && oleHoldings.getLocation() != null
654                    && (locationLevelName = getLocationLevelName(oleHoldings.getLocation().getLocationLevel(), "INSTITUTION")) != null) {
655                SubField subField = new SubField();
656                subField.setCode(code);
657                subField.setValue(locationLevelName);
658                addDataField(dataField, subField);
659            }
660        } catch (Exception ex) {
661            logError(oleHoldings, ex, "generateLocationLevel1()");
662        }
663    }
664
665    /**
666     * generates subfield for location level 5 - SHELVING for the given oleHoldings
667     *
668     * @param oleHoldings
669     * @param code
670     * @param dataField
671     * @throws Exception
672     */
673    private void generateLocationLevel5(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
674        String locationLevelName;
675        try {
676            if (oleHoldings != null && oleHoldings.getLocation() != null
677                    && (locationLevelName = getLocationLevelName(oleHoldings.getLocation().getLocationLevel(), "SHELVING")) != null) {
678                SubField subField = new SubField();
679                subField.setCode(code);
680                subField.setValue(locationLevelName);
681                addDataField(dataField, subField);
682            }
683        } catch (Exception ex) {
684            logError(oleHoldings, ex, "generateLocationLevel5()");
685        }
686    }
687
688    /**
689     * generates the subfields for the location level -4 COLLECTION for the given oleHoldings
690     *
691     * @param oleHoldings
692     * @param code
693     * @param dataField
694     */
695    private void generateLocationLevel4(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
696        String locationLevelName;
697        try {
698            if (oleHoldings != null && oleHoldings.getLocation() != null
699                    && (locationLevelName = getLocationLevelName(oleHoldings.getLocation().getLocationLevel(), "COLLECTION")) != null) {
700                SubField subField = new SubField();
701                subField.setCode(code);
702                subField.setValue(locationLevelName);
703                addDataField(dataField, subField);
704            }
705        } catch (Exception ex) {
706            logError(oleHoldings, ex, "generateLocationLevel4()");
707        }
708
709    }
710
711    /**
712     * generates the subfields for the Statistical Code for the given oleHoldings
713     *
714     * @param oleHoldings
715     * @param code
716     * @param dataField
717     */
718    private void generateStatisticalCode(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
719        try {
720            if (oleHoldings != null && oleHoldings.getStatisticalSearchingCode() != null && oleHoldings.getStatisticalSearchingCode().getCodeValue() != null) {
721                SubField subField = new SubField();
722                subField.setCode(code);
723                subField.setValue(oleHoldings.getStatisticalSearchingCode().getCodeValue());
724                addDataField(dataField, subField);
725            }
726        } catch (Exception ex) {
727            logError(oleHoldings, ex, "generateStatisticalCode()");
728        }
729    }
730
731    /**
732     * generates the subfields for the Access Status for the given oleHoldings
733     *
734     * @param oleHoldings
735     * @param code
736     * @param dataField
737     */
738    private void generateAccessStatus(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
739        try {
740            if (oleHoldings != null && oleHoldings.getAccessStatus() != null) {
741                SubField subField = new SubField();
742                subField.setCode(code);
743                subField.setValue(oleHoldings.getAccessStatus());
744                addDataField(dataField, subField);
745            }
746        } catch (Exception ex) {
747            logError(oleHoldings, ex, "generateAccessStatus()");
748        }
749    }
750
751    /**
752     * generates the subfields for the Platform for the given oleHoldings
753     *
754     * @param oleHoldings
755     * @param code
756     * @param dataField
757     */
758    private void generatePlatform(OleHoldings oleHoldings, String code, DataField dataField) throws Exception {
759        try {
760            if (oleHoldings != null && oleHoldings.getPlatform() != null && null != oleHoldings.getPlatform().getPlatformName()) {
761                SubField subField = new SubField();
762                subField.setCode(code);
763                subField.setValue(oleHoldings.getPlatform().getPlatformName());
764                addDataField(dataField, subField);
765            }
766        } catch (Exception ex) {
767            logError(oleHoldings, ex, "generatePlatform()");
768        }
769    }
770
771    /**
772     * generates the subfields for the Coverage Start Date for the given oleHoldings
773     *
774     * @param oleHoldings
775     * @param code
776     * @param dataField
777     */
778    private void generateCoverageStartDate(OleHoldings oleHoldings, Coverage coverage, String code, DataField dataField) throws Exception {
779        try {
780            if (null != coverage) {
781                SubField subField = new SubField();
782                subField.setCode(code);
783                subField.setValue(coverage.getCoverageStartDate());
784                addDataField(dataField, subField);
785            }
786        } catch (Exception ex) {
787            logError(oleHoldings, ex, "generateCoverageStartDate()");
788        }
789    }
790
791    /**
792     * generates the subfields for the Coverage End Date for the given oleHoldings
793     *
794     * @param oleHoldings
795     * @param code
796     * @param dataField
797     */
798    private void generateCoverageEndDate(OleHoldings oleHoldings, Coverage coverage, String code, DataField dataField) throws Exception {
799        try {
800            if (null != coverage) {
801                SubField subField = new SubField();
802                subField.setCode(code);
803                subField.setValue(coverage.getCoverageEndDate());
804                addDataField(dataField, subField);
805            }
806        } catch (Exception ex) {
807            logError(oleHoldings, ex, "generateCoverageEndDate()");
808        }
809    }
810
811    /**
812     * generates the subfields for the Coverage Start Volume for the given oleHoldings
813     *
814     * @param oleHoldings
815     * @param code
816     * @param dataField
817     */
818    private void generateCoverageStartVolume(OleHoldings oleHoldings, Coverage coverage, String code, DataField dataField) throws Exception {
819        try {
820            if (null != coverage) {
821                SubField subField = new SubField();
822                subField.setCode(code);
823                subField.setValue(coverage.getCoverageStartVolume());
824                addDataField(dataField, subField);
825            }
826        } catch (Exception ex) {
827            logError(oleHoldings, ex, "generateCoverageStartVolume()");
828        }
829    }
830
831    /**
832     * generates the subfields for the Coverage End Volume for the given oleHoldings
833     *
834     * @param oleHoldings
835     * @param code
836     * @param dataField
837     */
838    private void generateCoverageEndVolume(OleHoldings oleHoldings, Coverage coverage, String code, DataField dataField) throws Exception {
839        try {
840            if (null != coverage) {
841                SubField subField = new SubField();
842                subField.setCode(code);
843                subField.setValue(coverage.getCoverageEndVolume());
844                addDataField(dataField, subField);
845            }
846        } catch (Exception ex) {
847            logError(oleHoldings, ex, "generateCoverageEndVolume()");
848        }
849    }
850
851    /**
852     * generates the subfields for the Coverage Start Issue for the given oleHoldings
853     *
854     * @param oleHoldings
855     * @param code
856     * @param dataField
857     */
858    private void generateCoverageStartIssue(OleHoldings oleHoldings, Coverage coverage, String code, DataField dataField) throws Exception {
859        try {
860            if (null != coverage) {
861                SubField subField = new SubField();
862                subField.setCode(code);
863                subField.setValue(coverage.getCoverageStartIssue());
864                addDataField(dataField, subField);
865            }
866        } catch (Exception ex) {
867            logError(oleHoldings, ex, "generateCoverageStartIssue()");
868        }
869    }
870
871    /**
872     * generates the subfields for the Coverage End Issue for the given oleHoldings
873     *
874     * @param oleHoldings
875     * @param code
876     * @param dataField
877     */
878    private void generateCoverageEndIssue(OleHoldings oleHoldings, Coverage coverage, String code, DataField dataField) throws Exception {
879        try {
880            if (null != coverage) {
881                SubField subField = new SubField();
882                subField.setCode(code);
883                subField.setValue(coverage.getCoverageEndIssue());
884                addDataField(dataField, subField);
885            }
886        } catch (Exception ex) {
887            logError(oleHoldings, ex, "generateCoverageEndIssue()");
888        }
889    }
890
891    /**
892     * generates the subfields for the Coverage End Issue for the given oleHoldings
893     *
894     * @param oleHoldings
895     * @param code
896     * @param dataField
897     */
898    private void generatePublicDisplayNote(OleHoldings oleHoldings, Note note, String code, DataField dataField) throws Exception {
899        try {
900            if (null != oleHoldings && null != note) {
901                SubField subField = new SubField();
902                subField.setCode(code);
903                subField.setValue(note.getValue());
904                addDataField(dataField, subField);
905            }
906        } catch (Exception ex) {
907            logError(oleHoldings, ex, "generatePublicDisplayNote()");
908        }
909    }
910
911    /**
912     * generates the subfield for the donor public display for the given EHoldings
913     *
914     * @param oleHoldings
915     * @param code
916     * @param dataField
917     */
918    private void generateDonorPublicDisplay(OleHoldings oleHoldings, DonorInfo donorInfo, String code, DataField dataField) throws Exception {
919        try {
920            if (null != donorInfo) {
921                SubField subField = new SubField();
922                subField.setCode(code);
923                subField.setValue(donorInfo.getDonorPublicDisplay());
924                addDataField(dataField, subField);
925            }
926        } catch (Exception ex) {
927            logError(oleHoldings, ex, "generateDonorPublicDisplay()");
928        }
929    }
930
931    /**
932     * generates the subfield for the donor note for the given EHoldings
933     *
934     * @param oleHoldings
935     * @param code
936     * @param dataField
937     */
938    private void generateDonorNote(OleHoldings oleHoldings, DonorInfo donorInfo, String code, DataField dataField) throws Exception {
939        try {
940            if (null != donorInfo) {
941                SubField subField = new SubField();
942                subField.setCode(code);
943                subField.setValue(donorInfo.getDonorNote());
944                addDataField(dataField, subField);
945            }
946        } catch (Exception ex) {
947            logError(oleHoldings, ex, "generateDonorNote()");
948        }
949    }
950
951    /**
952     * generates the subfield for the donor code for the given EHoldings
953     *
954     * @param oleHoldings
955     * @param code
956     * @param dataField
957     */
958    private void generateDonorCode(OleHoldings oleHoldings, DonorInfo donorInfo, String code, DataField dataField) throws Exception {
959        try {
960            if (null != donorInfo) {
961                SubField subField = new SubField();
962                subField.setCode(code);
963                subField.setValue(donorInfo.getDonorCode());
964                addDataField(dataField, subField);
965            }
966        } catch (Exception ex) {
967            logError(oleHoldings, ex, "generateDonorCode()");
968        }
969    }
970
971    /**
972     * @param errorString
973     */
974    private void buildError(String... errorString) {
975        for (String str : errorString) {
976            errBuilder.append(str).append(COMMA);
977        }
978        errBuilder.append(lineSeparator);
979    }
980
981    /**
982     * Logs error for exception happening for oleHoldings mapping
983     *
984     * @param oleHoldings
985     * @param ex
986     */
987    private void logError(OleHoldings oleHoldings, Exception ex, String method) throws Exception {
988        if (oleHoldings != null) {
989            LOG.error("Error while " + method + " for eholding::" + oleHoldings.getHoldingsIdentifier(), ex);
990            buildError(ERR_HOLDING, oleHoldings.getHoldingsIdentifier(), ERR_CAUSE, ex.getMessage(), " ::At:: ", method, TIME_STAMP, new Date().toString());
991            throw ex;
992        } else {
993            LOG.error("Error while " + method + " for OleHoldings::" + oleHoldings.getHoldingsIdentifier(), ex);
994            throw ex;
995        }
996    }
997}