001    // $HeadURL:
002    // /deegreerepository/deegree/src/org/deegree/model/filterencoding/XMLFactory.java,v
003    // 1.1.1.1 2005/01/05 10:34:46 poth Exp $
004    /*----------------------------------------------------------------------------
005     This file is part of deegree, http://deegree.org/
006     Copyright (C) 2001-2009 by:
007       Department of Geography, University of Bonn
008     and
009       lat/lon GmbH
010    
011     This library is free software; you can redistribute it and/or modify it under
012     the terms of the GNU Lesser General Public License as published by the Free
013     Software Foundation; either version 2.1 of the License, or (at your option)
014     any later version.
015     This library is distributed in the hope that it will be useful, but WITHOUT
016     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
017     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
018     details.
019     You should have received a copy of the GNU Lesser General Public License
020     along with this library; if not, write to the Free Software Foundation, Inc.,
021     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022    
023     Contact information:
024    
025     lat/lon GmbH
026     Aennchenstr. 19, 53177 Bonn
027     Germany
028     http://lat-lon.de/
029    
030     Department of Geography, University of Bonn
031     Prof. Dr. Klaus Greve
032     Postfach 1147, 53001 Bonn
033     Germany
034     http://www.geographie.uni-bonn.de/deegree/
035    
036     e-mail: info@deegree.org
037    ----------------------------------------------------------------------------*/
038    package org.deegree.model.filterencoding;
039    
040    import java.io.StringReader;
041    import java.net.URI;
042    
043    import org.deegree.datatypes.QualifiedName;
044    import org.deegree.framework.xml.XMLException;
045    import org.deegree.framework.xml.XMLTools;
046    import org.deegree.model.filterencoding.capabilities.FilterCapabilities;
047    import org.deegree.model.filterencoding.capabilities.Function;
048    import org.deegree.model.filterencoding.capabilities.IdCapabilities;
049    import org.deegree.model.filterencoding.capabilities.Operator;
050    import org.deegree.model.filterencoding.capabilities.OperatorFactory100;
051    import org.deegree.model.filterencoding.capabilities.ScalarCapabilities;
052    import org.deegree.model.filterencoding.capabilities.SpatialCapabilities;
053    import org.deegree.model.filterencoding.capabilities.SpatialOperator;
054    import org.deegree.ogcbase.CommonNamespaces;
055    import org.w3c.dom.Document;
056    import org.w3c.dom.Element;
057    
058    /**
059     *
060     *
061     *
062     * @version $Revision: 18195 $
063     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
064     * @author last edited by: $Author: mschneider $
065     *
066     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
067     */
068    public class XMLFactory {
069    
070        private static URI OGCNS = CommonNamespaces.OGCNS;
071    
072        /**
073         * Appends the DOM representation of the <code>FilterCapabilities</code> to the passed
074         * <code>Element</code>. Generated DOM structure fulfills
075         * <code>Filter Encoding Specification 1.0.0</code>.
076         *
077         * @param root
078         * @param filterCapabilities
079         */
080        public static void appendFilterCapabilities100( Element root, FilterCapabilities filterCapabilities ) {
081    
082            Element filterCapabilitiesNode = XMLTools.appendElement( root, OGCNS, "ogc:Filter_Capabilities" );
083            Element spatialCapabilitiesNode = XMLTools.appendElement( filterCapabilitiesNode, OGCNS,
084                                                                      "ogc:Spatial_Capabilities" );
085            Element spatialOperationsNode = XMLTools.appendElement( spatialCapabilitiesNode, OGCNS, "ogc:Spatial_Operators" );
086            SpatialCapabilities spatialCapabilities = filterCapabilities.getSpatialCapabilities();
087            String[] operators = new String[] { OperatorFactory100.OPERATOR_BBOX, OperatorFactory100.OPERATOR_EQUALS,
088                                               OperatorFactory100.OPERATOR_DISJOINT, OperatorFactory100.OPERATOR_INTERSECT,
089                                               OperatorFactory100.OPERATOR_TOUCHES, OperatorFactory100.OPERATOR_CROSSES,
090                                               OperatorFactory100.OPERATOR_WITHIN, OperatorFactory100.OPERATOR_CONTAINS,
091                                               OperatorFactory100.OPERATOR_OVERLAPS, OperatorFactory100.OPERATOR_BEYOND,
092                                               OperatorFactory100.OPERATOR_DWITHIN };
093            for ( int i = 0; i < operators.length; i++ ) {
094                if ( spatialCapabilities.hasOperator( operators[i] ) ) {
095                    XMLTools.appendElement( spatialOperationsNode, OGCNS, "ogc:" + operators[i] );
096                }
097            }
098            Element scalarCapabilitiesNode = XMLTools.appendElement( filterCapabilitiesNode, OGCNS,
099                                                                     "ogc:Scalar_Capabilities" );
100            ScalarCapabilities scalarCapabilities = filterCapabilities.getScalarCapabilities();
101            if ( scalarCapabilities.hasLogicalOperatorsSupport() ) {
102                XMLTools.appendElement( scalarCapabilitiesNode, OGCNS, "ogc:"
103                                                                       + OperatorFactory100.OPERATOR_LOGICAL_OPERATORS );
104            }
105    
106            if ( scalarCapabilities.getComparisonOperators().length > 0 ) {
107    
108                Element operatorsNode = XMLTools.appendElement( scalarCapabilitiesNode, OGCNS, "ogc:Comparison_Operators" );
109                operators = new String[] { OperatorFactory100.OPERATOR_SIMPLE_COMPARISONS,
110                                          OperatorFactory100.OPERATOR_LIKE, OperatorFactory100.OPERATOR_BETWEEN,
111                                          OperatorFactory100.OPERATOR_NULL_CHECK };
112                for ( int i = 0; i < operators.length; i++ ) {
113                    if ( scalarCapabilities.hasComparisonOperator( operators[i] ) ) {
114                        XMLTools.appendElement( operatorsNode, OGCNS, "ogc:" + operators[i] );
115                    }
116                }
117            }
118            // 'ogc:Arithmetic_Operators'-element
119            if ( scalarCapabilities.getArithmeticOperators().length > 0 ) {
120                Element operatorsNode = XMLTools.appendElement( scalarCapabilitiesNode, OGCNS, "ogc:Arithmetic_Operators" );
121                // 'ogc:Simple_Arithmetic'-element
122                int hasFunctions = 1;
123                if ( scalarCapabilities.hasArithmeticOperator( OperatorFactory100.OPERATOR_SIMPLE_ARITHMETIC ) ) {
124                    XMLTools.appendElement( operatorsNode, OGCNS, "ogc:" + OperatorFactory100.OPERATOR_SIMPLE_ARITHMETIC );
125                    hasFunctions = 2;
126                }
127                // 'ogc:Functions'-element
128                Operator[] arithmeticOperators = scalarCapabilities.getArithmeticOperators();
129                if ( arithmeticOperators.length >= hasFunctions ) {
130                    Element functionsNode = XMLTools.appendElement( operatorsNode, OGCNS,
131                                                                    "ogc:" + OperatorFactory100.OPERATOR_FUNCTIONS, null );
132                    for ( int i = 0; i < arithmeticOperators.length; i++ ) {
133                        if ( arithmeticOperators[i] instanceof Function ) {
134                            Function function = (Function) arithmeticOperators[i];
135                            Element functionNode = XMLTools.appendElement( functionsNode, OGCNS, "ogc:Function_Name" );
136                            functionNode.setAttribute( "nArgs", "" + function.getArgumentCount() );
137                        }
138                    }
139                }
140            }
141        }
142    
143        /**
144         * Appends the DOM representation of the <code>FilterCapabilities</code> to the passed
145         * <code>Element</code>. Generated DOM structure fulfills
146         * <code>Filter Encoding Specification 1.1.0</code>.
147         *
148         * @param root
149         * @param filterCapabilities
150         */
151        public static void appendFilterCapabilities110( Element root, FilterCapabilities filterCapabilities ) {
152            Element filterCapabilitiesNode = XMLTools.appendElement( root, OGCNS, "ogc:Filter_Capabilities" );
153            appendSpatialCapabilities110( filterCapabilitiesNode, filterCapabilities.getSpatialCapabilities() );
154            appendScalarCapabilities110( filterCapabilitiesNode, filterCapabilities.getScalarCapabilities() );
155            appendIdCapabilities110( filterCapabilitiesNode, filterCapabilities.getIdCapabilities() );
156        }
157    
158        /**
159         * Appends the DOM representation of the <code>SpatialCapabilities</code> to the passed
160         * <code>Element</code>. Generated DOM structure fulfills
161         * <code>Filter Encoding Specification 1.1.0</code>.
162         *
163         * @param root
164         * @param spatialCapabilities
165         */
166        public static void appendSpatialCapabilities110( Element root, SpatialCapabilities spatialCapabilities ) {
167            Element spatialCapabilitiesNode = XMLTools.appendElement( root, OGCNS, "ogc:Spatial_Capabilities" );
168            QualifiedName[] geometryOperands = spatialCapabilities.getGeometryOperands();
169            if ( geometryOperands != null && geometryOperands.length > 0 ) {
170                appendGeometryOperands( spatialCapabilitiesNode, geometryOperands );
171            } else {
172                // default behavior to ensure that a valid filter capabilities element will be generated
173                Element geometryOperandsNode = XMLTools.appendElement( spatialCapabilitiesNode, OGCNS,
174                                                                       "ogc:GeometryOperands" );
175                XMLTools.appendElement( geometryOperandsNode, OGCNS, "ogc:GeometryOperand", "gml:Envelope" );
176    
177            }
178            SpatialOperator[] spatialOperators = spatialCapabilities.getSpatialOperators();
179            Element spatialOperatorsNode = XMLTools.appendElement( spatialCapabilitiesNode, OGCNS, "ogc:SpatialOperators" );
180            for ( int i = 0; i < spatialOperators.length; i++ ) {
181                Element spatialOperatorNode = XMLTools.appendElement( spatialOperatorsNode, OGCNS, "ogc:SpatialOperator" );
182                spatialOperatorNode.setAttribute( "name", spatialOperators[i].getName() );
183                geometryOperands = spatialOperators[i].getGeometryOperands();
184                if ( geometryOperands != null && geometryOperands.length > 0 ) {
185                    appendGeometryOperands( spatialOperatorsNode, geometryOperands );
186                }
187            }
188        }
189    
190        /**
191         * Appends the DOM representation of the <code>SpatialCapabilities</code> to the passed
192         * <code>Element</code>. Generated DOM structure fulfills
193         * <code>Filter Encoding Specification 1.1.0</code>.
194         *
195         * @param root
196         * @param geometryOperands
197         */
198        public static void appendGeometryOperands( Element root, QualifiedName[] geometryOperands ) {
199            Element geometryOperandsNode = XMLTools.appendElement( root, OGCNS, "ogc:GeometryOperands" );
200            for ( int i = 0; i < geometryOperands.length; i++ ) {
201                XMLTools.appendElement( geometryOperandsNode, OGCNS, "ogc:GeometryOperand",
202                                        geometryOperands[i].getPrefixedName() );
203            }
204        }
205    
206        /**
207         * Appends the DOM representation of the <code>ScalarCapabilities</code> to the passed
208         * <code>Element</code>. Generated DOM structure fulfills
209         * <code>Filter Encoding Specification 1.1.0</code>.
210         *
211         * @param root
212         * @param scalarCapabilities
213         */
214        public static void appendScalarCapabilities110( Element root, ScalarCapabilities scalarCapabilities ) {
215    
216            Element scalarCapabilitiesNode = XMLTools.appendElement( root, OGCNS, "ogc:Scalar_Capabilities" );
217            if ( scalarCapabilities.hasLogicalOperatorsSupport() ) {
218                XMLTools.appendElement( scalarCapabilitiesNode, OGCNS, "ogc:LogicalOperators" );
219            }
220            Operator[] comparisonOperators = scalarCapabilities.getComparisonOperators();
221            if ( comparisonOperators != null ) {
222                Element comparisonOperatorsNode = XMLTools.appendElement( scalarCapabilitiesNode, OGCNS,
223                                                                          "ogc:ComparisonOperators" );
224                for ( int i = 0; i < comparisonOperators.length; i++ ) {
225                    XMLTools.appendElement( comparisonOperatorsNode, OGCNS, "ogc:ComparisonOperator",
226                                            comparisonOperators[i].getName() );
227                }
228            }
229            Operator[] arithmeticOperators = scalarCapabilities.getArithmeticOperators();
230            if ( arithmeticOperators != null ) {
231                Element arithmeticOperatorsNode = XMLTools.appendElement( scalarCapabilitiesNode, OGCNS,
232                                                                          "ogc:ArithmeticOperators" );
233                XMLTools.appendElement( arithmeticOperatorsNode, OGCNS, "ogc:SimpleArithmetic" );
234    
235                boolean functionAvailable = false;
236                for ( int i = 0; i < arithmeticOperators.length; i++ ) {
237                    if ( arithmeticOperators[i] instanceof Function ) {
238                        functionAvailable = true;
239                    }
240                }
241    
242                if ( functionAvailable ) {
243                    Element functionsNode = XMLTools.appendElement( arithmeticOperatorsNode, OGCNS, "ogc:Functions" );
244                    Element functionNamesNode = XMLTools.appendElement( functionsNode, OGCNS, "ogc:FunctionNames" );
245                    for ( int i = 0; i < arithmeticOperators.length; i++ ) {
246                        if ( arithmeticOperators[i] instanceof Function ) {
247                            Function function = (Function) arithmeticOperators[i];
248                            Element functionNameNode = XMLTools.appendElement( functionNamesNode, OGCNS,
249                                                                               "ogc:FunctionName", function.getName() );
250                            functionNameNode.setAttribute( "nArgs", "" + function.getArgumentCount() );
251                        }
252                    }
253                }
254            }
255        }
256    
257        /**
258         * Appends the DOM representation of the <code>IdCapabilities</code> to the passed
259         * <code>Element</code>. Generated DOM structure fulfills
260         * <code>Filter Encoding Specification 1.1.0</code>.
261         *
262         * @param root
263         * @param idCapabilities
264         */
265        public static void appendIdCapabilities110( Element root, IdCapabilities idCapabilities ) {
266            Element idCapabilitiesNode = XMLTools.appendElement( root, OGCNS, "ogc:Id_Capabilities" );
267            if ( idCapabilities != null ) {
268                Element[] eidElements = idCapabilities.getEidElements();
269                for ( int i = 0; i < eidElements.length; i++ ) {
270                    XMLTools.insertNodeInto( eidElements[i], idCapabilitiesNode );
271                }
272                Element[] fidElements = idCapabilities.getFidElements();
273                for ( int i = 0; i < fidElements.length; i++ ) {
274                    XMLTools.insertNodeInto( fidElements[i], idCapabilitiesNode );
275                }
276            } else {
277                // default
278                XMLTools.appendElement( idCapabilitiesNode, OGCNS, "ogc:EID" );
279    
280            }
281        }
282    
283        /**
284         * Appends the DOM representation of the given <code>Filter</code>- section to the passed
285         * <code>Element</code>.
286         *
287         * TODO: Append the DOM-structure "node by node".
288         *
289         * @param root
290         * @param filter
291         *            must not be null
292         * @throws XMLException
293         */
294        public static void appendFilter( Element root, Filter filter )
295                                throws XMLException {
296            String filterString = filter.toXML().toString();
297            try {
298                Document doc = XMLTools.parse( new StringReader( filterString ) );
299                XMLTools.insertNodeInto( doc.getFirstChild(), root );
300            } catch ( Exception e ) {
301                e.printStackTrace();
302                throw new XMLException( "Error appending Filter-expression: " + e.getMessage() );
303            }
304        }
305    }