Java tutorial
/* * **************************************************- * Ingrid iPlug SNS * ================================================== * Copyright (C) 2014 - 2015 wemove digital solutions GmbH * ================================================== * Licensed under the EUPL, Version 1.1 or as soon they will be * approved by the European Commission - subsequent versions of the * EUPL (the "Licence"); * * You may not use this work except in compliance with the Licence. * You may obtain a copy of the Licence at: * * http://ec.europa.eu/idabc/eupl5 * * Unless required by applicable law or agreed to in writing, software * distributed under the Licence is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the Licence for the specific language governing permissions and * limitations under the Licence. * **************************************************# */ package de.ingrid.iplug.sns; import java.net.MalformedURLException; import java.net.URL; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.slb.taxi.webservice.xtm.stubs.FieldsType; import com.slb.taxi.webservice.xtm.stubs.SearchType; import com.slb.taxi.webservice.xtm.stubs.TopicMapFragment; import com.slb.taxi.webservice.xtm.stubs.xtm.Association; import com.slb.taxi.webservice.xtm.stubs.xtm.BaseName; import com.slb.taxi.webservice.xtm.stubs.xtm.InstanceOf; import com.slb.taxi.webservice.xtm.stubs.xtm.Member; import com.slb.taxi.webservice.xtm.stubs.xtm.Occurrence; import com.slb.taxi.webservice.xtm.stubs.xtm.Scope; import com.slb.taxi.webservice.xtm.stubs.xtm.Topic; import de.ingrid.external.FullClassifyService; import de.ingrid.external.GazetteerService; import de.ingrid.external.ThesaurusService; import de.ingrid.external.ThesaurusService.MatchingType; import de.ingrid.external.om.Event; import de.ingrid.external.om.FullClassifyResult; import de.ingrid.external.om.Location; import de.ingrid.external.om.RelatedTerm; import de.ingrid.external.om.RelatedTerm.RelationType; import de.ingrid.external.om.Term; import de.ingrid.external.om.Term.TermType; import de.ingrid.external.om.TreeTerm; import de.ingrid.external.sns.SNSClient; import de.ingrid.iplug.sns.utils.DetailedTopic; import de.ingrid.utils.IngridHit; import de.ingrid.utils.tool.SNSUtil; import de.ingrid.utils.tool.SpringUtil; /** * A API to access the main SNS WebService functionality * * created on 29.09.2005 * * @author sg * @version $Revision: 1.2 $ * */ public class SNSController { private static Log log = LogFactory.getLog(SNSController.class); private static final String SNS_INSTANCE_OF_URL = "http://www.semantic-network.de/xmlns/XTM/2005/2.0/sns-classes_2.0.xtm"; private static final String TEMPORAL_TOOccurrence = "temporalToOcc"; private static final String TEMPORAL_FROMOccurrence = "temporalFromOcc"; private static final String TEMPORAL_ATOccurrence = "temporalAtOcc"; private static final SimpleDateFormat expiredDateParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S"); private SNSClient fServiceClient; private final Class<ThesaurusService> _thesaurusService = null; private ThesaurusService thesaurusService; private final Class<GazetteerService> _gazetteerService = null; private GazetteerService gazetteerService; private final Class<FullClassifyService> _fullClassifyService = null; private FullClassifyService fullClassifyService; private static final String[] fTypeFilters = new String[] { "narrowerTermAssoc", "synonymAssoc", "relatedTermsAssoc" }; private static final String[] fAdministrativeTypes = new String[] { "communityType", "districtType", "quarterType", "stateType", "nationType", // extend with newest types ! "use6Type", "use4Type", "use2Type" }; private String fNativeKeyPrefix; /** Can be set from spring/external-services.xml, default is false */ private boolean getLocationsFromText_ignoreCase = false; /** * Constructor for SNS controller. * * @param client * @param nativeKeyPrefix */ public SNSController(SNSClient client, String nativeKeyPrefix) { this.fServiceClient = client; this.fNativeKeyPrefix = nativeKeyPrefix; SpringUtil springUtil = new SpringUtil("spring/external-services.xml"); this.thesaurusService = springUtil.getBean("thesaurusService", _thesaurusService); this.gazetteerService = springUtil.getBean("gazetteerService", _gazetteerService); this.fullClassifyService = springUtil.getBean("fullClassifyService", _fullClassifyService); // change default parameters e.g. query case sensitive or not ! (in GS Soil different than in PortalU) try { final Class<Map> _map = null; Map props = springUtil.getBean("servicesProperties", _map); getLocationsFromText_ignoreCase = new Boolean( (String) props.get("gazetteerService.getLocationsFromText.ignoreCase")); } catch (Exception ex) { if (log.isInfoEnabled()) { log.info("Problems fetching properties from spring/external-services.xml, we use defaults:\n" + "gazetteerService.getLocationsFromText.ignoreCase:" + getLocationsFromText_ignoreCase); } } } /** * For a given term (that should be a thesaurus "descriptor" topic itself !) an array * of associated topics will be returned. * * @param queryTerm The query term. * @param start IGNORED * @param maxResults Limit number of results. * @param plugId The plugId as String. * @param totalSize The quantity of the found topics altogether. * @param lang Is used to specify the preferred language for requests. * @param expired return also expired topics ? IGNORED when calling ThesaurusService API * @param includeUse * @return an array of associated topics or null in case the term itself is not found as topic * @throws Exception */ public synchronized de.ingrid.iplug.sns.utils.Topic[] getTopicsForTerm(String queryTerm, int start, int maxResults, String plugId, int[] totalSize, String lang, boolean expired, boolean includeUse) throws Exception { de.ingrid.iplug.sns.utils.Topic[] result = new de.ingrid.iplug.sns.utils.Topic[0]; de.ingrid.iplug.sns.utils.Topic ingridTopic = getThesaurusDescriptorTopic(queryTerm, totalSize, lang, includeUse, plugId); if (ingridTopic != null) { result = getTopicsForTopic(ingridTopic.getTopicID(), maxResults, "/thesa", plugId, lang, totalSize, expired); } return result; } /** * For a given topic (identified by id) an array of associated topics will be returned.</br> * Calls</br> * <ul> * <li>thesaurusService.getRelatedTermsFromTerm() * <li>gazetteerService.getRelatedLocationsFromLocation * <li>direct autoClassify() * </ul> * dependent from passed filter. * @param topicId The topic given by Id. * @param maxResults Limit number of results. * @param filter Topic type as search criterion * @param plugId The plugId as String * @param totalSize The quantity of the found topics altogether. * @param expired return also expired topics ? IGNORED when calling ThesaurusService / GazetteerService API * @return an array of associated topics for a type identified by id * @throws Exception */ public synchronized de.ingrid.iplug.sns.utils.Topic[] getTopicsForTopic(String topicId, int maxResults, String filter, String plugId, String lang, int[] totalSize, boolean expired) throws Exception { if (log.isDebugEnabled()) { log.debug("getTopicsForTopic: filter=" + filter + ", lang=" + lang); } // TERMS if ("/thesa".equals(filter)) { if (log.isDebugEnabled()) { log.debug(" !!!!!!!!!! calling API thesaurusService.getRelatedTermsFromTerm " + topicId + " " + lang); } RelatedTerm[] terms = thesaurusService.getRelatedTermsFromTerm(topicId, new Locale(lang)); List<de.ingrid.iplug.sns.utils.Topic> resultList = new ArrayList<de.ingrid.iplug.sns.utils.Topic>(); List<String> duplicateList = new ArrayList<String>(); for (RelatedTerm term : terms) { if (!duplicateList.contains(term.getId())) { resultList.add(buildTopicFromRelatedTerm(term, plugId, lang)); duplicateList.add(term.getId()); if (resultList.size() == maxResults) { break; } } } if (resultList.size() > 0) { totalSize[0] = resultList.size(); return resultList.toArray(new de.ingrid.iplug.sns.utils.Topic[resultList.size()]); } // LOCATIONS } else if ("/location".equals(filter)) { return getTopicSimilarLocationsFromTopic(topicId, maxResults, plugId, totalSize, lang); } else { // IS THIS EVER CALLED FOR ANOTHER TOPIC TYPE ? All Topics (filter null) ? Then this is executed. Map associationTypes = new HashMap(); Topic topic = new Topic(); topic.setId(topicId); Topic[] associatedTopics = getAssociatedTopics(topic, fTypeFilters, associationTypes, totalSize, expired); if (associatedTopics != null) { return copyToTopicArray(associatedTopics, associationTypes, maxResults, plugId, "bla"); } } return null; } /** * For a given text an array of detailed topics will be returned (synchronized version). NO FILTER (all topic types !). * * @param searchTerm * The given text to analyze. * @param maxToAnalyzeWords * Analyze only the first maxToAnalyzeWords words of the document in the body. * @param plugId * The plugId as String. * @param lang * Is used to specify the preferred language for requests. * @param totalSize * The quantity of the found topics altogether. * @param expired return also expired topics ? * @return Array of detailed topics for the given text. * @throws Exception */ public synchronized DetailedTopic[] getTopicsForText(String searchTerm, int maxToAnalyzeWords, String plugId, String lang, int[] totalSize, boolean expired) throws Exception { return getTopicsForText(searchTerm, maxToAnalyzeWords, null, plugId, lang, totalSize, expired); } /** For a given text an array of detailed topics will be returned.</br> * Calls</br> * <ul> * <li>thesaurusService.getTermsFromText() * <li>gazetteerService.getLocationsFromText() -> ONLY NON EXPIRED ONES ! * <li>direct autoClassify() * </ul> * dependent from passed filter. * @param documentText The given text to analyze. * @param maxToAnalyzeWords Analyze only the first maxToAnalyzeWords words of the document in the body. * @param filter Topic type as search criterion (only root paths may be used). * @param plugId The plugId as String. * @param lang Is used to specify the preferred language for requests. * @param totalSize The quantity of the found topics altogether. * @param expired return also expired topics ? IGNORED ! expired attribute only set in SNS * location topics. There we call Gazetteer API which always filters expired ones (SNS) ! * Was also filtered before introducing Gazetteer API. * @return array of detailed topics for the given text * @throws Exception */ public DetailedTopic[] getTopicsForText(String documentText, int maxToAnalyzeWords, String filter, String plugId, String lang, int[] totalSize, boolean expired) throws Exception { if (log.isDebugEnabled()) { log.debug("getTopicsForText: filter=" + filter + ", lang=" + lang); } DetailedTopic[] result = new DetailedTopic[0]; // TERMS if ("/thesa".equals(filter)) { if (log.isDebugEnabled()) { log.debug(" !!!!!!!!!! calling API thesaurusService.getTermsFromText " + lang); } Term[] terms = thesaurusService.getTermsFromText(documentText, maxToAnalyzeWords, true, new Locale(lang)); if (terms != null) { totalSize[0] = terms.length; result = toDetailedTopicArray(terms, plugId, lang); } // LOCATIONS } else if ("/location".equals(filter)) { if (log.isDebugEnabled()) { log.debug(" !!!!!!!!!! calling API gazetteerService.findLocationsFromQueryTerm " + lang); } // use find method, since autoClassify is not supported by WFS and the given text // normally should be a single word // Location[] locations = gazetteerService.getLocationsFromText(documentText, maxToAnalyzeWords, // getLocationsFromText_ignoreCase, new Locale(lang)); Location[] locations = gazetteerService.findLocationsFromQueryTerm(documentText, null, de.ingrid.external.GazetteerService.MatchingType.CONTAINS, new Locale(lang)); if (locations != null) { totalSize[0] = locations.length; result = toDetailedTopicArray(locations, plugId, lang); } } else { // IS THIS EVER CALLED FOR ANOTHER TOPIC TYPE ? Event ? All Topics (filter null) ? Then this is executed. // NOTICE: we may always execute this with according filter !!! but let's keep the old structure de.ingrid.external.FullClassifyService.FilterType filterType = getFullClassifyFilterType(filter); if (log.isDebugEnabled()) { log.debug( " !!!!!!!!!! calling API fullClassifyService.autoClassifyText " + filter + " " + lang); } FullClassifyResult classifyResult = fullClassifyService.autoClassifyText(documentText, maxToAnalyzeWords, false, filterType, new Locale(lang)); if (classifyResult != null) { result = toDetailedTopicArray(classifyResult, plugId, lang); totalSize[0] = result.length; } } return result; } /** * For a given URL an array of detailed topics will be returned. * NOTICE: Returns only NON EXPIRED topics. * * @param urlStr The given url to analyze. * @param maxToAnalyzeWords Analyze only the first maxToAnalyzeWords words of the document in the body. * @param filter Topic type as search criterion (only root paths may be used). * @param plugId The plugId as String. * @param lang Is used to specify the preferred language for requests. * @param totalSize The quantity of the found topics altogether. * @return array of detailed topics for the given text * @throws Exception */ public DetailedTopic[] getTopicsForURL(String urlStr, int maxToAnalyzeWords, String filter, String plugId, String lang, int[] totalSize) throws Exception { if (log.isDebugEnabled()) { log.debug("getTopicsForURL: " + urlStr + ", filter=" + filter + ", lang=" + lang); } URL url = createURL(urlStr); de.ingrid.external.FullClassifyService.FilterType filterType = getFullClassifyFilterType(filter); if (log.isDebugEnabled()) { log.debug(" !!!!!!!!!! calling API fullClassifyService.autoClassifyURL " + url + " " + filter + " " + lang); } FullClassifyResult classifyResult = fullClassifyService.autoClassifyURL(url, maxToAnalyzeWords, false, filterType, new Locale(lang)); DetailedTopic[] result = new DetailedTopic[0]; if (classifyResult != null) { result = toDetailedTopicArray(classifyResult, plugId, lang); totalSize[0] = result.length; } return result; } /** * For a given topic ID the detailed topic will be returned in an array. * @param topicID the id of the topic * @param filter Topic type as search criterion (only root paths may be used). * @param plugId The plugId as String. * @param lang Is used to specify the preferred language for requests. * @param totalSize The quantity of the found topics altogether (is 1 !) * @return array of detailed topics for the given topic id (should be size 1, if problems is size 0 * @throws Exception */ public DetailedTopic[] getTopicForId(String topicID, String filter, String plugId, String lang, int[] totalSize) throws Exception { if (log.isDebugEnabled()) { log.debug("getTopicForId: " + topicID + ", filter=" + filter + ", lang=" + lang); } DetailedTopic detailedTopic = getTopicDetail(topicID, filter, lang, plugId); DetailedTopic[] result = new DetailedTopic[0]; if (detailedTopic != null) { result = new DetailedTopic[] { detailedTopic }; totalSize[0] = 1; } return result; } /** * @return An array of ingrid detailed topics from a Term array. */ private DetailedTopic[] toDetailedTopicArray(Term[] terms, String plugId, String lang) { final List<DetailedTopic> returnList = new ArrayList<DetailedTopic>(); for (Term term : terms) { if (term.getType() != TermType.DESCRIPTOR) { continue; } returnList.add(buildDetailedTopicFromTerm(term, plugId, lang)); } return returnList.toArray(new DetailedTopic[returnList.size()]); } /** * @return An array of ingrid detailed topics from a Location array. */ private DetailedTopic[] toDetailedTopicArray(Location[] locations, String plugId, String lang) { final List<DetailedTopic> returnList = new ArrayList<DetailedTopic>(); for (Location location : locations) { // GSSoil Gazetteer delivers null locations and names !? if (location == null || location.getName() == null) { continue; } returnList.add(buildDetailedTopicFromLocation(location, plugId, lang)); } return returnList.toArray(new DetailedTopic[returnList.size()]); } /** * @return An array of ingrid detailed topics from an Event array. */ private DetailedTopic[] toDetailedTopicArray(Event[] events, String plugId, String lang) { final List<DetailedTopic> returnList = new ArrayList<DetailedTopic>(); for (Event event : events) { returnList.add(buildDetailedTopicFromEvent(event, plugId, lang)); } return returnList.toArray(new DetailedTopic[returnList.size()]); } /** * @return An array of ingrid detailed topics from a result of a full classification. */ private DetailedTopic[] toDetailedTopicArray(FullClassifyResult classifyResult, String plugId, String lang) { final List<DetailedTopic> returnList = new ArrayList<DetailedTopic>(); DetailedTopic[] topics; List<Term> classifyTerms = classifyResult.getTerms(); if (classifyTerms != null && classifyTerms.size() > 0) { topics = toDetailedTopicArray(classifyTerms.toArray(new Term[classifyTerms.size()]), plugId, lang); if (topics.length > 0) { returnList.addAll(Arrays.asList(topics)); } } List<Location> classifyLocations = classifyResult.getLocations(); if (classifyLocations != null && classifyLocations.size() > 0) { topics = toDetailedTopicArray(classifyLocations.toArray(new Location[classifyLocations.size()]), plugId, lang); if (topics.length > 0) { returnList.addAll(Arrays.asList(topics)); } } List<Event> classifyEvents = classifyResult.getEvents(); if (classifyEvents != null && classifyEvents.size() > 0) { topics = toDetailedTopicArray(classifyEvents.toArray(new Event[classifyEvents.size()]), plugId, lang); if (topics.length > 0) { returnList.addAll(Arrays.asList(topics)); } } return returnList.toArray(new DetailedTopic[returnList.size()]); } /** * Build a detailed metadata index for a given topic. * * @param topic * A given topic. * @param plugId * The plugId as String * @param lang * Is used to specify the preferred language for requests. * @return A detailed topic from Topic. */ private synchronized DetailedTopic buildDetailedTopicFromTopic(Topic topic, String plugId, String lang) { String topicId = topic.getId(); BaseName[] bn = topic.getBaseName(); String title = ""; for (int i = 0; i < bn.length; i++) { final String href = bn[i].getScope().getTopicRef()[0].getHref(); if (href.endsWith('#' + lang)) { title = bn[i].getBaseNameString().get_value(); break; } } // SNS workaround ! sometimes SNS delivers english title tagged as german ("language.xtm#de" in scope) // we always take the last title found, this can be german (if NO english title) or english (if // english title tagged as german, normally the last one !) if (title.isEmpty() && bn.length > 0) { title = bn[bn.length - 1].getBaseNameString().get_value(); } String summary = title + ' ' + topic.getInstanceOf()[0].getTopicRef().getHref(); DetailedTopic metaData = new DetailedTopic(plugId, topicId.hashCode(), topicId, title, summary, null); InstanceOf[] instanceOfs = topic.getInstanceOf(); for (int i = 0; i < instanceOfs.length; i++) { String href = instanceOfs[i].getTopicRef().getHref(); metaData.addToList(DetailedTopic.INSTANCE_OF, href); } pushTimes(metaData, topic); pushDefinitions(metaData, topic, lang); pushSamples(metaData, topic, lang); pushOccurensie(DetailedTopic.DESCRIPTION_OCC, topic, metaData, lang); pushOccurensie(DetailedTopic.ASSOCIATED_OCC, topic, metaData, lang); pushOccurensie(DetailedTopic.GEMET_OCC, topic, metaData, lang); pushOccurensie(de.ingrid.iplug.sns.utils.Topic.NATIVEKEY_OCC, topic, metaData, lang); String topicNativeKey = metaData.getTopicNativeKey(); if (null != topicNativeKey) { metaData.setTopicNativeKey(SNSUtil.transformSpacialReference(this.fNativeKeyPrefix, topicNativeKey)); } else { metaData.setTopicNativeKey(topicId); } if (containsTypes(fAdministrativeTypes, topic.getInstanceOf()[0].getTopicRef().getHref())) { metaData.setAdministrativeID(topic.getId()); } return metaData; } /** Build A detailed topic from Event. * NOTICE: NO MAPPING OF ASSOCIATED TERMS YET !!!!!! */ private synchronized DetailedTopic buildDetailedTopicFromEvent(Event event, String plugId, String lang) { String topicId = event.getId(); String title = event.getTitle(); String snsInstanceOf = getSNSInstanceOf(event); String summary = title + ' ' + snsInstanceOf; DetailedTopic result = new DetailedTopic(plugId, topicId.hashCode(), topicId, title, summary, null); result.addToList(DetailedTopic.INSTANCE_OF, snsInstanceOf); // we push the stuff which IS ALWAYS ADDED, even if empty // NOTICE: Further this converts the DetailedTopic to an IngridDocument !!!!? pushDefinitions(result, null, lang); pushSamples(result, null, lang); // NO TERM ASSOCIATIONS MAPPED in EVENT SO FAR !!! // pushOccurensie(DetailedTopic.ASSOCIATED_OCC, topic, metaData, lang); result.put(DetailedTopic.DESCRIPTION_OCC, event.getDescription()); if (event.getTimeAt() != null) { String at = getSNSDateString(event.getTimeAt()); result.setFrom(at); result.setTo(at); } else { result.setFrom(getSNSDateString(event.getTimeRangeFrom())); result.setTo(getSNSDateString(event.getTimeRangeTo())); } return result; } /** Build A detailed topic from Location */ private synchronized DetailedTopic buildDetailedTopicFromLocation(Location location, String plugId, String lang) { String topicId = location.getId(); String title = location.getName(); String snsInstanceOf = getSNSInstanceOf(location); String summary = title + ' ' + snsInstanceOf; DetailedTopic result = new DetailedTopic(plugId, topicId.hashCode(), topicId, title, summary, null); result.addToList(DetailedTopic.INSTANCE_OF, snsInstanceOf); // we push the stuff which IS ALWAYS ADDED, even if empty // NOTICE: Further this converts the DetailedTopic to an IngridDocument !!!!? pushDefinitions(result, null, lang); pushSamples(result, null, lang); if (location.getNativeKey() != null) { result.setTopicNativeKey( SNSUtil.transformSpacialReference(this.fNativeKeyPrefix, location.getNativeKey())); } else { result.setTopicNativeKey(topicId); } // if administrative location, also set topic id as administrative id !? String locationType = location.getTypeId(); for (String adminType : fAdministrativeTypes) { if (adminType.equals(locationType)) { result.setAdministrativeID(topicId); break; } } // NO BBox !!!? was never delivered ! return result; } /** Build A detailed topic from Term */ private synchronized DetailedTopic buildDetailedTopicFromTerm(Term term, String plugId, String lang) { String topicId = term.getId(); String title = term.getName(); String snsInstanceOf = getSNSInstanceOf(term); String summary = title + ' ' + snsInstanceOf; DetailedTopic result = new DetailedTopic(plugId, topicId.hashCode(), topicId, title, summary, null); result.addToList(DetailedTopic.INSTANCE_OF, snsInstanceOf); // we push the stuff which IS ALWAYS ADDED, even if empty // NOTICE: Further this converts the DetailedTopic to an IngridDocument !!!!? pushDefinitions(result, null, lang); pushSamples(result, null, lang); pushGemetDataFromTerm(result, term); result.setTopicNativeKey(topicId); return result; } /** If GEMET data set in term, adapt topic */ private void pushGemetDataFromTerm(de.ingrid.iplug.sns.utils.Topic topic, Term term) { if (term.getAlternateId() != null) { String gemetOcc = term.getAlternateId() + "@" + term.getName(); topic.put(DetailedTopic.GEMET_OCC, gemetOcc); // UMTHES name in AlternateName ! if (term.getAlternateName() != null) { topic.setTopicName(term.getAlternateName()); } } } private void pushDefinitions(DetailedTopic metaData, Topic topic, String lang) { List titles = new ArrayList(); List definitions = new ArrayList(); Occurrence[] occurrences = null; if (topic != null) { occurrences = topic.getOccurrence(); } if (occurrences != null) { String type = null; for (int i = 0; i < occurrences.length; i++) { if (occurrences[i].getInstanceOf() != null) { // Only compare the scope to the language if the element has one set. String scope = '#' + lang; if (occurrences[i].getScope() != null) { scope = occurrences[i].getScope().getTopicRef(0).getHref(); } type = occurrences[i].getInstanceOf().getTopicRef().getHref(); if (type.endsWith(DetailedTopic.DESCRIPTION_OCC) && occurrences[i].getResourceRef() != null && scope.endsWith('#' + lang)) { definitions.add(occurrences[i].getResourceRef().getHref().toString()); titles.add(occurrences[i].getResourceRef().getTitle()); } } } } metaData.setDefinitions((String[]) definitions.toArray(new String[definitions.size()])); metaData.setDefinitionTitles((String[]) titles.toArray(new String[titles.size()])); } private void pushSamples(DetailedTopic metaData, Topic topic, String lang) { List titles = new ArrayList(); List samples = new ArrayList(); Occurrence[] occurrences = null; if (topic != null) { occurrences = topic.getOccurrence(); } if (occurrences != null) { String type = null; for (int i = 0; i < occurrences.length; i++) { if (occurrences[i].getInstanceOf() != null) { // Only compare the scope to the language if the element has one set. String scope = '#' + lang; if (occurrences[i].getScope() != null) { scope = occurrences[i].getScope().getTopicRef(0).getHref(); } type = occurrences[i].getInstanceOf().getTopicRef().getHref(); if (type.endsWith(DetailedTopic.SAMPLE_OCC) && occurrences[i].getResourceRef() != null && scope.endsWith('#' + lang)) { samples.add(occurrences[i].getResourceRef().getHref().toString()); titles.add(occurrences[i].getResourceRef().getTitle()); } } } } metaData.setSamples((String[]) samples.toArray(new String[samples.size()])); metaData.setSampleTitles((String[]) titles.toArray(new String[titles.size()])); } /** * Pushs the time data in to the detailed topic. * * @param metaData * The detailed topic for which the time data should be set. * @param topic * A given topic. */ private void pushTimes(DetailedTopic metaData, Topic topic) { Occurrence[] occurrences = null; if (topic != null) { occurrences = topic.getOccurrence(); } if (occurrences != null) { String type = null; for (int i = 0; i < occurrences.length; i++) { if (occurrences[i].getInstanceOf() != null) { type = occurrences[i].getInstanceOf().getTopicRef().getHref(); if (type.endsWith(TEMPORAL_ATOccurrence)) { final String at = occurrences[i].getResourceData().get_value(); metaData.setFrom(at); metaData.setTo(at); break; } if (type.endsWith(TEMPORAL_FROMOccurrence)) { metaData.setFrom(occurrences[i].getResourceData().get_value()); } if (type.endsWith(TEMPORAL_TOOccurrence)) { metaData.setTo(occurrences[i].getResourceData().get_value()); } } } } } private synchronized void pushOccurensie(String occType, Topic topic, de.ingrid.iplug.sns.utils.Topic detailedTopic, String lang) { Occurrence[] occurrences = null; if (topic != null) { occurrences = topic.getOccurrence(); } if (occurrences != null) { String type = null; for (int i = 0; i < occurrences.length; i++) { if (occurrences[i].getInstanceOf() != null) { // Only compare the scope to the language if the element has one set. String scope = '#' + lang; if (occurrences[i].getScope() != null) { scope = occurrences[i].getScope().getTopicRef(0).getHref(); } type = occurrences[i].getInstanceOf().getTopicRef().getHref(); if (type.endsWith(occType) && occurrences[i].getResourceData() != null && scope.endsWith('#' + lang)) { detailedTopic.put(occType, occurrences[i].getResourceData().get_value()); } } } } } /** * @param topic * @param plugId * @param associationType * @param lang * @return A ingrid topic from a Topic. */ private synchronized de.ingrid.iplug.sns.utils.Topic buildTopicFromTopic(Topic topic, String plugId, String associationType, String lang) { BaseName[] baseNames = topic.getBaseName(); // Set a default if for the selected language nothing exists. String title = baseNames[0].getBaseNameString().get_value(); String topicLang = "en"; for (int i = 0; i < baseNames.length; i++) { final Scope scope = baseNames[i].getScope(); if (scope != null) { final String href = scope.getTopicRef()[0].getHref(); if (href.endsWith('#' + lang)) { title = baseNames[i].getBaseNameString().get_value(); topicLang = lang; break; } } } String summary = title + ' ' + topic.getInstanceOf()[0].getTopicRef().getHref(); String topicId = topic.getId(); de.ingrid.iplug.sns.utils.Topic result = new de.ingrid.iplug.sns.utils.Topic(plugId, topicId.hashCode(), topicId, title, summary, associationType, null); pushOccurensie(de.ingrid.iplug.sns.utils.Topic.NATIVEKEY_OCC, topic, result, lang); pushOccurensie(DetailedTopic.GEMET_OCC, topic, result, lang); String topicNativeKey = result.getTopicNativeKey(); if (null != topicNativeKey) { String ags = SNSUtil.transformSpacialReference(this.fNativeKeyPrefix, topicNativeKey); if (ags.startsWith("lawa:")) { ags = SNSUtil.transformSpacialReference("lawa:", topicNativeKey); } result.setTopicNativeKey(ags); } else { result.setTopicNativeKey(topicId); } result.setLanguage(topicLang); return result; } /** * @return A ingrid topic from a Term. */ private de.ingrid.iplug.sns.utils.Topic buildTopicFromTerm(Term term, String plugId, String lang) { String title = term.getName(); String summary = title + ' ' + getSNSInstanceOf(term); String topicId = term.getId(); String associationType = ""; de.ingrid.iplug.sns.utils.Topic result = new de.ingrid.iplug.sns.utils.Topic(plugId, topicId.hashCode(), topicId, title, summary, associationType, null); pushGemetDataFromTerm(result, term); result.setLanguage(lang); return result; } /** * @return A ingrid topic from a Location. */ private de.ingrid.iplug.sns.utils.Topic buildTopicFromLocation(Location location, String plugId, String lang) { String title = location.getName(); String summary = title + ' ' + getSNSInstanceOf(location); String topicId = location.getId(); String associationType = ""; de.ingrid.iplug.sns.utils.Topic result = new de.ingrid.iplug.sns.utils.Topic(plugId, topicId.hashCode(), topicId, title, summary, associationType, null); if (location.getNativeKey() != null) { String ags = SNSUtil.transformSpacialReference(this.fNativeKeyPrefix, location.getNativeKey()); if (ags.startsWith("lawa:")) { ags = SNSUtil.transformSpacialReference("lawa:", location.getNativeKey()); } result.setTopicNativeKey( SNSUtil.transformSpacialReference(this.fNativeKeyPrefix, location.getNativeKey())); } else { result.setTopicNativeKey(topicId); } result.setLanguage(lang); return result; } /** * Also adds children OR parents as successors to ingrid topic ! * @param addParentsAsSuccessors true = the parents of the passed term are added * as successors to the topic (recursively)</br> * false = the children of passed term are added as successors * @return A ingrid topic from a TreeTerm. Also sets up successors in topic ! */ private de.ingrid.iplug.sns.utils.Topic buildTopicFromTreeTerm(TreeTerm term, String plugId, String lang, boolean addParentsAsSuccessors) { de.ingrid.iplug.sns.utils.Topic resultTopic = buildTopicFromTerm(term, plugId, lang); // add children or parents as successors dependent from flag List<TreeTerm> successorTerms = term.getChildren(); if (addParentsAsSuccessors) { successorTerms = term.getParents(); } if (successorTerms != null) { for (TreeTerm successorTerm : successorTerms) { de.ingrid.iplug.sns.utils.Topic successorTopic = buildTopicFromTreeTerm(successorTerm, plugId, lang, addParentsAsSuccessors); resultTopic.addSuccessor(successorTopic); } } return resultTopic; } /** * Also adds relation information to ingrid topic ! * @return A ingrid topic from a RelatedTerm. Also sets up relation info in topic ! */ private de.ingrid.iplug.sns.utils.Topic buildTopicFromRelatedTerm(RelatedTerm term, String plugId, String lang) { de.ingrid.iplug.sns.utils.Topic resultTopic = buildTopicFromTerm(term, plugId, lang); // add association type dependent from relation String memberType = getSNSAssociationMemberType(term); resultTopic.setTopicAssoc(memberType); return resultTopic; } private String getSNSDateString(Date date) { if (date == null) { return null; } SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); return dateFormat.format(date); } /** Extract SNS instanceOf href from event ! */ private static String getSNSInstanceOf(Event event) { return SNS_INSTANCE_OF_URL + "#" + event.getTypeId(); } /** Extract SNS instanceOf href from location ! */ private static String getSNSInstanceOf(Location location) { return SNS_INSTANCE_OF_URL + "#" + location.getTypeId(); } /** Extract SNS instanceOf href from term ! */ private static String getSNSInstanceOf(Term term) { // unknown term types are handled as top terms ! String snsInstanceOf = "#topTermType"; // first check whether we have a tree term ! Only then we can determine whether top node ! boolean determined = false; if (TreeTerm.class.isAssignableFrom(term.getClass())) { if (((TreeTerm) term).getParents() == null) { snsInstanceOf = "#topTermType"; determined = true; } } if (!determined) { TermType termType = term.getType(); if (termType == TermType.NODE_LABEL) { snsInstanceOf = "#nodeLabelType"; } else if (termType == TermType.DESCRIPTOR) { snsInstanceOf = "#descriptorType"; } else if (termType == TermType.NON_DESCRIPTOR) { snsInstanceOf = "#nonDescriptorType"; } } return SNS_INSTANCE_OF_URL + snsInstanceOf; } /** Extract SNS assoziation member type from related term ! */ private static String getSNSAssociationMemberType(RelatedTerm term) { // default is synonym member type) String snsMemberType = "#synonymMember"; RelationType relationType = term.getRelationType(); if (relationType == RelationType.CHILD) { snsMemberType = "#narrowerTermMember"; } else if (relationType == RelationType.PARENT) { snsMemberType = "#widerTermMember"; } else if (relationType == RelationType.RELATIVE) { // check type of term ! if (term.getType() == TermType.DESCRIPTOR) { snsMemberType = "#descriptorMember"; } else { snsMemberType = "#synonymMember"; } } return SNS_INSTANCE_OF_URL + snsMemberType; } /** * @param baseTopic * @param typePattern * @param associationTypes * @param totalSize * @param expired return also expired topics ? * @return Topic array of associated topics filter by the given patterns * @throws Exception */ private Topic[] getAssociatedTopics(Topic baseTopic, String[] typePattern, Map associationTypes, int[] totalSize, boolean expired) throws Exception { List resultList = new ArrayList(); final TopicMapFragment mapFragment = this.fServiceClient.getPSI(baseTopic.getId(), 1, null); final Topic[] topics = mapFragment.getTopicMap().getTopic(); if (null != mapFragment.getListExcerpt()) { if (null != mapFragment.getListExcerpt().getTotalSize()) { totalSize[0] = mapFragment.getListExcerpt().getTotalSize().intValue(); } } final Association[] associations = mapFragment.getTopicMap().getAssociation(); // iterate through associations to find the correct association types if (associations != null) { for (int i = 0; i < associations.length; i++) { final Association association = associations[i]; // association type final String assocType = association.getInstanceOf().getTopicRef().getHref(); if (containsTypes(typePattern, assocType)) { // association members are the basetopic and it association final Member[] members = association.getMember(); for (int j = 0; j < members.length; j++) { final Member member = members[j]; // here is only the topic id available final String topicId = member.getTopicRef()[0].getHref(); final String assocMember = member.getRoleSpec().getTopicRef().getHref(); if (!topicId.equals(baseTopic.getId())) { final Topic topicById = getTopicById(topics, topicId); if (topicById != null) { if (!expired) { Date expiredDate = getExpiredDate(topicById); if ((null != expiredDate) && expiredDate.before(new Date())) { continue; } } if (null != associationTypes) { associationTypes.put(topicById.getId(), assocMember); } resultList.add(topicById); } } } } } return (Topic[]) resultList.toArray(new Topic[resultList.size()]); } return null; } /** * @param topics * @param topicId * @return the topic that match the topicId from the given Topic array */ private Topic getTopicById(Topic[] topics, String topicId) { for (int k = 0; k < topics.length; k++) { if (topicId.equals(topics[k].getId())) { return topics[k]; } } return null; } /** * ATTENTION: This method had a bug when using the old controller before introducing the ThesaurusService API ! * top and label topics were treated as descriptors !!! But not non descriptor topics ! * WE STILL SIMULATE THIS BUG HERE !!! Cause don't know where this query is called ! * @return just one matching topic, in case more topics match we return the FIRST ONE ! If no topic match we return null. * @throws Exception */ private de.ingrid.iplug.sns.utils.Topic getThesaurusDescriptorTopic(String queryTerm, int[] totalSize, String lang, boolean includeUse, String plugId) throws Exception { if (log.isDebugEnabled()) { log.debug("getTopic: " + queryTerm + ", lang=" + lang); } if (log.isDebugEnabled()) { log.debug(" !!!!!!!!!! calling API thesaurusService.findTermsFromQueryTerm: " + queryTerm + " ... " + lang); } Term[] terms = thesaurusService.findTermsFromQueryTerm(queryTerm, MatchingType.EXACT, includeUse, new Locale(lang)); // filter terms. Same name ! // NOTICE: old findTopics call before integration of API was // findTopics(queryTerm, "/thesa/descriptor", SearchType.exact, FieldsType.names, offSet, lang, includeUse); // Although "/thesa/descriptor" is passed, SNS returns also a top topic (Hydrosphre - Wasser und Gewsser) // or a label topic (Wasser) BUT FILTERS non decriptor topics (Waldsterben) ! // further the returned topic name matches the passed queryTerm, BUT CASE INSENSITIVE ! // check here: http://www.semantic-network.de/doc_findtopics.html?lang=de List<Term> filteredTerms = new ArrayList<Term>(); List<String> duplicateList = new ArrayList<String>(); for (Term term : terms) { // NO ! Not only descriptors ! see above ! // if (term.getType() != TermType.DESCRIPTOR) { // continue; // } // filter non descriptors, see above ! if (term.getType() == TermType.NON_DESCRIPTOR) { continue; } // CASE INSENSITIVE, see above ! if (!term.getName().equalsIgnoreCase(queryTerm)) { continue; } if (duplicateList.contains(term.getId())) { continue; } filteredTerms.add(term); duplicateList.add(term.getId()); } // RETURN FIRST TOPIC ! de.ingrid.iplug.sns.utils.Topic result = null; if (filteredTerms.size() > 0) { result = buildTopicFromTerm(filteredTerms.get(0), plugId, lang); totalSize[0] = 1; } return result; } /** * @param patterns * @param pattern * @return true in case the pattern is one of the given patterns */ private boolean containsTypes(String[] patterns, String pattern) { for (int i = 0; i < patterns.length; i++) { if (pattern.endsWith(patterns[i])) { return true; } } return false; } /** * @param maxResults * @param topics * @param associationTypes * @param plugId * @param lang * @return An array of Topic with the given length. * @throws Exception */ private de.ingrid.iplug.sns.utils.Topic[] copyToTopicArray(Topic[] topics, Map associationTypes, int maxResults, String plugId, String lang) throws Exception { final List ingridTopics = new ArrayList(); final List duplicateList = new ArrayList(); if (null != topics) { int count = Math.min(maxResults, topics.length); for (int i = 0; i < count; i++) { final String topicId = topics[i].getId(); if (!duplicateList.contains(topicId)) { if (!topicId.startsWith("_Interface")) { String associationType = ""; if ((null != associationTypes) && (associationTypes.containsKey(topicId))) { associationType = (String) associationTypes.get(topicId); } ingridTopics.add(buildTopicFromTopic(topics[i], plugId, associationType, lang)); } duplicateList.add(topicId); } } } return (de.ingrid.iplug.sns.utils.Topic[]) ingridTopics .toArray(new de.ingrid.iplug.sns.utils.Topic[ingridTopics.size()]); } /** * @return ingrid Topics from Terms. */ private de.ingrid.iplug.sns.utils.Topic[] copyToTopicArray(Term[] terms, int maxResults, String plugId, String lang) throws Exception { final List<de.ingrid.iplug.sns.utils.Topic> ingridTopics = new ArrayList<de.ingrid.iplug.sns.utils.Topic>(); final List<String> duplicateList = new ArrayList<String>(); if (null != terms) { int count = Math.min(maxResults, terms.length); for (int i = 0; i < count; i++) { final String topicId = terms[i].getId(); if (!duplicateList.contains(topicId)) { ingridTopics.add(buildTopicFromTerm(terms[i], plugId, lang)); duplicateList.add(topicId); } } } return (de.ingrid.iplug.sns.utils.Topic[]) ingridTopics .toArray(new de.ingrid.iplug.sns.utils.Topic[ingridTopics.size()]); } /** * @return ingrid Topics from Locations. */ private de.ingrid.iplug.sns.utils.Topic[] copyToTopicArray(Location[] locations, int maxResults, String plugId, String lang) throws Exception { final List<de.ingrid.iplug.sns.utils.Topic> ingridTopics = new ArrayList<de.ingrid.iplug.sns.utils.Topic>(); final List<String> duplicateList = new ArrayList<String>(); if (null != locations) { int count = Math.min(maxResults, locations.length); for (int i = 0; i < count; i++) { final String topicId = locations[i].getId(); // GSSoil Gazetteer delivers null locations and names !? if (locations[i] == null || locations[i].getName() == null) { continue; } if (!duplicateList.contains(topicId)) { ingridTopics.add(buildTopicFromLocation(locations[i], plugId, lang)); duplicateList.add(topicId); } } } return (de.ingrid.iplug.sns.utils.Topic[]) ingridTopics .toArray(new de.ingrid.iplug.sns.utils.Topic[ingridTopics.size()]); } /** * Search for a given date events of an requested event type. * * @param searchTerm * The search term. * @param eventTypes * Array with one or more types of events. * @param atDate * A date at which an event occured. * @param start * Defines the number of elements to skip. * @param length * Number of elements that should be retrieved. * @param plugId * The plugId as String. * @param totalSize * Has the total size of the query set after the call. * @param lang * Is used to specify the preferred language for requests. * @return A topic array of events. * @throws Exception */ public de.ingrid.iplug.sns.utils.Topic[] getEventFromTopic(String searchTerm, String[] eventTypes, String atDate, int start, int length, String plugId, int[] totalSize, String lang) throws Exception { de.ingrid.iplug.sns.utils.Topic[] result = new de.ingrid.iplug.sns.utils.Topic[0]; String[] eventPath = null; if (null != eventTypes) { eventPath = new String[eventTypes.length]; for (int i = 0; i < eventPath.length; i++) { eventPath[i] = "/event/" + eventTypes[i] + '/'; } } else { eventPath = new String[] { "/event/" }; } // now always "contains" like default on http://www.semantic-network.de/doc_findevents.html?lang=de SearchType searchType = SearchType.contains; /* SearchType searchType = SearchType.exact; if ((null == searchTerm) || (searchTerm.trim().equals(""))) { searchType = SearchType.contains; } */ TopicMapFragment topicMapFragment = this.fServiceClient.findEvents(searchTerm, true, searchType, eventPath, FieldsType.captors, start, atDate, lang, length); Topic[] topic = topicMapFragment.getTopicMap().getTopic(); totalSize[0] = topicMapFragment.getListExcerpt().getTotalSize().intValue(); if (topic != null) { de.ingrid.iplug.sns.utils.Topic[] topics = copyToTopicArray(topic, null, length, plugId, lang); result = topics; } return result; } /** * Returns all similar terms to a term. * * @param searchTerm * The given search term. * @param length * Number of elements that should be retrieved. * @param plugId * The plugId as String. * @param totalSize * The total size of the query set after the call. * @param lang * Is used to specify the preferred language for requests. * @return Topics to similar terms. * @throws Exception */ public de.ingrid.iplug.sns.utils.Topic[] getSimilarTermsFromTopic(String searchTerm, int length, String plugId, int[] totalSize, String lang) throws Exception { return getSimilarTermsFromTopic(new String[] { searchTerm }, length, plugId, totalSize, lang); } /** Calls thesaurusService.getSimilarTermsFromNames ! * @param searchTerm The given search term(s) * @param length Number of elements that should be retrieved. * @param plugId The plugId as String. * @param totalSize IGNORED * @param lang Is used to specify the preferred language for requests. * @return Topics to similar terms. * @throws Exception */ public de.ingrid.iplug.sns.utils.Topic[] getSimilarTermsFromTopic(String[] searchTerm, int length, String plugId, int[] totalSize, String lang) throws Exception { if (log.isDebugEnabled()) { log.debug("getSimilarTermsFromTopic: searchTerm[]=" + searchTerm + ", lang=" + lang); } if (log.isDebugEnabled()) { log.debug(" !!!!!!!!!! calling API thesaurusService.getSimilarTermsFromNames: " + searchTerm + " ... " + lang); } Term[] terms = thesaurusService.getSimilarTermsFromNames(searchTerm, true, new Locale(lang)); de.ingrid.iplug.sns.utils.Topic[] result = new de.ingrid.iplug.sns.utils.Topic[0]; if (terms != null) { result = copyToTopicArray(terms, length, plugId, lang); } return result; } /** * Returns all anniversaries to a date. * * @param searchTerm * The given search term. * @param length * Number of elements that should be retrieved. * @param plugId * The plugId as String. * @param totalSize * The total size of the query set after the call. * @return Topics to an anniversary. * @throws Exception */ public de.ingrid.iplug.sns.utils.Topic[] getAnniversaryFromTopic(String searchTerm, int length, String plugId, int[] totalSize) throws Exception { de.ingrid.iplug.sns.utils.Topic[] result = new de.ingrid.iplug.sns.utils.Topic[0]; TopicMapFragment topicMapFragment = this.fServiceClient.anniversary(searchTerm); Topic[] topic = topicMapFragment.getTopicMap().getTopic(); totalSize[0] = topicMapFragment.getListExcerpt().getTotalSize().intValue(); if (topic != null) { de.ingrid.iplug.sns.utils.Topic[] topics = copyToTopicArray(topic, null, length, plugId, "bla"); result = topics; } return result; } /** * Returns all events between two dates. * * @param searchTerm * The given search term. * @param eventTypes * Array with one or more types of events. * @param fromDate * A date after that an event occured. * @param toDate * A date before an event occured. * @param start * Defines the number of elements to skip. * @param length * Number of elements that should be retrieved. * @param plugId * The plugId as String. * @param totalSize * Has the total size of the query set after the call. * @param lang * Is used to specify the preferred language for requests. * @return Topics to an event. * @throws Exception */ public de.ingrid.iplug.sns.utils.Topic[] getEventFromTopic(String searchTerm, String[] eventTypes, String fromDate, String toDate, int start, int length, String plugId, int[] totalSize, String lang) throws Exception { de.ingrid.iplug.sns.utils.Topic[] result = new de.ingrid.iplug.sns.utils.Topic[0]; String[] eventPath = null; if (null != eventTypes) { eventPath = new String[eventTypes.length]; for (int i = 0; i < eventPath.length; i++) { eventPath[i] = "/event/" + eventTypes[i] + '/'; } } else { eventPath = new String[] { "/event/" }; } // now always "contains" like default on http://www.semantic-network.de/doc_findevents.html?lang=de SearchType searchType = SearchType.contains; /* SearchType searchType = SearchType.exact; if ((null == searchTerm) || (searchTerm.trim().equals(""))) { searchType = SearchType.contains; } */ TopicMapFragment topicMapFragment = this.fServiceClient.findEvents(searchTerm, true, searchType, eventPath, FieldsType.captors, start, fromDate, toDate, lang, length); Topic[] topic = topicMapFragment.getTopicMap().getTopic(); totalSize[0] = topicMapFragment.getListExcerpt().getTotalSize().intValue(); if (topic != null) { de.ingrid.iplug.sns.utils.Topic[] topics = copyToTopicArray(topic, null, length, plugId, lang); result = topics; } return result; } /** * Deliver for a given hit the detailed topic description. * * @param hit * The hit, for which further information should received. * @param lang * Is used to specify the preferred language for requests. * @return A detailed topic. * @throws Exception */ public DetailedTopic getTopicDetail(IngridHit hit, String lang) throws Exception { return getTopicDetail(hit, null, lang); } /** * Get detailed information for a hit.</br> * Calls</br> * <ul> * <li>thesaurusService.getTerm() * <li>gazetterService.getLocation() * <li>direct getPSI()() * </ul> * dependent from passed filter. * @param hit The hit, for which further information should received. * @param filter Topic type as search criterion (only root paths shall be used). * @param lang Is used to specify the preferred language for requests. * @return A detailed topic to a filter. * @throws Exception */ public DetailedTopic getTopicDetail(IngridHit hit, String filter, String lang) throws Exception { de.ingrid.iplug.sns.utils.Topic topic = (de.ingrid.iplug.sns.utils.Topic) hit; return getTopicDetail(topic.getTopicID(), filter, lang, hit.getPlugId()); } /** * Get detailed information for topic identified by its id.</br> * Calls</br> * <ul> * <li>thesaurusService.getTerm() * <li>gazetterService.getLocation() * <li>direct getPSI()() * </ul> * dependent from passed filter. * @param topicID The id of the topic for which further information should received. * @param filter Topic type as search criterion (only root paths shall be used). * @param lang Is used to specify the preferred language for requests. * @param plugId the plug id to be added to detail * @return A detailed topic to a filter. * @throws Exception */ private DetailedTopic getTopicDetail(String topicID, String filter, String lang, String plugId) throws Exception { if (log.isDebugEnabled()) { log.debug("getTopicDetail: topicID=" + topicID + ", filter=" + filter + ", lang=" + lang); } DetailedTopic result = null; // TERMS if ("/thesa".equals(filter)) { if (log.isDebugEnabled()) { log.debug(" !!!!!!!!!! calling API thesaurusService.getTerm: " + topicID + " " + lang); } Term term = thesaurusService.getTerm(topicID, new Locale(lang)); if (term != null) { result = buildDetailedTopicFromTerm(term, plugId, lang); } // LOCATIONS } else if ("/location".equals(filter)) { if (log.isDebugEnabled()) { log.debug(" !!!!!!!!!! calling API gazetteerService.getLocation: " + topicID + " " + lang); } Location location = gazetteerService.getLocation(topicID, new Locale(lang)); if (location != null) { result = buildDetailedTopicFromLocation(location, plugId, lang); } } else { // filter: "/event" or null TopicMapFragment mapFragment = null; try { mapFragment = this.fServiceClient.getPSI(topicID, 0, filter); } catch (Exception e) { log.error("Error calling snsClient.getPSI (topicId=" + topicID + ", filter=" + filter + "), we return null Details", e); } if (null != mapFragment) { Topic[] topics = mapFragment.getTopicMap().getTopic(); for (int i = 0; i < topics.length; i++) { if (topics[i].getId().equals(topicID)) { result = buildDetailedTopicFromTopic(topics[0], plugId, lang); } } } } return result; } /** * Find for a given topic similar locations. ONLY NON EXPIRED ONES !!! * Calls gazetteerService.getRelatedLocationsFromLocation(). * @param topicId The topic given by Id. * @param length Number of elements that should be retrieved. * @param plugId The plugId as string. * @param totalSize Has the total size of the query set after the call. * @param lang Is used to specify the preferred language for requests. * @return A topic array from similar location topics (NOT EXPIRED) or null ! * @throws Exception */ public de.ingrid.iplug.sns.utils.Topic[] getTopicSimilarLocationsFromTopic(String topicId, int length, String plugId, int[] totalSize, String lang) throws Exception { de.ingrid.iplug.sns.utils.Topic[] result = null; if (log.isDebugEnabled()) { log.debug(" !!!!!!!!!! calling API gazetteerService.getRelatedLocationsFromLocation" + topicId + " " + lang); } Location[] locations = gazetteerService.getRelatedLocationsFromLocation(topicId, true, new Locale(lang)); if (locations.length > 0) { totalSize[0] = locations.length; result = copyToTopicArray(locations, length, plugId, lang); } return result; } private Date getExpiredDate(Topic topic) { Date result = null; Occurrence[] occurrences = topic.getOccurrence(); if (null != occurrences) { for (int i = 0; i < occurrences.length; i++) { final InstanceOf instanceOf = occurrences[i].getInstanceOf(); if (instanceOf != null) { final String type = instanceOf.getTopicRef().getHref(); if (type.endsWith("expiredOcc")) { try { result = expiredDateParser.parse(occurrences[i].getResourceData().get_value()); } catch (ParseException e) { log.error("Not expected date format in sns expiredOcc.", e); } } } } } return result; } /** Calls thesaurusService dependent from passed direction and map results to ingrid Topics. * Never includesSiblings ! Never filters expired topics ! * @param totalSize IGNORED * @param associationName IGNORED * @param depth IGNORED * @param direction "down" -> thesaurusService.getHierarchyNextLevel(...), depth 2</br> * "up" -> thesaurusService.getHierarchyPathToTop(...), depth 0 (to top)</br> * @param includeSiblings IGNORED, always false * @param lang the language (e.g. "de") * @param root id of root topic (start topic) * @param expired return also expired topics ? IGNORED, expired topics are always removed * @param plugId the plug id needed for setup of Topics * @return structure of ingrid topics * @throws Exception */ public de.ingrid.iplug.sns.utils.Topic[] getTopicHierachy(int[] totalSize, String associationName, long depth, String direction, boolean includeSiblings, String lang, String root, boolean expired, String plugId) throws Exception { if (log.isDebugEnabled()) { log.debug("getTopicHierachy: topicID=" + root + ", direction=" + direction + ", lang=" + lang); } List<de.ingrid.iplug.sns.utils.Topic> resultList = new ArrayList<de.ingrid.iplug.sns.utils.Topic>(); if ("down".equals(direction)) { String topicId = root; if ("toplevel".equals(root)) { topicId = null; } // never with siblings, always depth 2 ! if (log.isDebugEnabled()) { log.debug(" !!!!!!!!!! calling API thesaurusService.getHierarchyNextLevel: " + topicId + " " + lang); } TreeTerm[] childTerms = thesaurusService.getHierarchyNextLevel(topicId, new Locale(lang)); if (log.isDebugEnabled()) { log.debug("num childTerms: " + childTerms.length); } // set up root topic encapsulating children // NOTICE: default is null ! If no children ! Evaluated in Test. de.ingrid.iplug.sns.utils.Topic rootTopic = null; if (topicId == null) { // toplevel nodes, we create dummy parent rootTopic = new de.ingrid.iplug.sns.utils.Topic(plugId, -1, root, null, null, null, null); } else { // start node is existing topic if (childTerms.length > 0) { // there are children ! Every child encapsulates its parent (root). rootTopic = buildTopicFromTerm(childTerms[0].getParents().get(0), plugId, lang); } } resultList.add(rootTopic); // set up children structure for (TreeTerm childTerm : childTerms) { de.ingrid.iplug.sns.utils.Topic childTopic = buildTopicFromTreeTerm(childTerm, plugId, lang, false); rootTopic.addSuccessor(childTopic); } } else { // never with siblings ! if (log.isDebugEnabled()) { log.debug( " !!!!!!!!!! calling API thesaurusService.getHierarchyPathToTop: " + root + " " + lang); } TreeTerm startTerm = thesaurusService.getHierarchyPathToTop(root, new Locale(lang)); // set up root topic encapsulating parents as successors // NOTICE: default is null ! If no parents ! Evaluated in Test. de.ingrid.iplug.sns.utils.Topic rootTopic = null; // start node is existing topic if (startTerm.getParents() != null) { // we have parents ! build topic structure with parents as successors ! rootTopic = buildTopicFromTreeTerm(startTerm, plugId, lang, true); } resultList.add(rootTopic); } return resultList.toArray(new de.ingrid.iplug.sns.utils.Topic[resultList.size()]); } /** Create URL from url String. Returns null if problems !!! */ private URL createURL(String urlStr) throws MalformedURLException { URL url = null; try { url = new URL(urlStr); } catch (MalformedURLException ex) { log.warn("Error building URL " + urlStr, ex); throw ex; } return url; } /** Determine FullClassifyService.FilterType from passed SNS filter. */ private de.ingrid.external.FullClassifyService.FilterType getFullClassifyFilterType(String filterStr) { de.ingrid.external.FullClassifyService.FilterType filterType = null; if ("/thesa".equals(filterStr)) { filterType = de.ingrid.external.FullClassifyService.FilterType.ONLY_TERMS; } else if ("/location".equals(filterStr)) { filterType = de.ingrid.external.FullClassifyService.FilterType.ONLY_LOCATIONS; } else if ("/event".equals(filterStr)) { filterType = de.ingrid.external.FullClassifyService.FilterType.ONLY_EVENTS; } return filterType; } }