You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sdap.apache.org by le...@apache.org on 2017/10/27 22:41:47 UTC

[10/15] incubator-sdap-edge git commit: SDAP-1 Import all code under the SDAP SGA

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/granule/iso/iso_template.xml
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/granule/iso/iso_template.xml b/src/main/python/plugins/granule/iso/iso_template.xml
new file mode 100644
index 0000000..f5cd340
--- /dev/null
+++ b/src/main/python/plugins/granule/iso/iso_template.xml
@@ -0,0 +1,674 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gmd:DS_Series xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.isotc211.org/2005/gmd http://www.ngdc.noaa.gov/metadata/published/xsd/schema.xsd" xmlns:gmd="http://www.isotc211.org/2005/gmd" xmlns:gco="http://www.isotc211.org/2005/gco" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:gml="http://www.opengis.net/gml" xmlns:gsr="http://www.isotc211.org/2005/gsr" xmlns:gss="http://www.isotc211.org/2005/gss" xmlns:gts="http://www.isotc211.org/2005/gts" xmlns:gmx="http://www.isotc211.org/2005/gmx" xmlns:gmi="http://www.isotc211.org/2005/gmi">
+{% if granules %}
+<gmd:composedOf>
+<gmd:DS_DataSet>
+<gmd:has>
+<gmi:MI_Metadata>
+<gmd:fileIdentifier>
+<gco:CharacterString>{{ granules[0]['Granule-Name'][0] }}</gco:CharacterString>
+</gmd:fileIdentifier>
+<gmd:contact xlink:href="#seriesMetadataContact"/>
+<gmd:dateStamp>
+<gco:DateTime>{{ granules[0]['Granule-CreateTimeLong'][0] }}</gco:DateTime>
+</gmd:dateStamp>
+<gmd:dataSetURI>
+<gco:CharacterString>{{ granules[0]['link'] }}</gco:CharacterString>
+</gmd:dataSetURI>
+<gmd:identificationInfo>
+<gmd:MD_DataIdentification>
+<gmd:citation>
+<gmd:CI_Citation>
+<gmd:title>
+<gco:CharacterString>{{ granules[0]['Granule-Name'][0] }}</gco:CharacterString>
+</gmd:title>
+<gmd:date>
+<gmd:CI_Date>
+<gmd:date>
+<gco:DateTime>{{ granules[0]['Granule-ArchiveTimeLong'][0] }}</gco:DateTime>
+</gmd:date>
+<gmd:dateType>
+<gmd:CI_DateTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="publication">publication</gmd:CI_DateTypeCode>
+</gmd:dateType>
+</gmd:CI_Date>
+</gmd:date>
+</gmd:CI_Citation>
+</gmd:citation>
+<gmd:abstract/>
+<gmd:language/>
+<gmd:extent>
+<gmd:EX_Extent>
+<gmd:geographicElement>
+<gmd:EX_GeographicBoundingBox id="swathBoundingBox">
+{% if GranuleBoundingBox %}
+<gmd:westBoundLongitude>
+<gco:Decimal>{{ GranuleBoundingBox['westernmostLongitude'] }}</gco:Decimal>
+</gmd:westBoundLongitude>
+<gmd:eastBoundLongitude>
+<gco:Decimal>{{ GranuleBoundingBox['easternmostLongitude'] }}</gco:Decimal>
+</gmd:eastBoundLongitude>
+<gmd:southBoundLatitude>
+<gco:Decimal>{{ GranuleBoundingBox['southernmostLatitude'] }}</gco:Decimal>
+</gmd:southBoundLatitude>
+<gmd:northBoundLatitude>
+<gco:Decimal>{{ GranuleBoundingBox['northernmostLatitude'] }}</gco:Decimal>
+</gmd:northBoundLatitude>
+{% else %}
+<gmd:westBoundLongitude>
+<gco:Decimal>-180.00</gco:Decimal>
+</gmd:westBoundLongitude>
+<gmd:eastBoundLongitude>
+<gco:Decimal>180.00</gco:Decimal>
+</gmd:eastBoundLongitude>
+<gmd:southBoundLatitude>
+<gco:Decimal>-90.00</gco:Decimal>
+</gmd:southBoundLatitude>
+<gmd:northBoundLatitude>
+<gco:Decimal>90.00</gco:Decimal>
+</gmd:northBoundLatitude>
+{% endif %}
+</gmd:EX_GeographicBoundingBox>
+</gmd:geographicElement>
+<gmd:temporalElement>
+<gmd:EX_TemporalExtent>
+<gmd:extent>
+<TimePeriod xmlns="http://www.opengis.net/gml/3.2" xmlns:ns1="http://www.opengis.net/gml/3.2" ns1:id="swathTemporalExtent">
+<beginPosition>{{ granules[0]['Granule-StartTimeLong'][0] }}</beginPosition>
+<endPosition>{{ granules[0]['Granule-StopTimeLong'][0] }}</endPosition>
+</TimePeriod>
+</gmd:extent>
+</gmd:EX_TemporalExtent>
+</gmd:temporalElement>
+</gmd:EX_Extent>
+</gmd:extent>
+</gmd:MD_DataIdentification>
+</gmd:identificationInfo>
+</gmi:MI_Metadata>
+</gmd:has>
+</gmd:DS_DataSet>
+</gmd:composedOf>
+{% endif %}
+{% if doc %}
+<gmd:seriesMetadata>
+<gmi:MI_Metadata id="{{ doc['Dataset-ShortName'][0] }}">
+<gmd:fileIdentifier>
+<gco:CharacterString>{{ doc['Dataset-ShortName'][0] }}</gco:CharacterString>
+</gmd:fileIdentifier>
+<gmd:language>
+<gco:CharacterString>eng</gco:CharacterString>
+</gmd:language>
+<gmd:characterSet>
+<gmd:MD_CharacterSetCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_CharacterSetCode" codeListValue="UTF8">UTF8</gmd:MD_CharacterSetCode>
+</gmd:characterSet>
+<gmd:hierarchyLevel>
+<gmd:MD_ScopeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_ScopeCode" codeListValue="series">series</gmd:MD_ScopeCode>
+</gmd:hierarchyLevel>
+<gmd:contact>
+<gmd:CI_ResponsibleParty id="seriesMetadataContact">
+<gmd:individualName>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-FirstName'][0] }}{% if doc['DatasetContact-Contact-MiddleName'][0] != 'none' %} {{ doc['DatasetContact-Contact-MiddleName'][0] }}{% endif %} {{ doc['DatasetContact-Contact-LastName'][0] }}</gco:CharacterString>
+</gmd:individualName>
+<gmd:organisationName>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-Provider-ShortName'][0] }} &gt; {{ doc['DatasetContact-Contact-Provider-LongName'][0] }}</gco:CharacterString>
+</gmd:organisationName>
+<gmd:positionName>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-Role'][0] }}</gco:CharacterString>
+</gmd:positionName>
+<gmd:contactInfo>
+<gmd:CI_Contact>
+<gmd:phone>
+<gmd:CI_Telephone>
+<gmd:voice>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-Phone'][0] }}</gco:CharacterString>
+</gmd:voice>
+<gmd:facsimile>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-Fax'][0] }}</gco:CharacterString>
+</gmd:facsimile>
+</gmd:CI_Telephone>
+</gmd:phone>
+<gmd:address>
+<gmd:CI_Address>
+<gmd:electronicMailAddress>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-Email'][0] }}</gco:CharacterString>
+</gmd:electronicMailAddress>
+</gmd:CI_Address>
+</gmd:address>
+<gmd:contactInstructions>
+<gco:CharacterString>Phone/FAX/E-mail</gco:CharacterString>
+</gmd:contactInstructions>
+</gmd:CI_Contact>
+</gmd:contactInfo>
+<gmd:role>
+<gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="pointOfContact">pointOfContact</gmd:CI_RoleCode>
+</gmd:role>
+</gmd:CI_ResponsibleParty>
+</gmd:contact>
+<gmd:dateStamp>
+<gco:Date>{{ DateStamp }}</gco:Date>
+</gmd:dateStamp>
+<gmd:metadataStandardName>
+<gco:CharacterString>ISO 19115-2 Geographic information — Metadata — Part 2: Extensions for imagery and gridded data</gco:CharacterString>
+</gmd:metadataStandardName>
+<gmd:metadataStandardVersion>
+<gco:CharacterString>ISO 19115-2:2009-02-15</gco:CharacterString>
+</gmd:metadataStandardVersion>
+<gmd:locale>
+<gmd:PT_Locale>
+<gmd:languageCode>
+<gmd:LanguageCode codeList="http://www.loc.gov/standards/iso639-2/php/English_list.php" codeListValue="eng">eng</gmd:LanguageCode>
+</gmd:languageCode>
+<gmd:country>
+<gmd:Country codeList="http://www.iso.org/iso/iso_3166-1_list_en.zip" codeListValue="US">US</gmd:Country>
+</gmd:country>
+<gmd:characterEncoding>
+<gmd:MD_CharacterSetCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_CharacterSetCode" codeListValue="UTF8">UTF8</gmd:MD_CharacterSetCode>
+</gmd:characterEncoding>
+</gmd:PT_Locale>
+</gmd:locale>
+<gmd:metadataExtensionInfo>
+<gmd:MD_MetadataExtensionInformation>
+<gmd:extensionOnLineResource>
+<gmd:CI_OnlineResource>
+<gmd:linkage>
+<gmd:URL>http://www.ngdc.noaa.gov/metadata/published/19115/GHRSST/ISO/CoverageExtensions.xml</gmd:URL>
+</gmd:linkage>
+<gmd:applicationProfile>
+<gco:CharacterString>Web Browser</gco:CharacterString>
+</gmd:applicationProfile>
+<gmd:description>
+<gco:CharacterString>A description of extensions developed at NGDC to classify coverages.</gco:CharacterString>
+</gmd:description>
+<gmd:function>
+<gmd:CI_OnLineFunctionCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_OnlineFunctionCode" codeListValue="information">information</gmd:CI_OnLineFunctionCode>
+</gmd:function>
+</gmd:CI_OnlineResource>
+</gmd:extensionOnLineResource>
+</gmd:MD_MetadataExtensionInformation>
+</gmd:metadataExtensionInfo>
+<gmd:identificationInfo>
+<gmd:MD_DataIdentification id="seriesIdentification">
+<gmd:citation>
+<gmd:CI_Citation>
+<gmd:title>
+<gco:CharacterString>{{ doc['Dataset-LongName'][0] }}</gco:CharacterString>
+</gmd:title>
+<gmd:alternateTitle>
+<gco:CharacterString>{{ doc['DatasetCitation-Title'][0] }}</gco:CharacterString>
+</gmd:alternateTitle>
+<gmd:date>
+<gmd:CI_Date>
+<gmd:date>
+<gco:Date>{{ DatasetCitation_ReleaseDate }}</gco:Date>
+</gmd:date>
+<gmd:dateType>
+<gmd:CI_DateTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_DateTypeCode" codeListValue="creation">creation</gmd:CI_DateTypeCode>
+</gmd:dateType>
+</gmd:CI_Date>
+</gmd:date>
+<gmd:edition>
+<gco:CharacterString>{{ doc['DatasetCitation-Version'][0] }}</gco:CharacterString>
+</gmd:edition>
+<gmd:citedResponsibleParty>
+<gmd:CI_ResponsibleParty>
+<gmd:individualName>
+<gco:CharacterString>{{ doc['DatasetCitation-Creator'][0] }}</gco:CharacterString>
+</gmd:individualName>
+<gmd:contactInfo>
+<gmd:CI_Contact>
+{% if (doc['DatasetCitation-OnlineResource'][0] | trim)[0:4] == 'http' or (doc['DatasetCitation-OnlineResource'][0] | trim)[0:3] == 'ftp' %}
+<gmd:onlineResource>
+<gmd:CI_OnlineResource>
+<gmd:linkage>
+<gmd:URL>{{ doc['DatasetCitation-OnlineResource'][0] }}</gmd:URL>
+</gmd:linkage>
+</gmd:CI_OnlineResource>
+</gmd:onlineResource>
+{% else %}
+<gmd:onlineResource gco:nilReason="missing"/>
+{% endif %}
+</gmd:CI_Contact>
+</gmd:contactInfo>
+<gmd:role>
+<gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="originator">originator</gmd:CI_RoleCode>
+</gmd:role>
+</gmd:CI_ResponsibleParty>
+</gmd:citedResponsibleParty>
+<gmd:citedResponsibleParty>
+<gmd:CI_ResponsibleParty>
+<gmd:organisationName>
+<gco:CharacterString>{{ doc['DatasetCitation-Publisher'][0] }}</gco:CharacterString>
+</gmd:organisationName>
+<gmd:contactInfo>
+<gmd:CI_Contact>
+<gmd:address>
+<gmd:CI_Address>
+<gmd:city>
+<gco:CharacterString>{{ doc['DatasetCitation-ReleasePlace'][0] }}</gco:CharacterString>
+</gmd:city>
+</gmd:CI_Address>
+</gmd:address>
+</gmd:CI_Contact>
+</gmd:contactInfo>
+<gmd:role>
+<gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="publisher">publisher</gmd:CI_RoleCode>
+</gmd:role>
+</gmd:CI_ResponsibleParty>
+</gmd:citedResponsibleParty>
+</gmd:CI_Citation>
+</gmd:citation>
+<gmd:abstract>
+<gco:CharacterString>{{ doc['Dataset-Description'][0] }}</gco:CharacterString>
+</gmd:abstract>
+<gmd:credit>
+<gco:CharacterString>{{ doc['DatasetCitation-CitationDetail'][0] }}</gco:CharacterString>
+</gmd:credit>
+<gmd:status>
+<gmd:MD_ProgressCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_ProgressCode" codeListValue="onGoing">onGoing</gmd:MD_ProgressCode>
+</gmd:status>
+<gmd:pointOfContact>
+<gmd:CI_ResponsibleParty>
+<gmd:individualName>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-FirstName'][0] }}{% if doc['DatasetContact-Contact-MiddleName'][0] != 'none' %} {{ doc['DatasetContact-Contact-MiddleName'][0] }}{% endif %} {{ doc['DatasetContact-Contact-LastName'][0] }}</gco:CharacterString>
+</gmd:individualName>
+<gmd:organisationName>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-Provider-ShortName'][0] }} &gt; {{ doc['DatasetContact-Contact-Provider-LongName'][0] }}</gco:CharacterString>
+</gmd:organisationName>
+<gmd:contactInfo>
+<gmd:CI_Contact>
+<gmd:phone>
+<gmd:CI_Telephone>
+<gmd:voice>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-Phone'][0] }}</gco:CharacterString>
+</gmd:voice>
+<gmd:facsimile>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-Fax'][0] }}</gco:CharacterString>
+</gmd:facsimile>
+</gmd:CI_Telephone>
+</gmd:phone>
+<gmd:address>
+<gmd:CI_Address>
+<gmd:electronicMailAddress>
+<gco:CharacterString>{{ doc['DatasetContact-Contact-Email'][0] }}</gco:CharacterString>
+</gmd:electronicMailAddress>
+</gmd:CI_Address>
+</gmd:address>
+{% if (doc['DatasetCitation-OnlineResource'][0] | trim)[0:4] == 'http' or (doc['DatasetCitation-OnlineResource'][0] | trim)[0:3] == 'ftp' %}
+<gmd:onlineResource>
+<gmd:CI_OnlineResource>
+<gmd:linkage>
+<gmd:URL>{{ doc['DatasetCitation-OnlineResource'][0] }}</gmd:URL>
+</gmd:linkage>
+</gmd:CI_OnlineResource>
+</gmd:onlineResource>
+{% else %}
+<gmd:onlineResource gco:nilReason="missing"/>
+{% endif %}
+</gmd:CI_Contact>
+</gmd:contactInfo>
+<gmd:role>
+<gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="pointOfContact">pointOfContact</gmd:CI_RoleCode>
+</gmd:role>
+</gmd:CI_ResponsibleParty>
+</gmd:pointOfContact>
+<gmd:resourceFormat>
+<gmd:MD_Format id="resourceFormat">
+<gmd:name>
+<gco:CharacterString>{{ doc['DatasetPolicy-DataFormat'][0] }}</gco:CharacterString>
+</gmd:name>
+<gmd:version>
+<gco:CharacterString>{{ DatasetPolicy_DataFormat_Version }}</gco:CharacterString>
+</gmd:version>
+<gmd:fileDecompressionTechnique>
+<gco:CharacterString>{{ doc['DatasetPolicy-CompressType'][0] }}</gco:CharacterString>
+</gmd:fileDecompressionTechnique>
+</gmd:MD_Format>
+</gmd:resourceFormat>
+{% for i in range(doc['DatasetParameter-Category']|count) %}
+<gmd:descriptiveKeywords>
+<gmd:MD_Keywords>
+<gmd:keyword>
+<gco:CharacterString>{{ doc['DatasetParameter-Category'][i] }} &gt; {{ doc['DatasetParameter-Topic'][i] }} &gt; {{ doc['DatasetParameter-Term'][i] }} &gt; {{ doc['DatasetParameter-Variable'][i] }}{% if doc['DatasetParameter-VariableDetail'][i] != ''  %} &gt; {{ doc['DatasetParameter-VariableDetail'][i] }}{% endif %}</gco:CharacterString>
+</gmd:keyword>
+<gmd:type>
+<gmd:MD_KeywordTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_KeywordTypeCode" codeListValue="theme">theme</gmd:MD_KeywordTypeCode>
+</gmd:type>
+<gmd:thesaurusName>
+<gmd:CI_Citation>
+<gmd:title>
+<gco:CharacterString>NASA/GCMD Earth Science Keywords</gco:CharacterString>
+</gmd:title>
+<gmd:date gco:nilReason="unknown"/>
+</gmd:CI_Citation>
+</gmd:thesaurusName>
+</gmd:MD_Keywords>
+</gmd:descriptiveKeywords>
+{% endfor %}
+<gmd:descriptiveKeywords>
+<gmd:MD_Keywords>
+<gmd:keyword>
+<gco:CharacterString>{{ doc['DatasetRegion-Region'][0] }}</gco:CharacterString>
+</gmd:keyword>
+<gmd:type>
+<gmd:MD_KeywordTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_KeywordTypeCode" codeListValue="place">place</gmd:MD_KeywordTypeCode>
+</gmd:type>
+<gmd:thesaurusName>
+<gmd:CI_Citation>
+<gmd:title>
+<gco:CharacterString>NASA/GCMD Location Keywords</gco:CharacterString>
+</gmd:title>
+<gmd:date gco:nilReason="unknown"/>
+</gmd:CI_Citation>
+</gmd:thesaurusName>
+</gmd:MD_Keywords>
+</gmd:descriptiveKeywords>
+<gmd:resourceConstraints>
+<gmd:MD_LegalConstraints>
+<gmd:useLimitation>
+<gco:CharacterString>{{ doc['DatasetPolicy-UseConstraint'][0] }}</gco:CharacterString>
+</gmd:useLimitation>
+<gmd:otherConstraints>
+<gco:CharacterString>{{ doc['DatasetPolicy-AccessConstraint'][0] }}</gco:CharacterString>
+</gmd:otherConstraints>
+</gmd:MD_LegalConstraints>
+</gmd:resourceConstraints>
+<gmd:spatialRepresentationType>
+<gmd:MD_SpatialRepresentationTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_SpatialRepresentationTypeCode" codeListValue="grid">grid</gmd:MD_SpatialRepresentationTypeCode>
+</gmd:spatialRepresentationType>
+<gmd:language>
+<gco:CharacterString>eng</gco:CharacterString>
+</gmd:language>
+<gmd:characterSet>
+<gmd:MD_CharacterSetCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_CharacterSetCode" codeListValue="UTF8">UTF8</gmd:MD_CharacterSetCode>
+</gmd:characterSet>
+<gmd:extent>
+<gmd:EX_Extent id="boundingExtent">
+<gmd:geographicElement>
+<gmd:EX_GeographicBoundingBox id="boundingBox">
+<gmd:extentTypeCode>
+<gco:Boolean>true</gco:Boolean>
+</gmd:extentTypeCode>
+<gmd:westBoundLongitude>
+<gco:Decimal>{{ doc['DatasetCoverage-WestLon'][0] }}</gco:Decimal>
+</gmd:westBoundLongitude>
+<gmd:eastBoundLongitude>
+<gco:Decimal>{{ doc['DatasetCoverage-EastLon'][0] }}</gco:Decimal>
+</gmd:eastBoundLongitude>
+<gmd:southBoundLatitude>
+<gco:Decimal>{{ doc['DatasetCoverage-SouthLat'][0] }}</gco:Decimal>
+</gmd:southBoundLatitude>
+<gmd:northBoundLatitude>
+<gco:Decimal>{{ doc['DatasetCoverage-NorthLat'][0] }}</gco:Decimal>
+</gmd:northBoundLatitude>
+</gmd:EX_GeographicBoundingBox>
+</gmd:geographicElement>
+<gmd:geographicElement>
+<gmd:EX_GeographicDescription>
+<gmd:extentTypeCode>
+<gco:Boolean>true</gco:Boolean>
+</gmd:extentTypeCode>
+<gmd:geographicIdentifier>
+<gmd:MD_Identifier>
+<gmd:code/>
+</gmd:MD_Identifier>
+</gmd:geographicIdentifier>
+</gmd:EX_GeographicDescription>
+</gmd:geographicElement>
+<gmd:temporalElement>
+<gmd:EX_TemporalExtent id="temporalExtent">
+<gmd:extent>
+<TimePeriod xmlns="http://www.opengis.net/gml/3.2" xmlns:ns1="http://www.opengis.net/gml/3.2" ns1:id="timePeriod">
+<beginPosition>{{ DatasetCoverage_StartTime }}</beginPosition>
+<endPosition>{{ DatasetCoverage_StopTime }}</endPosition>
+</TimePeriod>
+</gmd:extent>
+</gmd:EX_TemporalExtent>
+</gmd:temporalElement>
+<gmd:verticalElement gco:nilReason="inapplicable"/>
+</gmd:EX_Extent>
+</gmd:extent>
+</gmd:MD_DataIdentification>
+</gmd:identificationInfo>
+<gmd:contentInfo>
+<gmi:MI_CoverageDescription id="referenceInformation">
+<gmd:attributeDescription>
+<gco:RecordType xlink:href="http://www.ghrsst.org/documents.htm?parent=475"/>
+</gmd:attributeDescription>
+<gmd:contentType>
+<gmd:MD_CoverageContentTypeCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_CoverageContentTypeCode" codeListValue="referenceInformation">referenceInformation</gmd:MD_CoverageContentTypeCode>
+</gmd:contentType>
+<gmd:dimension>
+<gmd:MD_Band>
+<gmd:sequenceIdentifier>
+<gco:MemberName>
+<gco:aName>
+<gco:CharacterString>lat</gco:CharacterString>
+</gco:aName>
+<gco:attributeType>
+<gco:TypeName>
+<gco:aName>
+<gco:CharacterString>float</gco:CharacterString>
+</gco:aName>
+</gco:TypeName>
+</gco:attributeType>
+</gco:MemberName>
+</gmd:sequenceIdentifier>
+</gmd:MD_Band>
+</gmd:dimension>
+<gmd:dimension>
+<gmd:MD_Band>
+<gmd:sequenceIdentifier>
+<gco:MemberName>
+<gco:aName>
+<gco:CharacterString>lon</gco:CharacterString>
+</gco:aName>
+<gco:attributeType>
+<gco:TypeName>
+<gco:aName>
+<gco:CharacterString>float</gco:CharacterString>
+</gco:aName>
+</gco:TypeName>
+</gco:attributeType>
+</gco:MemberName>
+</gmd:sequenceIdentifier>
+</gmd:MD_Band>
+</gmd:dimension>
+<gmd:dimension>
+<gmd:MD_Band>
+<gmd:sequenceIdentifier>
+<gco:MemberName>
+<gco:aName>
+<gco:CharacterString>time</gco:CharacterString>
+</gco:aName>
+<gco:attributeType>
+<gco:TypeName>
+<gco:aName>
+<gco:CharacterString>int</gco:CharacterString>
+</gco:aName>
+</gco:TypeName>
+</gco:attributeType>
+</gco:MemberName>
+</gmd:sequenceIdentifier>
+</gmd:MD_Band>
+</gmd:dimension>
+</gmi:MI_CoverageDescription>
+</gmd:contentInfo>
+<gmd:distributionInfo>
+<gmd:MD_Distribution>
+<gmd:distributionFormat xlink:href="#resourceFormat"/>
+<gmd:distributor>
+<gmd:MD_Distributor>
+<gmd:distributorContact>
+<gmd:CI_ResponsibleParty>
+<gmd:individualName>
+<gco:CharacterString>PO.DAAC User Services</gco:CharacterString>
+</gmd:individualName>
+<gmd:organisationName>
+<gco:CharacterString>NASA/JPL/PODAAC &gt; Physical Oceanography Distributed Active Archive Center, Jet Propulsion Laboratory, NASA</gco:CharacterString>
+</gmd:organisationName>
+<gmd:contactInfo>
+<gmd:CI_Contact>
+<gmd:address>
+<gmd:CI_Address>
+<gmd:deliveryPoint>
+<gco:CharacterString>4800 Oak Grove Drive</gco:CharacterString>
+</gmd:deliveryPoint>
+<gmd:city>
+<gco:CharacterString>Pasadena</gco:CharacterString>
+</gmd:city>
+<gmd:administrativeArea>
+<gco:CharacterString>CA</gco:CharacterString>
+</gmd:administrativeArea>
+<gmd:postalCode>
+<gco:CharacterString>91109-8099</gco:CharacterString>
+</gmd:postalCode>
+<gmd:country>
+<gco:CharacterString>USA</gco:CharacterString>
+</gmd:country>
+<gmd:electronicMailAddress>
+<gco:CharacterString>podaac@podaac.jpl.nasa.gov</gco:CharacterString>
+</gmd:electronicMailAddress>
+</gmd:CI_Address>
+</gmd:address>
+<gmd:onlineResource>
+<gmd:CI_OnlineResource>
+<gmd:linkage>
+<gmd:URL>http://podaac.jpl.nasa.gov</gmd:URL>
+</gmd:linkage>
+</gmd:CI_OnlineResource>
+</gmd:onlineResource>
+</gmd:CI_Contact>
+</gmd:contactInfo>
+<gmd:role>
+<gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="distributor">distributor</gmd:CI_RoleCode>
+</gmd:role>
+</gmd:CI_ResponsibleParty>
+</gmd:distributorContact>
+</gmd:MD_Distributor>
+</gmd:distributor>
+{% for i in range(doc['DatasetResource-Path']|count) if doc['DatasetResource-Type'][i] != 'Thumbnail' %}
+<gmd:transferOptions>
+<gmd:MD_DigitalTransferOptions>
+<gmd:onLine>
+<gmd:CI_OnlineResource>
+<gmd:linkage>
+<gmd:URL>{{ doc['DatasetResource-Path'][i] }}</gmd:URL>
+</gmd:linkage>
+<gmd:name>
+<gco:CharacterString>{{ doc['DatasetResource-Name'][i] }}</gco:CharacterString>
+</gmd:name>
+<gmd:description>
+<gco:CharacterString>{{ doc['DatasetResource-Description'][i] }}</gco:CharacterString>
+</gmd:description>
+<gmd:function>
+<gmd:CI_OnLineFunctionCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_OnlineFunctionCode" codeListValue="information">information</gmd:CI_OnLineFunctionCode>
+</gmd:function>
+</gmd:CI_OnlineResource>
+</gmd:onLine>
+</gmd:MD_DigitalTransferOptions>
+</gmd:transferOptions>
+{% endfor %}
+</gmd:MD_Distribution>
+</gmd:distributionInfo>
+<gmd:metadataMaintenance>
+<gmd:MD_MaintenanceInformation>
+<gmd:maintenanceAndUpdateFrequency>
+<gmd:MD_MaintenanceFrequencyCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#MD_MaintenanceFrequencyCode" codeListValue="asNeeded">asNeeded</gmd:MD_MaintenanceFrequencyCode>
+</gmd:maintenanceAndUpdateFrequency>
+<gmd:maintenanceNote>
+<gco:CharacterString>Translated from GCMD DIF </gco:CharacterString>
+</gmd:maintenanceNote>
+</gmd:MD_MaintenanceInformation>
+</gmd:metadataMaintenance>
+<gmi:acquisitionInformation>
+<gmi:MI_AcquisitionInformation>
+{% for i in UniqueDatasetSensor %}
+<gmi:instrument>
+<gmi:MI_Instrument>
+<gmi:identifier>
+<gmd:MD_Identifier>
+<gmd:code>
+<gco:CharacterString>{{ doc['DatasetSource-Sensor-ShortName'][i] }} &gt; {{ doc['DatasetSource-Sensor-LongName'][i] }}</gco:CharacterString>
+</gmd:code>
+</gmd:MD_Identifier>
+</gmi:identifier>
+<gmi:type>
+<gco:CharacterString>sensor</gco:CharacterString>
+</gmi:type>
+<gmi:description>
+<gco:CharacterString>{{ doc['DatasetSource-Sensor-Description'][i] }}</gco:CharacterString>
+</gmi:description>
+</gmi:MI_Instrument>
+</gmi:instrument>
+{% endfor %}
+{% for i in UniqueDatasetSource %}
+<gmi:platform>
+<gmi:MI_Platform>
+<gmi:identifier>
+<gmd:MD_Identifier>
+<gmd:code>
+<gco:CharacterString>{{ doc['DatasetSource-Source-ShortName'][i] }} &gt; {{ doc['DatasetSource-Source-LongName'][i] }}</gco:CharacterString>
+</gmd:code>
+</gmd:MD_Identifier>
+</gmi:identifier>
+<gmi:description>
+<gco:CharacterString>{{ doc['DatasetSource-Source-Description'][i] }}</gco:CharacterString>
+</gmi:description>
+<gmi:sponsor>
+<gmd:CI_ResponsibleParty>
+<gmd:organisationName>
+<gco:CharacterString>{{ doc['DatasetCitation-Creator'][0] }}</gco:CharacterString>
+</gmd:organisationName>
+<gmd:contactInfo>
+<gmd:CI_Contact>
+{% if (doc['DatasetCitation-OnlineResource'][0] | trim)[0:4] == 'http' or (doc['DatasetCitation-OnlineResource'][0] | trim)[0:3] == 'ftp' %}
+<gmd:onlineResource>
+<gmd:CI_OnlineResource>
+<gmd:linkage>
+<gmd:URL>{{ doc['DatasetCitation-OnlineResource'][0] }}</gmd:URL>
+</gmd:linkage>
+</gmd:CI_OnlineResource>
+</gmd:onlineResource>
+{% else %}
+<gmd:onlineResource gco:nilReason="missing"/>
+{% endif %}
+</gmd:CI_Contact>
+</gmd:contactInfo>
+<gmd:role>
+<gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="sponsor"/>
+</gmd:role>
+</gmd:CI_ResponsibleParty>
+</gmi:sponsor>
+<gmi:sponsor>
+<gmd:CI_ResponsibleParty>
+<gmd:organisationName>
+<gco:CharacterString>NASA/JPL/PODAAC &gt; Physical Oceanography Distributed Active Archive Center, Jet Propulsion Laboratory, NASA</gco:CharacterString>
+</gmd:organisationName>
+<gmd:contactInfo>
+<gmd:CI_Contact>
+<gmd:onlineResource>
+<gmd:CI_OnlineResource>
+<gmd:linkage>
+<gmd:URL>http://podaac.jpl.nasa.gov</gmd:URL>
+</gmd:linkage>
+<gmd:function>
+<gmd:CI_OnLineFunctionCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_OnLineFunctionCode" codeListValue="information"/>
+</gmd:function>
+</gmd:CI_OnlineResource>
+</gmd:onlineResource>
+</gmd:CI_Contact>
+</gmd:contactInfo>
+<gmd:role>
+<gmd:CI_RoleCode codeList="http://www.isotc211.org/2005/resources/Codelist/gmxCodelists.xml#CI_RoleCode" codeListValue="sponsor"/>
+</gmd:role>
+</gmd:CI_ResponsibleParty>
+</gmi:sponsor>
+<gmi:instrument xlink:href="{{ doc['DatasetSource-Source-ShortName'][i] }}"/>
+</gmi:MI_Platform>
+</gmi:platform>
+{% endfor %}
+</gmi:MI_AcquisitionInformation>
+</gmi:acquisitionInformation>
+</gmi:MI_Metadata>
+</gmd:seriesMetadata>
+{% endif %}
+</gmd:DS_Series>

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/granule/iso/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/granule/iso/plugin.conf b/src/main/python/plugins/granule/iso/plugin.conf
new file mode 100644
index 0000000..760017f
--- /dev/null
+++ b/src/main/python/plugins/granule/iso/plugin.conf
@@ -0,0 +1,10 @@
+[solr]
+datasetUrl=http://localhost:8983/solr.war/dataset
+granuleUrl=http://localhost:8983/solr.war/granule
+entriesPerPage=7
+
+[service]
+url=http://localhost:8890
+linkToGranule=LOCAL-FTP,REMOTE-FTP
+database=podaac_dev/podaac$dev@DAACDEV
+template=iso_template.xml

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/granule/rss/RssWriter.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/granule/rss/RssWriter.py b/src/main/python/plugins/granule/rss/RssWriter.py
new file mode 100644
index 0000000..6d2cb25
--- /dev/null
+++ b/src/main/python/plugins/granule/rss/RssWriter.py
@@ -0,0 +1,21 @@
+import logging
+
+from edge.opensearch.granulerssresponse import GranuleRssResponse
+from edge.opensearch.granulewriter import GranuleWriter
+
+class RssWriter(GranuleWriter):
+    
+    def __init__(self, configFilePath):
+        super(RssWriter, self).__init__(configFilePath, [['datasetId', 'shortName']])
+
+    def _generateOpenSearchResponse(self, solrResponse, searchText, searchUrl, searchParams, pretty):
+        response = GranuleRssResponse(self._configuration.get('service', 'linkToGranule'), 
+                                      self._configuration.get('service', 'host'),
+                                      self._configuration.get('service', 'url'))
+
+        response.title = 'PO.DAAC Granule Search Results'
+        response.description = 'Search result for "'+searchText+'"'
+        response.link = searchUrl
+        response.parameters = searchParams
+
+        return response.generate(solrResponse, pretty) 

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/granule/rss/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/granule/rss/__init__.py b/src/main/python/plugins/granule/rss/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/granule/rss/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/granule/rss/plugin.conf b/src/main/python/plugins/granule/rss/plugin.conf
new file mode 100644
index 0000000..3f14b5f
--- /dev/null
+++ b/src/main/python/plugins/granule/rss/plugin.conf
@@ -0,0 +1,12 @@
+[solr]
+datasetUrl=http://localhost:8983/solr.war/dataset
+granuleUrl=http://localhost:8983/solr.war/granule
+entriesPerPage=7
+
+[service]
+url=http://localhost:8890
+linkToGranule=LOCAL-FTP,REMOTE-FTP
+host=localhost:8890
+database=podaac_dev/podaac$dev@DAACDEV
+l2=http://biaxin.jpl.nasa.gov/ws/search/granule
+bbox=l2

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/heartbeat/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/heartbeat/__init__.py b/src/main/python/plugins/heartbeat/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/heartbeat/json/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/heartbeat/json/Writer.py b/src/main/python/plugins/heartbeat/json/Writer.py
new file mode 100644
index 0000000..8628f8a
--- /dev/null
+++ b/src/main/python/plugins/heartbeat/json/Writer.py
@@ -0,0 +1,30 @@
+import logging
+import json
+
+import requestresponder
+from edge.httputility import HttpUtility
+
+class Writer(requestresponder.RequestResponder):
+    url = None
+
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)
+        self.url = self._configuration.get('solr', 'url') + "/admin/ping"
+
+    def get(self, requestHandler):
+        super(Writer, self).get(requestHandler)
+        try:
+            httpUtility = HttpUtility()
+            result = httpUtility.getResponse(self.url, self.onResponse)
+        except BaseException as exception:
+            raise exception
+
+    def onResponse(self, response):
+        self.requestHandler.set_header("Content-Type", "application/json")
+        self.requestHandler.set_header('Access-Control-Allow-Origin', '*')
+        if response.error:
+            self.requestHandler.write(json.dumps({"online": False}))
+            self.requestHandler.finish()
+        else:
+            self.requestHandler.write(json.dumps({"online": True}))
+            self.requestHandler.finish()

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/heartbeat/json/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/heartbeat/json/__init__.py b/src/main/python/plugins/heartbeat/json/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/heartbeat/json/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/heartbeat/json/plugin.conf b/src/main/python/plugins/heartbeat/json/plugin.conf
new file mode 100644
index 0000000..98b11c8
--- /dev/null
+++ b/src/main/python/plugins/heartbeat/json/plugin.conf
@@ -0,0 +1,2 @@
+[solr]
+url=http://localhost:8983/solr/[core]

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/icoads/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/icoads/__init__.py b/src/main/python/plugins/icoads/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/icoads/json/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/icoads/json/Writer.py b/src/main/python/plugins/icoads/json/Writer.py
new file mode 100644
index 0000000..c3bf33a
--- /dev/null
+++ b/src/main/python/plugins/icoads/json/Writer.py
@@ -0,0 +1,89 @@
+import logging
+import os
+import os.path
+import urllib
+
+from edge.writer.solrtemplateresponsewriter import SolrTemplateResponseWriter
+from edge.response.solrjsontemplateresponse import SolrJsonTemplateResponse
+
+class Writer(SolrTemplateResponseWriter):
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)
+        
+        self.contentType = 'application/json'
+
+        templatePath = os.path.dirname(configFilePath) + os.sep
+        templatePath += self._configuration.get('service', 'template')
+        self.template = self._readTemplate(templatePath)
+
+    def _generateOpenSearchResponse(self, solrResponse, searchText, searchUrl, searchParams, pretty):
+        response = SolrJsonTemplateResponse(searchUrl, searchParams)
+        response.setTemplate(self.template)
+
+        return response.generate(solrResponse, pretty=pretty)
+
+    def _constructSolrQuery(self, startIndex, entriesPerPage, parameters, facets):
+        queries = []
+        filterQueries = []
+        sort = None
+
+        for key, value in parameters.iteritems():
+            if value != "":
+                if key == 'keyword':
+                    queries.append(urllib.quote(value))
+                elif key == 'startTime':
+                    filterQueries.append('time:['+value+'%20TO%20*]')
+                elif key == 'endTime':
+                    filterQueries.append('time:[*%20TO%20'+value+']')
+                elif key == 'bbox':
+                    coordinates = value.split(",")
+                    filterQueries.append('loc:[' + coordinates[1] + ',' + coordinates[0] + '%20TO%20' + coordinates[3] + ',' + coordinates[2] + ']')
+                elif key == 'variable':
+                    if value.lower() == 'sss':
+                        filterQueries.append('sss:[*%20TO%20*]')
+                    elif value.lower() == 'sst':
+                        filterQueries.append('sst:[*%20TO%20*]')
+                    elif value.lower() == 'wind':
+                        filterQueries.append('wind_speed:[*%20TO%20*]')
+                elif key == "minDepth":
+                    if 'variable' in parameters:
+                        if parameters['variable'].lower() == 'sss':
+                            filterQueries.append('(sss_depth:['+value+'%20TO%20*]+OR+(*:*%20NOT%20sss_depth:*))')
+                        elif parameters['variable'].lower() == 'sst':
+                            filterQueries.append('(sst_depth:['+value+'%20TO%20*]+OR+(*:*%20NOT%20sst_depth:*))')
+                        elif parameters['variable'].lower() == 'wind':
+                            filterQueries.append('(wind_depth:['+value+'%20TO%20*]+OR+(*:*%20NOT%20wind_depth:*))')
+                elif key == "maxDepth":
+                    if 'variable' in parameters:
+                        if parameters['variable'].lower() == 'sss':
+                            filterQueries.append('(sss_depth:[*%20TO%20'+value+']+OR+(*:*%20NOT%20sss_depth:*))')
+                        elif parameters['variable'].lower() == 'sst':
+                            filterQueries.append('(sst_depth:[*%20TO%20'+value+']+OR+(*:*%20NOT%20sst_depth:*))')
+                        elif parameters['variable'].lower() == 'wind':
+                            filterQueries.append('(wind_depth:[*%20TO%20'+value+']+OR+(*:*%20NOT%20wind_depth:*))')
+                elif key == 'platform':
+                    if type(value) is list:
+                        filterQueries.append('platform:(' + '+OR+'.join(value) + ')')
+                    else:
+                        filterQueries.append('platform:'+value)
+
+        if len(queries) == 0:
+            queries.append('*:*')
+
+        query = 'q='+'+AND+'.join(queries)+'&wt=json&start='+str(startIndex)+'&rows='+str(entriesPerPage)
+
+        if len(filterQueries) > 0:
+            query += '&fq='+'+AND+'.join(filterQueries)
+
+        if sort is not None:
+            query += '&sort=' + sort
+
+        if 'stats' in parameters and parameters['stats'].lower() == 'true':
+            query += '&stats=true&stats.field={!min=true%20max=true}sss_depth&stats.field={!min=true%20max=true}sst_depth&stats.field={!min=true%20max=true}wind_depth'
+
+        if 'facet' in parameters and parameters['facet'].lower() == 'true':
+            query += '&facet=true&facet.field=platform&facet.field=device&facet.limit=-1&facet.mincount=1'
+
+        logging.debug('solr query: '+query)
+
+        return query

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/icoads/json/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/icoads/json/__init__.py b/src/main/python/plugins/icoads/json/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/icoads/json/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/icoads/json/plugin.conf b/src/main/python/plugins/icoads/json/plugin.conf
new file mode 100644
index 0000000..04438e6
--- /dev/null
+++ b/src/main/python/plugins/icoads/json/plugin.conf
@@ -0,0 +1,11 @@
+[solr]
+datasetUrl=http://localhost:8983/solr/icoads
+entriesPerPage=10
+maxEntriesPerPage=100000
+defaultSearchParam=keyword
+parameters=keyword,startTime,endTime,bbox,minDepth,maxDepth,variable,stats,platform,facet
+facets={}
+
+[service]
+url=http://localhost:8890
+template=template.json

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/icoads/json/template.json
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/icoads/json/template.json b/src/main/python/plugins/icoads/json/template.json
new file mode 100755
index 0000000..6133e52
--- /dev/null
+++ b/src/main/python/plugins/icoads/json/template.json
@@ -0,0 +1,64 @@
+{
+{% if last %}"last": "{{ last }}",{% endif %}
+{% if prev %}"prev": "{{ prev }}",{% endif %}
+{% if next %}"next": "{{ next }}",{% endif %}
+{% if first %}"first": "{{ first }}",{% endif %}
+"results":[
+{% for doc in docs %}
+{
+"id": "{{ doc['id'] }}",
+"time": "{{ doc['time'] }}",
+"point": "{{ doc['loc'] }}",
+"sea_water_temperature": {{ doc['sst'] | jsonify }},
+"sea_water_temperature_depth": {{ doc['sst_depth'] | jsonify }},
+"sea_water_temperature_quality": {{ doc['sst_qc_flag'] | jsonify }},
+"wind_speed": {{ doc['wind_speed'] | jsonify }},
+"eastward_wind": {{ doc['wind_u'] | jsonify }},
+"northward_wind": {{ doc['wind_v'] | jsonify }},
+"wind_depth": {{ doc['wind_depth'] | jsonify }},
+"wind_quality": {{ doc['wind_qc_flag'] | jsonify }},
+"sea_water_salinity": {{ doc['sss'] | jsonify }},
+"sea_water_salinity_depth": {{ doc['sss_depth'] | jsonify }},
+"sea_water_salinity_quality": {{ doc['sss_qc_flag'] | jsonify }},
+"mission": {{ doc['mission'] | jsonify }},
+"platform": {{ doc['platform'] | jsonify }},
+"device": {{ doc['device'] | jsonify }},
+"metadata": {{ doc['meta'] }}
+}
+{% if not loop.last %}
+,
+{% endif %}
+{% endfor %}
+]
+,"totalResults":{{ numFound }}
+,"startIndex":{{ startIndex  }}
+,"itemsPerPage":{{ itemsPerPage }}
+{% if stats %}
+,
+"stats_fields": {{ stats['stats_fields'] | jsonify }}
+{% endif %}
+{% if facets %}
+,
+"facets":[
+{% for key, facet in facets['facet_fields'].iteritems() %}
+{
+"field": "{{ key }}",
+"values":[
+{% for i in range(0, facet|count, 2) %}
+{
+"count":{{facet[i+1] }},
+"value": "{{ facet[i] }}"
+}
+{% if not loop.last %}
+,
+{% endif %}
+{% endfor %}
+]
+}
+{% if not loop.last %}
+,
+{% endif %}
+{% endfor %}
+]
+{% endif %}
+}

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/nexus/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/nexus/__init__.py b/src/main/python/plugins/nexus/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/nexus/climatology/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/nexus/climatology/Writer.py b/src/main/python/plugins/nexus/climatology/Writer.py
new file mode 100644
index 0000000..0d78465
--- /dev/null
+++ b/src/main/python/plugins/nexus/climatology/Writer.py
@@ -0,0 +1,8 @@
+import logging
+import urllib
+
+from edge.writer.genericproxywriter import GenericProxyWriter
+
+class Writer(GenericProxyWriter):
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/nexus/climatology/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/nexus/climatology/__init__.py b/src/main/python/plugins/nexus/climatology/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/nexus/climatology/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/nexus/climatology/plugin.conf b/src/main/python/plugins/nexus/climatology/plugin.conf
new file mode 100644
index 0000000..8372843
--- /dev/null
+++ b/src/main/python/plugins/nexus/climatology/plugin.conf
@@ -0,0 +1,2 @@
+[proxy]
+url=http://127.0.0.1:8080/climatology

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/nexus/solr/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/nexus/solr/Writer.py b/src/main/python/plugins/nexus/solr/Writer.py
new file mode 100644
index 0000000..0d78465
--- /dev/null
+++ b/src/main/python/plugins/nexus/solr/Writer.py
@@ -0,0 +1,8 @@
+import logging
+import urllib
+
+from edge.writer.genericproxywriter import GenericProxyWriter
+
+class Writer(GenericProxyWriter):
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/nexus/solr/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/nexus/solr/__init__.py b/src/main/python/plugins/nexus/solr/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/nexus/solr/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/nexus/solr/plugin.conf b/src/main/python/plugins/nexus/solr/plugin.conf
new file mode 100644
index 0000000..e97553c
--- /dev/null
+++ b/src/main/python/plugins/nexus/solr/plugin.conf
@@ -0,0 +1,2 @@
+[proxy]
+url=http://127.0.0.1:8080/solr

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/nexus/subsetter/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/nexus/subsetter/Writer.py b/src/main/python/plugins/nexus/subsetter/Writer.py
new file mode 100644
index 0000000..0d78465
--- /dev/null
+++ b/src/main/python/plugins/nexus/subsetter/Writer.py
@@ -0,0 +1,8 @@
+import logging
+import urllib
+
+from edge.writer.genericproxywriter import GenericProxyWriter
+
+class Writer(GenericProxyWriter):
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/nexus/subsetter/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/nexus/subsetter/__init__.py b/src/main/python/plugins/nexus/subsetter/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/nexus/subsetter/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/nexus/subsetter/plugin.conf b/src/main/python/plugins/nexus/subsetter/plugin.conf
new file mode 100644
index 0000000..0222e15
--- /dev/null
+++ b/src/main/python/plugins/nexus/subsetter/plugin.conf
@@ -0,0 +1,2 @@
+[proxy]
+url=http://127.0.0.1:8082/subsetter

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oceanxtremes/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oceanxtremes/__init__.py b/src/main/python/plugins/oceanxtremes/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oceanxtremes/datacasting/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oceanxtremes/datacasting/Writer.py b/src/main/python/plugins/oceanxtremes/datacasting/Writer.py
new file mode 100644
index 0000000..e3a83b6
--- /dev/null
+++ b/src/main/python/plugins/oceanxtremes/datacasting/Writer.py
@@ -0,0 +1,62 @@
+import logging
+import os
+import os.path
+import urllib
+import json
+
+from edge.writer.solrtemplateresponsewriter import SolrTemplateResponseWriter
+from edge.opensearch.solrtemplateresponse import SolrTemplateResponse
+
+class Writer(SolrTemplateResponseWriter):
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)
+
+        templatePath = os.path.dirname(configFilePath) + os.sep
+        templatePath += self._configuration.get('service', 'template')
+        self.template = self._readTemplate(templatePath)
+
+    def _generateOpenSearchResponse(self, solrResponse, searchText, searchUrl, searchParams, pretty):
+        response = SolrTemplateResponse(self._configuration, searchUrl, searchParams)
+        response.setTemplate(self.template)
+        response.variables['serviceUrl'] = self._configuration.get('service', 'url')
+
+        return response.generate(solrResponse, pretty=pretty)
+
+    def _constructSolrQuery(self, startIndex, entriesPerPage, parameters, facets):
+        sortKeys = json.loads(self._configuration.get('solr', 'sortKeys'))
+
+        queries = []
+        filterQueries = []
+        sort = None
+        sortDir = 'asc'
+        start = '*'
+        end = '*'
+
+        for key, value in parameters.iteritems():
+            if value != "":
+                if key == 'keyword':
+                    queries.append(urllib.quote(value))
+                elif key == 'shortName':
+                    queries.append("primary_dataset_short_name:" + urllib.quote(value))
+
+        if len(queries) == 0:
+            queries.append('*:*')
+
+        query = 'q='+'+AND+'.join(queries)+'&version=2.2&indent=on&wt=json'
+
+        if len(filterQueries) > 0:
+            query += '&fq='+'+AND+'.join(filterQueries)
+        
+        if self.facet:
+            query += '&rows=0&facet=true&facet.limit=-1&facet.mincount=1&'
+            query += '&'.join(['facet.field=' + facet for facet in self.facetDefs.values()])
+        else:
+            query += '&start='+str(startIndex)+'&rows='+str(entriesPerPage)
+            if sort is not None:
+                query += '&sort=' + urllib.quote(sort + ' ' + sortDir + ",InternalVersion desc")
+            else:
+                query += '&sort=' + urllib.quote("submit_date desc")
+
+        logging.debug('solr query: '+query)
+
+        return query

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oceanxtremes/datacasting/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oceanxtremes/datacasting/__init__.py b/src/main/python/plugins/oceanxtremes/datacasting/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oceanxtremes/datacasting/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oceanxtremes/datacasting/plugin.conf b/src/main/python/plugins/oceanxtremes/datacasting/plugin.conf
new file mode 100644
index 0000000..42ab19d
--- /dev/null
+++ b/src/main/python/plugins/oceanxtremes/datacasting/plugin.conf
@@ -0,0 +1,12 @@
+[solr]
+datasetUrl=http://localhost:8983/solr/anomaly
+entriesPerPage=2000
+maxEntriesPerPage=2000
+defaultSearchParam=keyword
+parameters=keyword,shortName
+facets={}
+sortKeys={}
+
+[service]
+url=http://localhost:8890
+template=template.xml

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oceanxtremes/datacasting/template.xml
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oceanxtremes/datacasting/template.xml b/src/main/python/plugins/oceanxtremes/datacasting/template.xml
new file mode 100755
index 0000000..fd7a2a9
--- /dev/null
+++ b/src/main/python/plugins/oceanxtremes/datacasting/template.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<rss xmlns:datacasting="http://datacasting.jpl.nasa.gov/datacasting"
+    xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml" version="2.0">
+    <channel>
+       <title>{{ parameters['shortName'] }}</title>
+       <link>{{ serviceUrl }}/anomaly?shortName={{ parameters['shortName'] }}</link>
+       <description>Anomalies flagged using dataset {{ parameters['shortName'] }}</description>
+       <datacasting:channelUID>{{ parameters['shortName'] }}</datacasting:channelUID>
+       <datacasting:dataSource>{{ parameters['shortName'] }}</datacasting:dataSource>
+       <datacasting:customEltDef displayName="Keyword" type="string" name="keyword"/>
+       <datacasting:customEltDef displayName="Lower Threshold" type="float" name="lowerThreshold"/>
+       <datacasting:customEltDef displayName="Upper Threshold" type="float" name="upperThreshold"/>
+       <datacasting:customEltDef displayName="Dataset Short Name" type="string" name="datasetShortName"/>
+       <datacasting:customEltDef displayName="Climatology Short Name" type="string" name="climatologyShortName"/>
+       <pubDate>{{ updated | convertISOTime('%a, %d %b %Y %H:%M:%S GMT') }}</pubDate>
+{% for doc in docs %}
+       <item>
+           <title>{{ doc['description'] }}</title>
+           <description>{{ doc['description'] }}</description>
+           <link>{{ doc['anomaly_url'] }}</link>
+           <datacasting:acquisitionStartDate>{{ doc['anomaly_begin_date'] | convertISOTime('%a, %d %b %Y %H:%M:%S GMT') }}</datacasting:acquisitionStartDate>
+           <datacasting:acquisitionEndDate>{{ doc['anomaly_end_date'] | convertISOTime('%a, %d %b %Y %H:%M:%S GMT') }}</datacasting:acquisitionEndDate>
+           <georss:where>
+               <gml:Envelope>
+{% set bbox = doc['bbox'][9:-1].split(',') %}
+                   <gml:lowerCorner>{{ bbox[3] }} {{ bbox[0] }}</gml:lowerCorner>
+                   <gml:upperCorner>{{ bbox[2] }} {{ bbox[1] }}</gml:upperCorner>
+               </gml:Envelope>
+           </georss:where>
+           <enclosure url="{{ doc['anomaly_url'] }}" length="0" type="application/x-gzip"/>
+           <datacasting:customElement name="keyword" value="{{ ','.join(doc['keyword']) }}"/>
+           <datacasting:customElement name="datasetShortName" value="{{ doc['primary_dataset_short_name'] }}"/>
+           <datacasting:customElement name="climatologyShortName" value="{{ doc['climatology_dataset_short_name'] }}"/>
+           <datacasting:customElement name="lowerThreshold" value="{{ doc['below_threshold'] }}"/>
+           <datacasting:customElement name="upperThreshold" value="{{ doc['above_threshold'] }}"/>
+           <datacasting:preview>{{ doc['anomaly_url'] }}</datacasting:preview>
+           <guid isPermaLink="false">{{ doc['id'] }}</guid>
+           <pubDate>{{ doc['submit_date'] | convertISOTime('%a, %d %b %Y %H:%M:%S GMT') }}</pubDate>
+           <source url="{{ doc['algorithm_url'] }}">{{ doc['primary_dataset_short_name'] }}</source>
+       </item>
+{% endfor %}
+    </channel>
+</rss>

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oceanxtremes/post/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oceanxtremes/post/Writer.py b/src/main/python/plugins/oceanxtremes/post/Writer.py
new file mode 100644
index 0000000..fd5fad8
--- /dev/null
+++ b/src/main/python/plugins/oceanxtremes/post/Writer.py
@@ -0,0 +1,44 @@
+import logging
+import urllib2
+import urlparse
+import uuid
+import json
+from datetime import datetime
+
+import requestresponder
+from edge.httputility import HttpUtility
+
+class Writer(requestresponder.RequestResponder):
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)
+
+    def options(self, requestHandler):
+        super(Writer, self).options(requestHandler)
+        self.requestHandler.set_header('Access-Control-Allow-Origin', '*')
+        self.requestHandler.set_header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
+        self.requestHandler.set_header('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With')
+        self.requestHandler.set_header('Allow', 'OPTIONS, GET, HEAD, POST')
+        self.requestHandler.set_header('Accept', 'application/json')
+        self.requestHandler.set_status(200)
+        self.requestHandler.finish()
+
+    def post(self, requestHandler):
+        super(Writer, self).post(requestHandler)
+        data = json.loads(requestHandler.request.body)
+
+        data["id"] = str(uuid.uuid4())
+        data["submit_date"] = datetime.utcnow().isoformat() + "Z"
+
+        httpUtility = HttpUtility()
+        solrUrl = self._configuration.get('solr', 'url') + "/update/json/docs?commit=true"
+        result = httpUtility.getResponse(solrUrl, self.onResponse, body=json.dumps(data), headers={'Content-Type': 'application/json'})
+
+    def onResponse(self, response):
+        self.requestHandler.set_header('Access-Control-Allow-Origin', '*')
+        if response.error:
+            self.requestHandler.set_status(404)
+            self.requestHandler.write(str(response.error))
+            self.requestHandler.finish()
+        else:
+            self.requestHandler.write(response.body)
+            self.requestHandler.finish()

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oceanxtremes/post/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oceanxtremes/post/__init__.py b/src/main/python/plugins/oceanxtremes/post/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oceanxtremes/post/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oceanxtremes/post/plugin.conf b/src/main/python/plugins/oceanxtremes/post/plugin.conf
new file mode 100644
index 0000000..d5dae25
--- /dev/null
+++ b/src/main/python/plugins/oceanxtremes/post/plugin.conf
@@ -0,0 +1,3 @@
+[solr]
+url=http://localhost:8983/solr/anomaly
+

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oiip/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oiip/__init__.py b/src/main/python/plugins/oiip/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oiip/json/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oiip/json/Writer.py b/src/main/python/plugins/oiip/json/Writer.py
new file mode 100644
index 0000000..58d84e6
--- /dev/null
+++ b/src/main/python/plugins/oiip/json/Writer.py
@@ -0,0 +1,46 @@
+import logging
+import os
+import os.path
+import urllib
+
+from edge.writer.solrtemplateresponsewriter import SolrTemplateResponseWriter
+from edge.response.solrjsontemplateresponse import SolrJsonTemplateResponse
+
+class Writer(SolrTemplateResponseWriter):
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)
+        
+        self.contentType = 'application/json'
+
+        templatePath = os.path.dirname(configFilePath) + os.sep
+        templatePath += self._configuration.get('service', 'template')
+        self.template = self._readTemplate(templatePath)
+
+    def _generateOpenSearchResponse(self, solrResponse, searchText, searchUrl, searchParams, pretty):
+        response = SolrJsonTemplateResponse()
+        response.setTemplate(self.template)
+
+        return response.generate(solrResponse, pretty=pretty)
+
+    def _constructSolrQuery(self, startIndex, entriesPerPage, parameters, facets):
+        queries = []
+
+        for key, value in parameters.iteritems():
+            if value != "":
+                if key == 'keyword':
+                    queries.append(urllib.quote(value))
+                elif key == 'necessity':
+                    queries.append("necessity:" + urllib.quote(value))
+                elif key == 'source':
+                    queries.append("source_ss:\"" + urllib.quote(value) + "\"")
+
+        if len(queries) == 0:
+            queries.append('*:*')
+
+        query = 'q='+'+AND+'.join(queries)+'&version=2.2&indent=on&wt=json&start='+str(startIndex)+'&rows='+str(entriesPerPage)
+
+        query += '&sort=category+asc'
+
+        logging.debug('solr query: '+query)
+
+        return query

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oiip/json/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oiip/json/__init__.py b/src/main/python/plugins/oiip/json/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oiip/json/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oiip/json/plugin.conf b/src/main/python/plugins/oiip/json/plugin.conf
new file mode 100644
index 0000000..882e3f1
--- /dev/null
+++ b/src/main/python/plugins/oiip/json/plugin.conf
@@ -0,0 +1,11 @@
+[solr]
+datasetUrl=http://localhost:8983/solr/attribute
+entriesPerPage=2000
+maxEntriesPerPage=2000
+defaultSearchParam=keyword
+parameters=keyword,necessity,source
+facets={}
+
+[service]
+url=http://localhost:8890
+template=template.json

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oiip/json/template.json
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oiip/json/template.json b/src/main/python/plugins/oiip/json/template.json
new file mode 100755
index 0000000..a5f3819
--- /dev/null
+++ b/src/main/python/plugins/oiip/json/template.json
@@ -0,0 +1,22 @@
+{
+   "attributes":
+[
+{% for doc in docs %}
+{
+"name": {{ doc['name'] | jsonify }},
+"category": {{ doc['category'] | jsonify }},
+"type": {{ doc['type'] | jsonify }},
+"description": {{ doc['description'] | jsonify }},
+"necessity": {{ doc['necessity'] | jsonify }},
+"source":
+{
+"name": {{ doc["source_name"] | jsonify }},
+"version": {{ doc["source_version"] | jsonify }}
+}
+}
+{% if not loop.last %}
+,
+{% endif %}
+{% endfor %}
+]
+}

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oiip/xml/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oiip/xml/Writer.py b/src/main/python/plugins/oiip/xml/Writer.py
new file mode 100644
index 0000000..c5c9c6c
--- /dev/null
+++ b/src/main/python/plugins/oiip/xml/Writer.py
@@ -0,0 +1,44 @@
+import logging
+import os
+import os.path
+import urllib
+
+from edge.writer.solrtemplateresponsewriter import SolrTemplateResponseWriter
+from edge.response.solrjsontemplateresponse import SolrJsonTemplateResponse
+
+class Writer(SolrTemplateResponseWriter):
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)
+
+        templatePath = os.path.dirname(configFilePath) + os.sep
+        templatePath += self._configuration.get('service', 'template')
+        self.template = self._readTemplate(templatePath)
+
+    def _generateOpenSearchResponse(self, solrResponse, searchText, searchUrl, searchParams, pretty):
+        response = SolrJsonTemplateResponse()
+        response.setTemplate(self.template)
+
+        return response.generate(solrResponse, pretty=pretty)
+
+    def _constructSolrQuery(self, startIndex, entriesPerPage, parameters, facets):
+        queries = []
+
+        for key, value in parameters.iteritems():
+            if value != "":
+                if key == 'keyword':
+                    queries.append(urllib.quote(value))
+                elif key == 'necessity':
+                    queries.append("necessity:" + urllib.quote(value))
+                elif key == 'source':
+                    queries.append("source_ss:\"" + urllib.quote(value) + "\"")
+
+        if len(queries) == 0:
+            queries.append('*:*')
+
+        query = 'q='+'+AND+'.join(queries)+'&version=2.2&indent=on&wt=json&start='+str(startIndex)+'&rows='+str(entriesPerPage)
+
+        query += '&sort=category+asc'
+
+        logging.debug('solr query: '+query)
+
+        return query

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oiip/xml/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oiip/xml/__init__.py b/src/main/python/plugins/oiip/xml/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oiip/xml/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oiip/xml/plugin.conf b/src/main/python/plugins/oiip/xml/plugin.conf
new file mode 100644
index 0000000..71df193
--- /dev/null
+++ b/src/main/python/plugins/oiip/xml/plugin.conf
@@ -0,0 +1,11 @@
+[solr]
+datasetUrl=http://localhost:8983/solr/attribute
+entriesPerPage=2000
+maxEntriesPerPage=2000
+defaultSearchParam=keyword
+parameters=keyword,necessity,source
+facets={}
+
+[service]
+url=http://localhost:8890
+template=template.xml

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/oiip/xml/template.xml
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/oiip/xml/template.xml b/src/main/python/plugins/oiip/xml/template.xml
new file mode 100755
index 0000000..9fd1ef7
--- /dev/null
+++ b/src/main/python/plugins/oiip/xml/template.xml
@@ -0,0 +1,14 @@
+<?xml version='1.0' encoding='utf-8'?>
+<globalMetadataItems>
+{% for doc in docs %}
+<globalMetadataItem>
+<displayName>{{ ' '.join(doc['name'].split('_')).title() }}</displayName>
+<tagName>{{ doc['name'] }}</tagName>
+{% if doc['necessity'] == 'required' %}
+<isRequired>true</isRequired>
+{% endif %}
+<description>{{ doc['description'] }}</description>
+<metadataType>{{ doc['category'] }}</metadataType>
+</globalMetadataItem>
+{% endfor %}
+</globalMetadataItems>

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/passthrough/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/passthrough/__init__.py b/src/main/python/plugins/passthrough/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/passthrough/pt/PassThroughWriter.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/passthrough/pt/PassThroughWriter.py b/src/main/python/plugins/passthrough/pt/PassThroughWriter.py
new file mode 100644
index 0000000..f4785b7
--- /dev/null
+++ b/src/main/python/plugins/passthrough/pt/PassThroughWriter.py
@@ -0,0 +1,105 @@
+import logging
+import urllib2
+import urlparse
+
+import requestresponder
+from edge.httputility import HttpUtility
+
+class PassThroughWriter(requestresponder.RequestResponder):
+    def __init__(self, configFilePath):
+        super(PassThroughWriter, self).__init__(configFilePath)
+
+    def get(self, requestHandler):
+        super(PassThroughWriter, self).get(requestHandler)
+        url = None
+        try:
+            url = requestHandler.get_argument('url')
+        except:
+            raise Exception('Missing url.')
+
+        if self._isAllowed(url) == False:
+            raise Exception('Not allowed to connect to that url: '+url)
+
+        #io = None
+        try:
+            """
+            logging.debug('url: '+url)
+            io = urllib2.urlopen(url)
+
+            message = io.info()
+            for headerEntry in message.headers:
+                pair = headerEntry.split(':')
+                logging.debug('key: '+pair[0]+', value: '+pair[1].replace('\r\n', ''))
+                requestHandler.set_header(pair[0], pair[1].replace('\r\n', ''))
+
+            while True:
+                data = io.read()
+                if data == '':
+                    break
+                else:
+                    requestHandler.write(data)
+            """
+            
+            httpUtility = HttpUtility()
+            result = httpUtility.getResponse(url, self.onResponse)
+            """
+            for header in result['header']:
+                logging.debug('header: '+header[0]+':'+header[1])
+                requestHandler.set_header(header[0], header[1])
+
+            requestHandler.write(result['data'])
+            """
+        except BaseException as exception:
+            raise exception
+        """
+        finally:
+            if io is not None:
+                io.close()
+        """
+
+    def onResponse(self, response):
+        if response.error:
+            self.requestHandler.set_status(404)
+            self.requestHandler.write(str(response.error))
+            self.requestHandler.finish()
+        else:
+            for name, value in response.headers.iteritems():
+                logging.debug('header: '+name+':'+value)
+                self.requestHandler.set_header(name, value)
+            self.requestHandler.set_header('Access-Control-Allow-Origin', '*')
+            self.requestHandler.write(response.body)
+            self.requestHandler.finish()
+        
+    def _isAllowed(self, url):
+        allow = self._configuration.get('service', 'allow')
+        allows = allow.split(',')
+        for i in range(len(allows)):
+            allows[i] = allows[i].strip()
+
+        """
+        for value in allows:
+            logging.debug('allow: '+value)
+        """
+
+        segments = urlparse.urlparse(url)
+        netlocation = segments.netloc
+
+        targets = [netlocation]
+        netlocations = netlocation.split(':')
+        if len(netlocations) == 2:
+            if netlocations[1] == '80':
+                targets.append(netlocations[0])
+
+        """
+        for element in targets:
+            logging.debug('target: '+element)
+        """
+
+        isAllowed = False
+        for target in targets:
+            for element in allows:
+                if target == element:
+                    isAllowed = True
+                    break
+
+        return isAllowed

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/passthrough/pt/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/passthrough/pt/__init__.py b/src/main/python/plugins/passthrough/pt/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/passthrough/pt/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/passthrough/pt/plugin.conf b/src/main/python/plugins/passthrough/pt/plugin.conf
new file mode 100644
index 0000000..181a0f2
--- /dev/null
+++ b/src/main/python/plugins/passthrough/pt/plugin.conf
@@ -0,0 +1,2 @@
+[service]
+allow=localhost:9200, msas-es.jpl.nasa.gov

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/product/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/product/__init__.py b/src/main/python/plugins/product/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/product/atom/AtomWriter.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/product/atom/AtomWriter.py b/src/main/python/plugins/product/atom/AtomWriter.py
new file mode 100644
index 0000000..babef98
--- /dev/null
+++ b/src/main/python/plugins/product/atom/AtomWriter.py
@@ -0,0 +1,27 @@
+import logging
+import datetime
+
+from edge.elasticsearch.opensearch.granuleatomresponse import GranuleAtomResponse
+from edge.elasticsearch.granulewriter import GranuleWriter
+
+class AtomWriter(GranuleWriter):
+    
+    def __init__(self, configFilePath):
+        super(AtomWriter, self).__init__(configFilePath, [['identifier']])
+
+    def _generateOpenSearchResponse(self, solrResponse, searchText, searchUrl, searchParams, pretty):
+        response = GranuleAtomResponse(
+            self._configuration.get('service', 'linkToGranule'),
+            self._configuration.get('service', 'host'),
+            self._configuration.get('service', 'url')
+        )
+
+        response.title = 'GIBS Product Search Results'
+        #response.description = 'Search result for "'+searchText+'"'
+        response.link = searchUrl
+        response.authors.append('GIBS Product Search Service')
+        response.updated = datetime.datetime.utcnow().isoformat()+'Z'
+        response.id = 'tag:'+self._configuration.get('service', 'host')+','+datetime.datetime.utcnow().date().isoformat()
+        response.parameters = searchParams
+
+        return response.generate(solrResponse, pretty) 

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/product/atom/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/product/atom/Writer.py b/src/main/python/plugins/product/atom/Writer.py
new file mode 100644
index 0000000..f4e085f
--- /dev/null
+++ b/src/main/python/plugins/product/atom/Writer.py
@@ -0,0 +1,71 @@
+import logging
+import os
+import os.path
+import urllib
+
+from edge.writer.solrtemplateresponsewriter import SolrTemplateResponseWriter
+from edge.opensearch.solrcmrtemplateresponse import SolrCmrTemplateResponse
+
+class Writer(SolrTemplateResponseWriter):
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)
+
+        templatePath = os.path.dirname(configFilePath) + os.sep
+        templatePath += self._configuration.get('service', 'template')
+        self.template = self._readTemplate(templatePath)
+
+    def _generateOpenSearchResponse(self, solrResponse, searchText, searchUrl, searchParams, pretty):
+
+        response = SolrCmrTemplateResponse(self._configuration, searchUrl, searchParams)
+        response.setTemplate(self.template)
+        response.variables['serviceUrl'] = self._configuration.get('service', 'url')
+
+        return response.generate(solrResponse, pretty=pretty)
+
+    def _constructSolrQuery(self, startIndex, entriesPerPage, parameters, facets):
+        queries = []
+        filterQueries = []
+
+        for key, value in parameters.iteritems():
+            if key == 'keyword':
+                logging.debug('product/atom/Writer.py: keyword='+value)
+                queries.append(urllib.quote(value))
+            elif key == 'product_pt_id':
+                filterQueries.append(key + ':' + self._urlEncodeSolrQueryValue(value))
+            elif key == 'startTime':
+                queries.append('EndingDateTime:['+value+'%20TO%20*]')
+            elif key == 'endTime':
+                queries.append('BeginningDateTime:[*%20TO%20'+value+']')
+            elif key == 'bbox':
+                coordinates = value.split(",")
+                filterQueries.append('Spatial-Geometry:[' + coordinates[1] + ',' + coordinates[0] + '%20TO%20' + coordinates[3] + ',' + coordinates[2] + ']')
+            elif key == 'id':
+                queries.append('id:' + self._urlEncodeSolrQueryValue(value))
+
+        for key, value in facets.iteritems():
+            if type(value) is list:
+                if (len(value) == 1):
+                    filterQueries.append(key + ':' + self._urlEncodeSolrQueryValue(value[0]))
+                else:
+                    filterQueries.append(key + ':(' + '+OR+'.join([ self._urlEncodeSolrQueryValue(x) for x in value ]) + ")")
+            else:    
+                filterQueries.append(key + ':' + self._urlEncodeSolrQueryValue(value))
+
+        if len(queries) == 0:
+            queries.append('*:*')
+
+        query = 'q='+'+AND+'.join(queries)+'&version=2.2&indent=on&wt=json'
+
+        if len(filterQueries) > 0:
+            query += '&fq='+'+AND+'.join(filterQueries)
+        
+        if self.facet:
+            query += '&rows=0&facet=true&facet.limit=-1&facet.mincount=1&'
+            query += '&'.join(['facet.field=' + facet for facet in self._configuration.get('solr', 'facets').split(',')])
+        else:
+            query += '&start='+str(startIndex)+'&rows='+str(entriesPerPage)
+            query += '&sort=' + self._configuration.get('solr', 'sort')
+
+        logging.debug('solr query: '+query)
+
+        return query

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/product/atom/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/product/atom/__init__.py b/src/main/python/plugins/product/atom/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/product/atom/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/product/atom/plugin.conf b/src/main/python/plugins/product/atom/plugin.conf
new file mode 100644
index 0000000..4644a51
--- /dev/null
+++ b/src/main/python/plugins/product/atom/plugin.conf
@@ -0,0 +1,12 @@
+[solr]
+datasetUrl=http://localhost:8983/solr/product
+entriesPerPage=10
+maxEntriesPerPage=2000
+defaultSearchParam=keyword
+parameters=keyword,product_pt_id,startTime,endTime,bbox,id
+facets={}
+sort=product_name+asc
+
+[service]
+url=http://localhost:8890
+template=template.xml

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/product/atom/template.xml
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/product/atom/template.xml b/src/main/python/plugins/product/atom/template.xml
new file mode 100644
index 0000000..f92eeca
--- /dev/null
+++ b/src/main/python/plugins/product/atom/template.xml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed esipdiscovery:version="1.2"
+      xmlns="http://www.w3.org/2005/Atom"
+      xmlns:dc="http://purl.org/dc/terms/"
+      xmlns:echo="http://www.echo.nasa.gov/esip"
+      xmlns:gibs="http://gibs.jpl.nasa.gov/esip" 
+      xmlns:esipdiscovery="http://commons.esipfed.org/ns/discovery/1.2/"
+      xmlns:georss="http://www.georss.org/georss/10"
+      xmlns:gml="http://www.opengis.net/gml"
+      xmlns:os="http://a9.com/-/spec/opensearch/1.1/"
+      xmlns:time="http://a9.com/-/opensearch/extensions/time/1.0/">
+   <updated>{{ updated }}</updated>
+   <id>https://api.echo.nasa.gov:443/opensearch/datasets.atom</id>
+   <author>
+      <name>GIBS</name>
+      <email>support@echo.nasa.gov</email>
+   </author>
+   <title type="text">GIBS Product Metadata</title>
+   <os:totalResults>{{ numFound }}</os:totalResults>
+   <os:itemsPerPage>{{ itemsPerPage }}</os:itemsPerPage>
+   <os:startIndex>{{ startIndex }}</os:startIndex>
+   <os:Query role="request"
+             xmlns:echo="http://www.echo.nasa.gov/esip"
+             xmlns:geo="http://a9.com/-/opensearch/extensions/geo/1.0/"
+             xmlns:time="http://a9.com/-/opensearch/extensions/time/1.0/" />
+   <subtitle type="text">Search parameters: None</subtitle>
+   <link href="{{ myself }}" hreflang="en-US" rel="self" type="application/atom+xml" />
+   {% if last %}<link href="{{ last }}" hreflang="en-US" rel="last" type="application/atom+xml" />{% endif %}
+   {% if prev %}<link href="{{ prev }}" hreflang="en-US" rel="previous" type="application/atom+xml" />{% endif %}
+   {% if next %}<link href="{{ next }}" hreflang="en-US" rel="next" type="application/atom+xml" />{% endif %}
+   {% if first %}<link href="{{ first }}" hreflang="en-US" rel="first" type="application/atom+xml" />{% endif %}
+   <link href="https://wiki.earthdata.nasa.gov/display/echo/Open+Search+API+release+information"
+         hreflang="en-US" rel="describedBy" title="Release Notes" type="text/html" />
+   {% for doc in docs %}
+      <entry>
+         <id>{{ link }}?id={{ doc['product_id'] }}</id>
+         <dc:identifier>{{ doc['product_name'] }}</dc:identifier>
+         <author>
+            <name>GIBS</name>
+            <email>support@echo.nasa.gov</email>
+         </author>
+         <title type="text">{{ doc['product_name'] }}</title>
+         <summary type="text">{{ 'summary: ' + doc['product_name'] }}</summary>
+         <updated>{{ doc['product_meta_history_last_revision_date_string'] }}</updated>
+         <echo:shortName>{{ doc['product_name'] }}</echo:shortName>
+         <echo:longName>{{ doc['product_root_path'] + '/' + doc['product_name'] }}</echo:longName>
+         <echo:versionId>{{ doc['product_version'] }}</echo:versionId>
+         {% for i in range(doc['product_granule_dataset_id_list']|count)  %}
+            <gibs:cmr>
+               {% if doc['cmr_dataset_id'] %}<echo:datasetId>{{ doc['cmr_dataset_id'][i] }}</echo:datasetId>
+               {% else %}<echo:datasetId />{% endif %}
+               {% if doc['cmr_title'] %}<echo:description>{{ doc['cmr_title'][i] + ' : ' + doc['cmr_time_start'][i] + ' to ' +  doc['cmr_time_end'][i]}}</echo:description>
+               {% else %}<echo:description />{% endif %}
+               {% if doc['cmr_updated'] %}<echo:lastUpdate>{{ doc['cmr_updated'][i] }}</echo:lastUpdate>
+               {% else %}<echo:lastUpdate />{% endif %}
+               {% if doc['cmr_data_center'] %}<echo:dataCenter>{{ doc['cmr_data_center'][i] }}</echo:dataCenter>
+               {% else %}<echo:dataCenter />{% endif %}
+               {% if doc['cmr_original_format'] %}<echo:originalFormat>{{ doc['cmr_original_format'][i] }}</echo:originalFormat>
+               {% else %}<echo:originalFormat />{% endif %}
+               {% if doc['cmr_coordinate_system'] %}<echo:coordinateSystem>{{ doc['cmr_coordinate_system'][i] }}</echo:coordinateSystem>
+               {% else %}<echo:coordinateSystem />{% endif %}
+               {% if doc['cmr_online_access_flag'] %}<echo:onlineAccessFlag>{{ doc['cmr_online_access_flag'][i] }}</echo:onlineAccessFlag>
+               {% else %}<echo:onlineAccessFlag />{% endif %}
+               {% if doc['cmr_browse_flag'] %}<echo:browseFlag>{{ doc['cmr_browse_flag'][i] }}</echo:browseFlag>
+               {% else %}<echo:browseFlag />{% endif %}
+               {% if doc['cmr_boxes'] %}
+                  {% for box in doc['cmr_boxes'][i] %}
+                     <georss:box>{{ box }}</georss:box>
+                  {% endfor %}
+               {% else %}<georss:box />{% endif %}
+               {% if doc['cmr_links'] %}
+                  {% for cmr_link in doc['cmr_links'][i] %}
+                     <link href="{{ cmr_link['href'] }}" hreflang="en-US" rel="enclosure" title="{{ cmr_link['title'] }}" />
+                  {% endfor %}
+               {% endif %} 
+             </gibs:cmr>
+         {% endfor %}
+      <link href="{{ serviceUrl }}/ws/search/product?id={{ doc['id'] }}&amp;pretty=true"
+            hreflang="en-US" rel="enclosure" title="Product Search" type="application/xml" pretty="true" />  
+      <link href="{{ serviceUrl }}/ws/metadata/product?id={{ doc['id'] }}&amp;pretty=true"
+            hreflang="en-US" rel="alternate" title="Product metadata" type="application/xml" />
+      <dc:date>{{ doc['product_start_time_string'] }}/{{ doc['product_end_time_string'] }}</dc:date>
+   </entry>
+   {% endfor %}
+</feed>

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/product/iso/Writer.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/product/iso/Writer.py b/src/main/python/plugins/product/iso/Writer.py
new file mode 100644
index 0000000..a90552e
--- /dev/null
+++ b/src/main/python/plugins/product/iso/Writer.py
@@ -0,0 +1,38 @@
+import logging
+import os
+import os.path
+
+from edge.writer.solrtemplateresponsewriter import SolrTemplateResponseWriter
+from edge.opensearch.solrtemplateresponse import SolrTemplateResponse
+
+class Writer(SolrTemplateResponseWriter):
+    def __init__(self, configFilePath):
+        super(Writer, self).__init__(configFilePath)
+
+        templatePath = os.path.dirname(configFilePath) + os.sep
+        templatePath += self._configuration.get('service', 'template')
+        self.template = self._readTemplate(templatePath)
+
+    def _generateOpenSearchResponse(self, solrResponse, searchText, searchUrl, searchParams, pretty):
+
+        print "iso product:seachParams = [%s]\n" %searchParams
+
+        response = SolrTemplateResponse(self._configuration, searchUrl, searchParams)
+        response.setTemplate(self.template)
+
+        return response.generate(solrResponse, pretty=pretty)
+
+    def _constructSolrQuery(self, startIndex, entriesPerPage, parameters, facets):
+        queries = []
+
+        for key, value in parameters.iteritems():
+            if key == 'id':
+                queries.append('id:' + self._urlEncodeSolrQueryValue(value))
+            elif key == 'title':
+                queries.append('product_type_title:' + self._urlEncodeSolrQueryValue(value))
+
+        query = 'q='+'+AND+'.join(queries)+'&version=2.2&indent=on&wt=json'+'&rows='+str(entriesPerPage)
+
+        logging.debug('solr query: '+query)
+
+        return query

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/product/iso/__init__.py
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/product/iso/__init__.py b/src/main/python/plugins/product/iso/__init__.py
new file mode 100644
index 0000000..e69de29

http://git-wip-us.apache.org/repos/asf/incubator-sdap-edge/blob/53351bf3/src/main/python/plugins/product/iso/plugin.conf
----------------------------------------------------------------------
diff --git a/src/main/python/plugins/product/iso/plugin.conf b/src/main/python/plugins/product/iso/plugin.conf
new file mode 100644
index 0000000..d40c358
--- /dev/null
+++ b/src/main/python/plugins/product/iso/plugin.conf
@@ -0,0 +1,8 @@
+[solr]
+datasetUrl=http://localhost:8983/solr/product
+entriesPerPage=1
+parameters=id,title
+
+[service]
+url=http://localhost:8890
+template=template.xml