001    //$HeadURL: 
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2010 by:
005     - Department of Geography, University of Bonn -
006     and
007     - lat/lon GmbH -
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035     ----------------------------------------------------------------------------*/
036    package org.deegree.portal.cataloguemanager.control;
037    
038    import java.io.ByteArrayInputStream;
039    import java.io.ByteArrayOutputStream;
040    import java.io.IOException;
041    import java.net.URL;
042    import java.util.Enumeration;
043    import java.util.HashMap;
044    import java.util.List;
045    import java.util.Map;
046    
047    import javax.servlet.http.HttpServletRequest;
048    import javax.xml.bind.JAXBContext;
049    import javax.xml.bind.JAXBException;
050    import javax.xml.bind.Marshaller;
051    import javax.xml.bind.Unmarshaller;
052    
053    import org.apache.commons.httpclient.HttpException;
054    import org.apache.commons.httpclient.HttpMethod;
055    import org.deegree.enterprise.control.ajax.ResponseHandler;
056    import org.deegree.enterprise.control.ajax.WebEvent;
057    import org.deegree.framework.log.ILogger;
058    import org.deegree.framework.log.LoggerFactory;
059    import org.deegree.framework.util.BootLogger;
060    import org.deegree.framework.util.HttpUtils;
061    import org.deegree.framework.util.TimeTools;
062    import org.deegree.framework.xml.XMLFragment;
063    import org.deegree.framework.xml.XMLParsingException;
064    import org.deegree.framework.xml.XMLTools;
065    import org.deegree.model.crs.CRSFactory;
066    import org.deegree.model.crs.CRSTransformationException;
067    import org.deegree.model.crs.CoordinateSystem;
068    import org.deegree.model.spatialschema.Envelope;
069    import org.deegree.model.spatialschema.GeometryFactory;
070    import org.deegree.ogcbase.CommonNamespaces;
071    import org.deegree.portal.cataloguemanager.model.Address;
072    import org.deegree.portal.cataloguemanager.model.CICitation;
073    import org.deegree.portal.cataloguemanager.model.CIDate;
074    import org.deegree.portal.cataloguemanager.model.CIDateTypeCode;
075    import org.deegree.portal.cataloguemanager.model.CIOnlineResource;
076    import org.deegree.portal.cataloguemanager.model.CIResponsibleParty;
077    import org.deegree.portal.cataloguemanager.model.Contact;
078    import org.deegree.portal.cataloguemanager.model.ContactInfo;
079    import org.deegree.portal.cataloguemanager.model.Date;
080    import org.deegree.portal.cataloguemanager.model.DateType;
081    import org.deegree.portal.cataloguemanager.model.DistributionFormat;
082    import org.deegree.portal.cataloguemanager.model.EXExtent;
083    import org.deegree.portal.cataloguemanager.model.EXGeographicBoundingBox;
084    import org.deegree.portal.cataloguemanager.model.EXTemporalExtent;
085    import org.deegree.portal.cataloguemanager.model.ExceptionBean;
086    import org.deegree.portal.cataloguemanager.model.Keyword;
087    import org.deegree.portal.cataloguemanager.model.Linkage;
088    import org.deegree.portal.cataloguemanager.model.MDDataIdentification;
089    import org.deegree.portal.cataloguemanager.model.MDDigitalTransferOptions;
090    import org.deegree.portal.cataloguemanager.model.MDDistribution;
091    import org.deegree.portal.cataloguemanager.model.MDFormat;
092    import org.deegree.portal.cataloguemanager.model.MDLegalConstraints;
093    import org.deegree.portal.cataloguemanager.model.MDMetadata;
094    import org.deegree.portal.cataloguemanager.model.MDReferenceSystem;
095    import org.deegree.portal.cataloguemanager.model.MDRepresentativeFraction;
096    import org.deegree.portal.cataloguemanager.model.MetadataBean;
097    import org.deegree.portal.cataloguemanager.model.Name;
098    import org.deegree.portal.cataloguemanager.model.OnLine;
099    import org.deegree.portal.cataloguemanager.model.ParentIdentifier;
100    import org.deegree.portal.cataloguemanager.model.Phone;
101    import org.deegree.portal.cataloguemanager.model.PointOfContact;
102    import org.deegree.portal.cataloguemanager.model.ResourceConstraints;
103    import org.deegree.portal.cataloguemanager.model.SpatialResolution;
104    import org.deegree.portal.cataloguemanager.model.TimePeriod;
105    import org.deegree.portal.cataloguemanager.model.TransferOptions;
106    import org.deegree.portal.cataloguemanager.model.Version;
107    import org.w3c.dom.Element;
108    import org.xml.sax.SAXException;
109    
110    /**
111     * 
112     * 
113     * 
114     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
115     * @author last edited by: $Author: apoth $
116     * 
117     * @version $Revision: 30690 $, $Date: 2011-05-06 10:23:46 +0200 (Fr, 06 Mai 2011) $
118     */
119    public class InsertMetadataListener extends AbstractMetadataListener {
120    
121        protected static CoordinateSystem crs;
122    
123        static {
124            if ( crs == null ) {
125                try {
126                    crs = CRSFactory.create( "EPSG:4326" );
127                } catch ( Exception e ) {
128                    BootLogger.logError( e.getMessage(), e );
129                }
130            }
131        }
132    
133        private static ILogger LOG = LoggerFactory.getLogger( InsertMetadataListener.class );
134    
135        protected CatalogueManagerConfiguration conf;
136    
137        @Override
138        public void actionPerformed( WebEvent event, ResponseHandler responseHandler )
139                                throws IOException {
140    
141            try {
142                conf = getCatalogueManagerConfiguration( event );
143                MetadataBean bean = (MetadataBean) event.getAsBean();
144                JAXBContext jc = JAXBContext.newInstance( "org.deegree.portal.cataloguemanager.model" );
145                Unmarshaller u = jc.createUnmarshaller();
146    
147                String tmp = conf.getTemplateURL( bean.getHlevel() );
148                URL url = conf.resolve( tmp );
149                MDMetadata mdMetadata = (MDMetadata) u.unmarshal( url );
150    
151                // metadata settings
152                mdMetadata.getFileIdentifier().setCharacterString( bean.getIdentifier() );
153                mdMetadata.getHierarchyLevel().getMDScopeCode().setCodeListValue( bean.getHlevel() );
154                tmp = bean.getHlevel();
155                if ( "series".equalsIgnoreCase( tmp ) ) {
156                    tmp = "datasetcollection";
157                }
158                if ( "dataset".equalsIgnoreCase( tmp ) && bean.getParentId() != null ) {
159                    ParentIdentifier pi = new ParentIdentifier();
160                    pi.setCharacterString( bean.getParentId() );
161                    mdMetadata.setParentIdentifier( pi );
162                }
163                mdMetadata.getHierarchyLevelName().setCharacterString( tmp );
164                setContact( mdMetadata, bean );
165                mdMetadata.getDateStamp().setDateTime( TimeTools.getISOFormattedTime() );
166                if ( bean.getCrs() != null ) {
167                    MDReferenceSystem mdRef = mdMetadata.getReferenceSystemInfo().getMDReferenceSystem();
168                    mdRef.getReferenceSystemIdentifier().getRSIdentifier().getCode().setCharacterString( bean.getCrs() );
169                }
170    
171                // data identification settings
172                MDDataIdentification mdDataId = mdMetadata.getIdentificationInfo().getMDDataIdentification();
173                mdDataId.getAbstract().setCharacterString( bean.getAbstract_() );
174                mdDataId.setUuid( "_" + bean.getIdentifier() );
175                mdDataId.setId( bean.getIdentifier() );
176                setKeywords( mdDataId, bean );
177                setPointOfContact( mdDataId, bean );
178                mdDataId.getTopicCategory().setMDTopicCategoryCode( bean.getTopCat() );
179                setExtent( mdDataId, bean );
180    
181                SpatialResolution spr = mdDataId.getSpatialResolution();
182                if ( bean.getScale() == null || bean.getScale().trim().length() == 0 ) {
183                    mdDataId.setSpatialResolution( null );
184                } else {
185                    MDRepresentativeFraction frac = spr.getMDResolution().getEquivalentScale().getMDRepresentativeFraction();
186                    frac.getDenominator().setInteger( Integer.parseInt( bean.getScale().trim() ) );
187                }
188    
189                CICitation citation = mdDataId.getCitation().getCICitation();
190                citation.getTitle().setCharacterString( bean.getDatasetTitle() );
191                citation.getIdentifier().getMDIdentifier().getCode().setCharacterString( bean.getIdentifier() );
192    
193                // citation dates
194                List<Date> dates = citation.getDate();
195                dates.clear();
196                if ( bean.getCreation() != null ) {
197                    addDate( dates, "creation", bean.getCreation() );
198                }
199                if ( bean.getPublication() != null ) {
200                    addDate( dates, "publication", bean.getPublication() );
201                }
202                if ( bean.getRevision() != null ) {
203                    addDate( dates, "revision", bean.getRevision() );
204                }
205    
206                if ( bean.getTransferOnline() != null && bean.getTransferOnline().trim().length() > 0 ) {
207                    setDistributionInfo( mdMetadata, bean );
208                } else {
209                    mdMetadata.setDistributionInfo( null );
210                }
211    
212                // lineage
213                if ( bean.getLineage() != null && bean.getLineage().trim().length() > 0 ) {
214                    mdMetadata.getDataQualityInfo().getDQDataQuality().getLineage().getLILineage().getStatement().setCharacterString(
215                                                                                                                                      bean.getLineage() );
216                } else {
217                    mdMetadata.setDataQualityInfo( null );
218                }
219    
220                // resource constraints
221                List<ResourceConstraints> list = mdMetadata.getIdentificationInfo().getMDDataIdentification().getResourceConstraints();
222                if ( bean.getAccessConstraints() == null ) {
223                    list.clear();
224                } else {
225                    MDLegalConstraints legal = null;
226                    for ( ResourceConstraints resourceConstraints : list ) {
227                        if ( resourceConstraints.getMDLegalConstraints() != null ) {
228                            legal = resourceConstraints.getMDLegalConstraints();
229                            legal.getAccessConstraints().getMDRestrictionCode().setCodeListValue(
230                                                                                                  bean.getAccessConstraints() );
231                            legal.getAccessConstraints().getMDRestrictionCode().setValue( bean.getAccessConstraints() );
232                        }
233                    }
234                }
235    
236                insertIntoCSW_( responseHandler, mdMetadata );
237    
238            } catch ( Exception e ) {
239                LOG.logError( e.getMessage(), e );
240                ExceptionBean eb = new ExceptionBean( getClass().getName(), e.getMessage() );
241                responseHandler.writeAndClose( true, eb );
242                return;
243            }
244        }
245    
246        private void setDistributionInfo( MDMetadata mdMetadata, MetadataBean bean ) {
247            MDDistribution mddist = mdMetadata.getDistributionInfo().getMDDistribution();
248            if ( mddist == null ) {
249                mddist = new MDDistribution();
250                TransferOptions to = new TransferOptions();
251                MDDigitalTransferOptions dto = new MDDigitalTransferOptions();
252                OnLine ol = new OnLine();
253                CIOnlineResource ciolr = new CIOnlineResource();
254                ciolr.setLinkage( new Linkage() );
255                ol.setCIOnlineResource( ciolr );
256                dto.setOnLine( ol );
257                to.setMDDigitalTransferOptions( dto );
258                mddist.setTransferOptions( to );
259            }
260            MDDigitalTransferOptions to = mddist.getTransferOptions().getMDDigitalTransferOptions();
261            to.getOnLine().getCIOnlineResource().getLinkage().setURL( bean.getTransferOnline() );
262            if ( bean.getTransferFormatName() != null && bean.getTransferFormatName().length() > 0 ) {
263                DistributionFormat format = mdMetadata.getDistributionInfo().getMDDistribution().getDistributionFormat();
264                if ( format == null ) {
265                    format = new DistributionFormat();
266                    MDFormat mdf = new MDFormat();
267                    mdf.setName( new Name() );
268                    mdf.setVersion( new Version() );
269                    format.setMDFormat( mdf );
270                }
271                format.getMDFormat().getName().setCharacterString( bean.getTransferFormatName() );
272                if ( bean.getTransferFormatVersion() != null && bean.getTransferFormatVersion().length() > 0 ) {
273                    format.getMDFormat().getVersion().setCharacterString( bean.getTransferFormatVersion() );
274                } else {
275                    format.getMDFormat().getVersion().setCharacterString( "unknown" );
276                }
277            } else {
278                mdMetadata.getDistributionInfo().getMDDistribution().setDistributionFormat( null );
279            }
280        }
281    
282        @SuppressWarnings("unchecked")
283        private String insertIntoCSW_( ResponseHandler responseHandler, MDMetadata mdMetadata )
284                                throws JAXBException, IOException, HttpException, SAXException, XMLParsingException {
285    
286            JAXBContext jc = JAXBContext.newInstance( "org.deegree.portal.cataloguemanager.model" );
287            Marshaller m = jc.createMarshaller();
288            ByteArrayOutputStream bos = new ByteArrayOutputStream( 10000 );
289            m.marshal( mdMetadata, bos );
290            XMLFragment md = new XMLFragment();
291            md.load( new ByteArrayInputStream( bos.toByteArray() ), XMLFragment.DEFAULT_URL );
292    
293            URL url = getClass().getResource( "insert.xml" );
294            XMLFragment insert = new XMLFragment( url );
295            Element elem = XMLTools.getElement( insert.getRootElement(), "csw202:Insert",
296                                                CommonNamespaces.getNamespaceContext() );
297            XMLTools.copyNode( md.getRootElement().getOwnerDocument(), elem );
298    
299            Enumeration<String> en = ( (HttpServletRequest) getRequest() ).getHeaderNames();
300            Map<String, String> map = new HashMap<String, String>();
301            while ( en.hasMoreElements() ) {
302                String name = (String) en.nextElement();
303                if ( !name.equalsIgnoreCase( "accept-encoding" ) && !name.equalsIgnoreCase( "content-length" )
304                     && !name.equalsIgnoreCase( "user-agent" ) ) {
305                    map.put( name, ( (HttpServletRequest) getRequest() ).getHeader( name ) );
306                }
307            }
308            HttpMethod post = HttpUtils.performHttpPost( conf.getCatalogueURL(), insert, 60000, null, null, map );
309            String s = post.getResponseBodyAsString();
310            if ( s.toLowerCase().indexOf( "exception" ) > -1 ) {
311                ExceptionBean eb = new ExceptionBean( getClass().getName(), "insert failed" );
312                responseHandler.writeAndClose( true, eb );
313            } else {
314                responseHandler.writeAndClose( "insert performed" );
315            }
316    
317            return s;
318        }
319    
320        protected void setContact( MDMetadata mdMetadata, MetadataBean bean ) {
321            Contact contact = mdMetadata.getContact();
322            CIResponsibleParty respParty = contact.getCIResponsibleParty();
323            respParty.getIndividualName().setCharacterString( bean.getContactIndividualName() );
324            respParty.getOrganisationName().setCharacterString( bean.getContactOrganisationName() );
325            respParty.getRole().getCIRoleCode().setCodeListValue( bean.getContactRole() );
326            ContactInfo ci = respParty.getContactInfo();
327            Phone phone = ci.getCIContact().getPhone();
328            phone.getCITelephone().getFacsimile().setCharacterString( bean.getContactFacsimile() );
329            phone.getCITelephone().getVoice().setCharacterString( bean.getContactVoice() );
330            Address address = ci.getCIContact().getAddress();
331            address.getCIAddress().getCity().setCharacterString( bean.getContactCity() );
332            address.getCIAddress().getCountry().setCharacterString( bean.getContactCountry() );
333            address.getCIAddress().getDeliveryPoint().setCharacterString( bean.getContactDeliveryPoint() );
334            address.getCIAddress().getElectronicMailAddress().setCharacterString( bean.getContactEmailAddress() );
335            address.getCIAddress().getPostalCode().setCharacterString( bean.getContactPostalCode() );
336        }
337    
338        protected void setExtent( MDDataIdentification mdDataId, MetadataBean bean )
339                                throws CRSTransformationException {
340            EXExtent extent = mdDataId.getExtent().getEXExtent();
341            extent.getDescription().setCharacterString( getGeogrDesc( bean.getGeogrDescription() ) );
342            EXTemporalExtent te = extent.getTemporalElement().getEXTemporalExtent();
343            TimePeriod tp = te.getExtent().getTimePeriod();
344    
345            tp.setBeginPosition( bean.getBegin() );
346            tp.setEndPosition( bean.getEnd() );
347            EXGeographicBoundingBox bbox = extent.getGeographicElement().getEXGeographicBoundingBox();
348            Envelope env = getEnvelope( bean.getGeogrDescription() );
349            bbox.getWestBoundLongitude().setDecimal( (float) env.getMin().getX() );
350            bbox.getSouthBoundLatitude().setDecimal( (float) env.getMin().getY() );
351            bbox.getEastBoundLongitude().setDecimal( (float) env.getMax().getX() );
352            bbox.getNorthBoundLatitude().setDecimal( (float) env.getMax().getY() );
353        }
354    
355        /**
356         * @param geographicIdentifier
357         * @return
358         */
359        private String getGeogrDesc( String geographicIdentifier ) {
360            List<SpatialExtent> extents = conf.getSpatialExtents();
361            for ( SpatialExtent spatialExtent : extents ) {
362                if ( spatialExtent.getId().equalsIgnoreCase( geographicIdentifier ) ) {
363                    return spatialExtent.getName();
364                }
365            }
366            return "-";
367        }
368    
369        protected Envelope getEnvelope( String geogrDescription )
370                                throws CRSTransformationException {
371            List<SpatialExtent> spatialExtents = conf.getSpatialExtents();
372            String bbox = "-180,-90,180,90";
373            for ( SpatialExtent spatialExtent : spatialExtents ) {
374                if ( spatialExtent.getId().equals( geogrDescription ) ) {
375                    bbox = spatialExtent.getBbox();
376                    break;
377                }
378            }
379            return GeometryFactory.createEnvelope( bbox, crs );
380        }
381    
382        protected void setPointOfContact( MDDataIdentification mdDataId, MetadataBean bean ) {
383            PointOfContact poc = mdDataId.getPointOfContact();
384            CIResponsibleParty respParty = poc.getCIResponsibleParty();
385            respParty.getIndividualName().setCharacterString( bean.getPocIndividualName() );
386            respParty.getOrganisationName().setCharacterString( bean.getPocOrganisationName() );
387            respParty.getRole().getCIRoleCode().setCodeListValue( bean.getPocRole() );
388            ContactInfo ci = respParty.getContactInfo();
389            Phone phone = ci.getCIContact().getPhone();
390            phone.getCITelephone().getFacsimile().setCharacterString( bean.getPocFacsimile() );
391            phone.getCITelephone().getVoice().setCharacterString( bean.getPocVoice() );
392            Address address = ci.getCIContact().getAddress();
393            address.getCIAddress().getCity().setCharacterString( bean.getPocCity() );
394            address.getCIAddress().getCountry().setCharacterString( bean.getPocCountry() );
395            address.getCIAddress().getDeliveryPoint().setCharacterString( bean.getPocDeliveryPoint() );
396            address.getCIAddress().getElectronicMailAddress().setCharacterString( bean.getPocEmailAddress() );
397            address.getCIAddress().getPostalCode().setCharacterString( bean.getPocPostalCode() );
398        }
399    
400        @SuppressWarnings("unchecked")
401        protected void setKeywords( MDDataIdentification mdDataId, MetadataBean bean ) {
402            List<Keyword> list = mdDataId.getDescriptiveKeywords().getMDKeywords().getKeyword();
403            list.clear();
404            List<String> kw = bean.getKeywords();
405            for ( String keyword : kw ) {
406                Keyword key = new Keyword();
407                key.setCharacterString( keyword );
408                list.add( key );
409            }
410            Keyword key = new Keyword();
411            key.setCharacterString( bean.getInspireDataTheme() );
412            list.add( key );
413        }
414    
415        protected void addDate( List<Date> dates, String type, String value ) {
416            Date date = new Date();
417            CIDate cidate = new CIDate();
418            cidate.setDate( date );
419            DateType dt = new DateType();
420            CIDateTypeCode dtc = new CIDateTypeCode();
421            dtc.setCodeList( "http://www.isotc211.org/2005/resources/codeList.xml#CI_DateTypeCode" );
422            dtc.setCodeListValue( type );
423            dt.setCIDateTypeCode( dtc );
424            cidate.setDateType( dt );
425            Date dateValue = new Date();
426            dateValue.setDateTime( value + "T00:00:00Z" );
427            cidate.setDate( dateValue );
428            date.setCIDate( cidate );
429            dates.add( date );
430        }
431    
432    }