/* See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * Esri Inc. licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.esri.gpt.catalog.schema.indexable; import com.esri.gpt.catalog.discovery.IStoreable; import com.esri.gpt.catalog.discovery.IStoreables; import com.esri.gpt.catalog.discovery.PropertyMeaning; import com.esri.gpt.catalog.discovery.PropertyMeanings; import com.esri.gpt.catalog.lucene.Storeables; import com.esri.gpt.catalog.schema.EsriTags; import com.esri.gpt.catalog.schema.Meaning; import com.esri.gpt.catalog.schema.Schema; import com.esri.gpt.catalog.schema.indexable.tp.TpAnalyzer; import com.esri.gpt.catalog.search.ResourceIdentifier; import com.esri.gpt.framework.util.Val; import java.util.ArrayList; import org.w3c.dom.Document; /** * Provides a context for the indexing of properties associated with a metadata schema. */ public class IndexableContext { /** instance variables ====================================================== */ private PropertyMeanings propertyMeanings; private ResourceIdentifier resourceIdentifier; private IStoreables storables; /** constructors ============================================================ */ /** * Construct with a configured collection of property meanings. * propertyMeanings the configured property meanings */ public IndexableContext(PropertyMeanings propertyMeanings) { this.propertyMeanings = propertyMeanings; this.storables = new Storeables(this.propertyMeanings,true); } /** properties ============================================================== */ /** * Gets the configured property meanings. * @return the property meanings */ public PropertyMeanings getPropertyMeanings() { return this.propertyMeanings; } /** * Gets storeable properties. * @return the storeable properties */ public IStoreables getStoreables() { return this.storables; } /** methods ================================================================= */ /** * Adds a storeable value. * @param meaning the associated property meaning * @param value the value to add */ public void addStoreableValue(PropertyMeaning meaning, Object value) { if (value != null) { this.addStorableValues(meaning, new Object[]{value}); } } /** * Adds a collection storeable values. * @param meaning the associated property meaning * @param values the values to add */ public void addStorableValues(PropertyMeaning meaning, Object[] values) { if ((meaning != null) && (values != null) && (values.length > 0)) { IStoreable storeable = this.getStoreables().get(meaning.getName()); if (storeable == null) { storeable = this.getStoreables().connect(meaning); if (storeable != null) { ((Storeables)this.getStoreables()).add(storeable); } } if (storeable == null) { // TODO warn } else { Object[] existingValues = storeable.getValues(); if ((existingValues != null) && (existingValues.length > 0)) { java.util.ArrayList<Object> alValues = new ArrayList<Object>(); for (Object value: existingValues) alValues.add(value); for (Object value: values) alValues.add(value); storeable.setValues(alValues.toArray()); } else { storeable.setValues(values); } } } } /** * Ensures the existence of a resource identifier. * @return the resource identifier */ public ResourceIdentifier ensureResourceIdentifier() { if (this.resourceIdentifier == null) { this.resourceIdentifier = ResourceIdentifier.newIdentifier(null); } return this.resourceIdentifier; } /** * Gets the first storeable string value associated with a property meaning name. * @param name the property meaning name * @return the first storeable value (can be null) */ private String getFirstStoreableString(String name) { IStoreable storeable = this.getStoreables().get(name); if (storeable != null) { Object[] values = storeable.getValues(); if ((values != null) && (values.length > 0)) { for (Object value: values) { if ((value != null) && (value instanceof String)) { String sValue = Val.chkStr((String)value); if (sValue.length() > 0) { return sValue; } } } } } return null; } /** * Gets the first storeable value associated with a property meaning name. * @param name the property meaning name * @return the first storeable value (can be null) */ private String getFirstStoreableValue(String name) { IStoreable storeable = this.getStoreables().get(name); if (storeable != null) { Object[] values = storeable.getValues(); if ((values != null) && (values.length > 0) && (values[0] != null)) { return values[0].toString(); } } return null; } /** * Resolves any inconsistencies associated with * @param schema the schema being evaluated * @param dom the metadata document * @param esriTags the evaluated ESRI tags (/metadata/Esri) */ public void resolve(Schema schema, Document dom, EsriTags esriTags) { // check the title String sTitle = Val.chkStr(this.getFirstStoreableString(Meaning.MEANINGTYPE_TITLE)); if (sTitle.length() > 0) { schema.getMeaning().setTitle(sTitle); } // check the file identifier String sFileId = Val.chkStr(this.getFirstStoreableString(Meaning.MEANINGTYPE_FILEIDENTIFIER)); if (sFileId.length() > 0) { schema.getMeaning().setFileIdentifier(sFileId); } // check the thumbnail url String sThumbUrl = Val.chkStr(this.getFirstStoreableString(Meaning.MEANINGTYPE_THUMBNAIL_URL)); if (sThumbUrl.length() > 0) { schema.getMeaning().setThumbnailUrl(sThumbUrl); } // ESRI tags: published doc id if (esriTags != null) { String esriDocID = schema.getMeaning().getEsriDocID(); if ((esriDocID == null) || (esriDocID.length() == 0)) { esriDocID = esriTags.getPublishedDocId(); if ((esriDocID != null) && (esriDocID.length() > 0)) { schema.getMeaning().setEsriDocID(esriDocID); } } } // ESRI tags: thumbnail attachment (base64) if (esriTags != null) { String base64Thumbnail = schema.getMeaning().getThumbnailBinary(); if ((base64Thumbnail == null) || (base64Thumbnail.length() == 0)) { base64Thumbnail = esriTags.getThumbnailBinary(); if ((base64Thumbnail != null) && (base64Thumbnail.length() > 0)) { schema.getMeaning().setThumbnailBinary(base64Thumbnail); } } } // ESRI tags: website URL if (esriTags != null) { String sWebsiteUrl = Val.chkStr(this.getFirstStoreableString(Meaning.MEANINGTYPE_WEBSITE_URL)); if ((sWebsiteUrl == null) || (sWebsiteUrl.length() == 0)) { sWebsiteUrl = esriTags.getPrimaryOnlink(); if ((sWebsiteUrl != null) && (sWebsiteUrl.length() > 0)) { PropertyMeaning meaning = this.getPropertyMeanings().get(Meaning.MEANINGTYPE_WEBSITE_URL); IStoreable storeable = this.getStoreables().get(Meaning.MEANINGTYPE_WEBSITE_URL); if ((meaning != null) && (storeable != null)) { storeable.setValue(sWebsiteUrl); } else if (meaning != null) { this.addStoreableValue(meaning,sWebsiteUrl); } } } } // ESRI tags: resource URL if (esriTags != null) { String sResourceUrl = Val.chkStr(this.getFirstStoreableString(Meaning.MEANINGTYPE_RESOURCE_URL)); if ((sResourceUrl == null) || (sResourceUrl.length() == 0)) { ResourceIdentifier ri = ensureResourceIdentifier(); sResourceUrl = esriTags.makeResourceUrl(ri); if ((sResourceUrl != null) && (sResourceUrl.length() > 0)) { PropertyMeaning meaning = this.getPropertyMeanings().get(Meaning.MEANINGTYPE_RESOURCE_URL); IStoreable storeable = this.getStoreables().get(Meaning.MEANINGTYPE_RESOURCE_URL); if ((meaning != null) && (storeable != null)) { storeable.setValue(sResourceUrl); } else if (meaning != null) { this.addStoreableValue(meaning,sResourceUrl); } } } } // try to determine the resource url String sResourceUrl = Val.chkStr(this.getFirstStoreableString(Meaning.MEANINGTYPE_RESOURCE_URL)); if ((sResourceUrl == null) || (sResourceUrl.length() == 0)) { IStoreable storeable = this.getStoreables().get("resource.check.urls"); if (storeable != null) { Object[] values = storeable.getValues(); if ((values != null) && (values.length > 0)) { boolean resourceUrlResolved = false; ResourceIdentifier ri = ensureResourceIdentifier(); for (Object value: values) { if ((value != null) && (value instanceof String)) { String sValue = Val.chkStr((String)value); if (sValue.length() > 0) { sValue = Val.chkStr(this.resolveResourceUrl(schema,dom,esriTags,sValue)); } if (sValue.length() > 0) { String aimsct = Val.chkStr(ri.guessArcIMSContentTypeFromUrl(sValue)); if (aimsct.length() > 0) { String sResUrl = sValue; PropertyMeaning meaning2 = this.getPropertyMeanings().get(Meaning.MEANINGTYPE_RESOURCE_URL); IStoreable storeable2 = this.getStoreables().get(Meaning.MEANINGTYPE_RESOURCE_URL); if ((meaning2 != null) && (storeable2 != null)) { storeable2.setValue(sResUrl); } else if (meaning2 != null) { this.addStoreableValue(meaning2,sResUrl); } resourceUrlResolved = true; break; } } } } if (!resourceUrlResolved) { // if no resource.url has been resolved - take a first non empty String sResUrl = null; for (Object value: values) { if ((value != null) && (value instanceof String)) { String sValue = Val.chkStr((String)value); if (sValue.length() > 0) { sResUrl = sValue; PropertyMeaning meaning2 = this.getPropertyMeanings().get(Meaning.MEANINGTYPE_RESOURCE_URL); IStoreable storeable2 = this.getStoreables().get(Meaning.MEANINGTYPE_RESOURCE_URL); if ((meaning2 != null) && (storeable2 != null)) { storeable2.setValue(sResUrl); } else if (meaning2 != null) { this.addStoreableValue(meaning2,sResUrl); } break; } } } } } } } // classify the ArcIMS content type from the resource URL String aimsContentType = Val.chkStr(this.getFirstStoreableValue(Meaning.MEANINGTYPE_CONTENTTYPE)); if (aimsContentType.length() > 0) { ResourceIdentifier ri = ensureResourceIdentifier(); aimsContentType = Val.chkStr(ri.guessArcIMSContentTypeFromResourceType(aimsContentType)); } if (aimsContentType.length() == 0) { PropertyMeaning meaning = this.getPropertyMeanings().get(Meaning.MEANINGTYPE_CONTENTTYPE); IStoreable storeable = this.getStoreables().get(Meaning.MEANINGTYPE_RESOURCE_URL); if ((meaning != null) && (storeable != null)) { Object[] values = storeable.getValues(); if (values != null) { for (Object value: values) { if ((value != null) && (value instanceof String)) { String url = Val.chkStr((String)value); if (url.length() > 0) { ResourceIdentifier ri = ensureResourceIdentifier(); aimsContentType = Val.chkStr(ri.guessArcIMSContentTypeFromUrl(url)); if (aimsContentType.length() > 0) { this.addStoreableValue(meaning,aimsContentType); break; } } } } } } } // analyze the time period of the content TpAnalyzer tp = new TpAnalyzer(); tp.analyze(this,schema,dom,sTitle); } /** * Resolves any inconsistencies associated with the resource URL. * @param schema the schema being evaluated * @param dom the metadata document * @param esriTags the evaluated ESRI tags (/metadata/Esri) * @param url the url to check * @return the resolved URL */ private String resolveResourceUrl(Schema schema, Document dom, EsriTags esriTags, String url) { String sUrl = Val.chkStr(url); String sUrlLc = sUrl.toLowerCase(); if (sUrlLc.startsWith("server=http")) { String[] tokens = sUrlLc.split(";"); String sServer = ""; String sService = ""; String sServiceType = ""; for (String token: tokens) { String s = Val.chkStr(token).toLowerCase(); if (s.startsWith("server=http")) { sServer = Val.chkStr(token).substring(7); } else if (s.startsWith("service=")) { sService = Val.chkStr(token).substring(8); } else if (s.startsWith("servicename=")) { sService = Val.chkStr(token).substring(12); } else if (s.equals("servicetype=image")) { sServiceType = "image"; } else if (s.equals("servicetype=feature")) { sServiceType = "feature"; } } if ((sServer.length() > 0) && (sService.length() > 0) && (sServiceType.length() > 0)) { String sEsrimap = "servlet/com.esri.esrimap.Esrimap"; String sResourceUrl = ""; if (sServer.indexOf(sEsrimap) == -1) { if ((sServer.indexOf("?") == -1) && (sServer.indexOf("&") == -1)) { if (!sServer.endsWith("/")) sServer += "/"; if (sService.length() > 0) sResourceUrl = sServer+sEsrimap+"?ServiceName="+sService; } } else { if ((sServer.indexOf("?") == -1) && (sServer.indexOf("&") == -1)) { if (!sServer.endsWith("/")) sServer += "/"; if (sService.length() > 0) sResourceUrl = sServer+"?ServiceName="+sService; } else if (sServer.indexOf("ServiceName=") == -1) { if (sServer.indexOf("?") == -1) { if (!sServer.endsWith("/")) sServer += "/"; sResourceUrl = sServer+"?ServiceName="+sService; } else { sResourceUrl = sServer+"&ServiceName="+sService; } } } if (sResourceUrl.length() > 0) { if (sServiceType.equalsIgnoreCase("image")) { } else if (sServiceType.equalsIgnoreCase("feature")) { //sResourceUrl = ""; } else if (sServiceType.equalsIgnoreCase("metadata")) { //sResourceUrl = ""; } } return sResourceUrl; } else { sServer = Val.chkStr(sUrl).substring(7); if (sServer.endsWith("/com.esri.wms.Esrimap")) { sServer += "?service=WMS&request=GetCapabilities"; } return sServer; } } else if (sUrl.endsWith("/com.esri.wms.Esrimap")) { return sUrl+"?service=WMS&request=GetCapabilities"; } return url; } }