001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/framework/trigger/TriggerConfigurationDocument.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 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.framework.trigger;
037    
038    import java.io.File;
039    import java.io.IOException;
040    import java.net.MalformedURLException;
041    import java.net.URI;
042    import java.net.URISyntaxException;
043    import java.net.URL;
044    import java.util.ArrayList;
045    import java.util.Date;
046    import java.util.HashMap;
047    import java.util.List;
048    import java.util.Map;
049    
050    import org.deegree.framework.log.ILogger;
051    import org.deegree.framework.log.LoggerFactory;
052    import org.deegree.framework.util.TimeTools;
053    import org.deegree.framework.xml.NamespaceContext;
054    import org.deegree.framework.xml.XMLFragment;
055    import org.deegree.framework.xml.XMLParsingException;
056    import org.deegree.framework.xml.XMLTools;
057    import org.deegree.i18n.Messages;
058    import org.w3c.dom.Element;
059    import org.w3c.dom.Node;
060    import org.xml.sax.SAXException;
061    
062    /**
063     *
064     *
065     *
066     * @version $Revision: 18195 $
067     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
068     * @author last edited by: $Author: mschneider $
069     *
070     * @version 1.0. $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
071     *
072     * @since 2.0
073     */
074    public class TriggerConfigurationDocument extends XMLFragment {
075    
076        private ILogger LOG = LoggerFactory.getLogger( TriggerConfigurationDocument.class );
077    
078        private static NamespaceContext nsc = new NamespaceContext();
079        static {
080            try {
081                nsc.addNamespace( "dgTr", new URI( "http://www.deegree.org/trigger" ) );
082            } catch ( URISyntaxException e ) {
083                // should never happen
084                e.printStackTrace();
085            }
086        }
087    
088        /**
089         * default constructor
090         */
091        public TriggerConfigurationDocument() {
092    
093        }
094    
095        /**
096         * initialized the class by assigning a XML file
097         *
098         * @param file
099         * @throws IOException
100         * @throws SAXException
101         */
102        public TriggerConfigurationDocument( File file ) throws IOException, SAXException {
103            super( file.toURL() );
104        }
105    
106        /**
107         *
108         * @return TriggerCapabilities
109         * @throws XMLParsingException
110         * @throws TriggerException
111         */
112        public TriggerCapabilities parseTriggerCapabilities()
113                                throws XMLParsingException, TriggerException {
114    
115            List list = XMLTools.getNodes( getRootElement(), "dgTr:class", nsc );
116            Map<String, TargetClass> targetClasses = new HashMap<String, TargetClass>( list.size() );
117            for ( int i = 0; i < list.size(); i++ ) {
118                TargetClass tc = parserTargetClass( (Element) list.get( i ) );
119                targetClasses.put( tc.getName(), tc );
120            }
121    
122            return new TriggerCapabilities( targetClasses );
123        }
124    
125        /**
126         *
127         * @param element
128         * @return TargetClass
129         * @throws XMLParsingException
130         * @throws TriggerException
131         */
132        private TargetClass parserTargetClass( Element element )
133                                throws XMLParsingException, TriggerException {
134    
135            String clName = XMLTools.getRequiredNodeAsString( element, "dgTr:name/text()", nsc );
136    
137            List list = XMLTools.getNodes( element, "dgTr:method", nsc );
138            Map<String, TargetMethod> targetMethods = new HashMap<String, TargetMethod>( list.size() );
139            for ( int i = 0; i < list.size(); i++ ) {
140                TargetMethod tm = parseTargetMethod( (Element) list.get( i ) );
141                targetMethods.put( tm.getName(), tm );
142            }
143    
144            return new TargetClass( clName, targetMethods );
145        }
146    
147        /**
148         *
149         * @param element
150         * @return TargetMethod
151         * @throws XMLParsingException
152         * @throws TriggerException
153         */
154        private TargetMethod parseTargetMethod( Element element )
155                                throws XMLParsingException, TriggerException {
156    
157            String mName = XMLTools.getRequiredNodeAsString( element, "dgTr:name/text()", nsc );
158    
159            TriggerCapability preTrigger = null;
160            TriggerCapability postTrigger = null;
161    
162            // it is possible that no trigger is assigned to a method
163            // in this case the present of a method just indicates that
164            // it that Triggers can be assigned to it
165            Node node = XMLTools.getNode( element, "dgTr:preTrigger/dgTr:trigger", nsc );
166            if ( node != null ) {
167                preTrigger = parseTriggerCapability( (Element) node );
168            }
169            node = XMLTools.getNode( element, "dgTr:postTrigger/dgTr:trigger", nsc );
170            if ( node != null ) {
171                postTrigger = parseTriggerCapability( (Element) node );
172            }
173    
174            return new TargetMethod( mName, preTrigger, postTrigger );
175        }
176    
177        /**
178         *
179         * @param element
180         * @return trigger capability
181         * @throws XMLParsingException
182         * @throws TriggerException
183         */
184        private TriggerCapability parseTriggerCapability( Element element )
185                                throws XMLParsingException, TriggerException {
186    
187            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
188                XMLFragment doc = new XMLFragment();
189                doc.setRootElement( element );
190                LOG.logDebug( "Incoming trigger configuration element:\n " + doc.getAsPrettyString() );
191            }
192            // a node (if not null) may represents a simple Trigger or a
193            // TriggerChain (which is a Trigger too)
194            String trName = XMLTools.getRequiredNodeAsString( element, "dgTr:name/text()", nsc );
195            String clName = XMLTools.getRequiredNodeAsString( element, "dgTr:performingClass/text()", nsc );
196            Class clss = null;
197            try {
198                clss = Class.forName( clName );
199                LOG.logDebug( "Found class: " + clss );
200            } catch ( ClassNotFoundException e ) {
201                LOG.logError( e.getMessage(), e );
202                throw new XMLParsingException( Messages.getMessage( "FRAMEWORK_UNKNOWN_TRIGGERCLASS", clName ) );
203            }
204    
205            if ( !Trigger.class.isAssignableFrom( clss ) ) {
206                // class read from the configuration must be an implementation
207                // of org.deegree.framework.trigger.Trigger
208                throw new TriggerException( Messages.getMessage( "FRAMEWORK_INVALID_TRIGGERCLASS", clName ) );
209            }
210    
211            Map<String, Class> paramTypes = new HashMap<String, Class>();
212            Map<String, Object> paramValues = new HashMap<String, Object>();
213            List<String> paramNames = new ArrayList<String>();
214            List initParams = XMLTools.getNodes( element, "dgTr:initParam", nsc );
215            parseInitParams( paramTypes, paramValues, paramNames, initParams );
216    
217            // get nested Trigger capabilities if available
218            List nested = XMLTools.getNodes( element, "dgTr:trigger/dgTr:trigger", nsc );
219            List<TriggerCapability> nestedList = new ArrayList<TriggerCapability>( nested.size() );
220            for ( int i = 0; i < nested.size(); i++ ) {
221                nestedList.add( parseTriggerCapability( (Element) nested.get( i ) ) );
222            }
223    
224            return new TriggerCapability( trName, clss, paramNames, paramTypes, paramValues, nestedList );
225    
226        }
227    
228        /**
229         *
230         * @param paramTypes
231         * @param paramValues
232         * @param paramNames
233         * @param initParams
234         * @throws XMLParsingException
235         */
236        private void parseInitParams( Map<String, Class> paramTypes, Map<String, Object> paramValues,
237                                      List<String> paramNames, List initParams )
238                                throws XMLParsingException {
239            for ( int i = 0; i < initParams.size(); i++ ) {
240                String name = XMLTools.getRequiredNodeAsString( (Node) initParams.get( i ), "dgTr:name/text()", nsc );
241                paramNames.add( name );
242                String tmp = XMLTools.getRequiredNodeAsString( (Node) initParams.get( i ), "dgTr:type/text()", nsc );
243                Class cl = null;
244                try {
245                    cl = Class.forName( tmp );
246                } catch ( ClassNotFoundException e ) {
247                    LOG.logError( e.getMessage(), e );
248                    throw new XMLParsingException( Messages.getMessage( "FRAMEWORK_UNKNOWN_INITPARAMCLASS", tmp ) );
249                }
250                tmp = XMLTools.getRequiredNodeAsString( (Node) initParams.get( i ), "dgTr:value/text()", nsc );
251                Object value = null;
252                try {
253                    value = getValue( cl, tmp );
254                } catch ( MalformedURLException e ) {
255                    LOG.logError( e.getMessage(), e );
256                    throw new XMLParsingException( Messages.getMessage( "FRAMEWORK_TRIGGER_INITPARAM_PARSING", tmp,
257                                                                        cl.getName() ) );
258                }
259                paramTypes.put( name, cl );
260                paramValues.put( name, value );
261            }
262        }
263    
264        /**
265         *
266         * @param type
267         * @param tmp
268         * @return parameter value
269         * @throws MalformedURLException
270         */
271        private Object getValue( Class type, String tmp )
272                                throws MalformedURLException {
273            Object value = null;
274            if ( type.equals( Integer.class ) ) {
275                value = Integer.parseInt( tmp );
276            } else if ( type.equals( Double.class ) ) {
277                value = Double.parseDouble( tmp );
278            } else if ( type.equals( Float.class ) ) {
279                value = Float.parseFloat( tmp );
280            } else if ( type.equals( URL.class ) ) {
281                value = new URL( tmp );
282            } else if ( type.equals( Date.class ) ) {
283                value = TimeTools.createCalendar( tmp ).getTime();
284            } else if ( type.equals( String.class ) ) {
285                value = tmp;
286            }
287            return value;
288        }
289    
290    }