Project

General

Profile

« Previous | Next » 

Revision 3118

Added by perry about 18 years ago

Initial architecture for dynamically generating SLD/OGC:Filter documents to control which docids get shown on the map. The sldfactory servlet is in place to handle this but is not fully functional since there is currently no way to quickly and dynamically generate a list of allowable docids with a level of performance acceptable for real-time web mapping.

View differences:

lib/spatial/geoserver/data/styles/data_bounds_style.sld
4 4
	xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" 
5 5
	xmlns:xlink="http://www.w3.org/1999/xlink" 
6 6
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
7
    <UserLayer>
8
    <Name>metacat:data_bounds</Name>
7 9
    <UserStyle>
8 10
        <Name>Default Styler</Name>
9 11
        <Title>Default Styler</Title>
......
47 49
            </Rule>
48 50
        </FeatureTypeStyle>
49 51
    </UserStyle>
52
    </UserLayer>
50 53
</StyledLayerDescriptor>
lib/spatial/geoserver/data/styles/data_points_style.sld
5 5
	xmlns:ogc="http://www.opengis.net/ogc"
6 6
	xmlns:xlink="http://www.w3.org/1999/xlink"
7 7
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
8
        <UserLayer>
9
        <Name>metacat:data_points</Name>
8 10
	<UserStyle>
9 11
		<Name>Default Styler</Name>
10 12
		<Title>Default Styler</Title>
......
58 60
			</Rule>
59 61
		</FeatureTypeStyle>
60 62
	</UserStyle>
63
        </UserLayer>
61 64
</StyledLayerDescriptor>
src/edu/ucsb/nceas/metacat/spatial/SldFactory.java
1
/*
2
 * Styled Layer Descriptor Factory
3
 * Author: Matt Perry
4
 * Status: testing
5
 * MPTODO: Use a spatial access constraints class to generate the appropriate SLD filter
1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000 Regents of the University of California and the
4
 *  National Center for Ecological Analysis and Synthesis
5
 *
6
 *  Author: Matthew Perry
7
 *  '$Date$'
8
 *  '$Revision$'
9
 *
10
 *  This program is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU General Public License as published by
12
 *  the Free Software Foundation; either version 2 of the License, or
13
 *  (at your option) any later version.
14
 *  
15
 *  This program is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU General Public License
21
 *  along with this program; if not, write to the Free Software
22
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 *
24
 *  Purpose: Servlet to generate a styled layer descriptor (SLD)
25
 *           with a filter to restrict features on
26
 *           a WMS map to given docids
27
 *
28
 *  Status: Currently this is just a working stub
29
 *          with some hardcoded values. Since this needs to be
30
 *          fired off on every map redraw, we'll need a way to make 
31
 *          the generation of docid list very efficient. 
32
 *
33
 *  Usage: Append the URL as an "SLD" to any WMS GetMap request
34
 *    ex: http://server/context/wms?...&SLD=http://server/context/sldfactory?originalSld=data_points_style
6 35
 */
36

  
37

  
7 38
package edu.ucsb.nceas.metacat.spatial;
8 39

  
9 40
import edu.ucsb.nceas.utilities.XMLUtilities;
41
import edu.ucsb.nceas.metacat.MetaCatUtil;
10 42

  
11 43
import javax.servlet.ServletConfig;
12 44
import javax.servlet.ServletContext;
......
29 61

  
30 62
import java.io.File;
31 63
import java.io.IOException;
64
import java.io.FileNotFoundException;
32 65

  
66
import java.util.Vector;
67

  
33 68
import org.w3c.dom.*;
34 69

  
35 70
/**
......
73 108
   *
74 109
   * @param request Incoming servlet request.
75 110
   * @param response Servlet response.
76
   * @todo Determine filename from variables in metacat.properties.
77 111
   */
78 112
  private void handleGetOrPost(HttpServletRequest request, HttpServletResponse response)
79 113
  throws ServletException, IOException
80 114
  {
81
    //String dataset = request.getParameter("dataset"); 
82
    // MPTODO : Eventually use dataset to determine filename
83
    String filename = "/var/lib/tomcat5/webapps/knb/style/skins/ebm/spatial/data_bounds_style.sld";
84
    String sld = getSld(filename);
115
    String dataset = request.getParameter("originalSld"); 
116
    String filename = MetaCatUtil.getOption("certPath") + "data/styles/" + dataset;
117
    try {
118
	String sld = getSld(filename);
119
        System.out.println(sld);
120
	response.setContentType("text/xml");
121
	response.getWriter().write(sld);
122
    } catch (FileNotFoundException fnf) {
123
	fnf.printStackTrace();
124
    } catch (Exception e) {
125
        e.printStackTrace();
126
    }
85 127
    
86
    response.setContentType("text/xml");
87
    response.getWriter().write(sld);
88
    
89
    System.out.println("\n*** SldFactory request handled ***\n");
90 128
  }
91 129
  
92 130
  /**
93 131
   * Given a filename of an existing SLD document,
94 132
   * reads the sld and adds an ogc:Filter to exclude/include
95 133
   * certain docids based on user's permissions. 
134
   * The sld file is specified without path and 
135
   * must exist within geoserver's styles folder (context/data/styles/*)
96 136
   * 
97 137
   * returns SLD document as a String.
98 138
   * 
99 139
   * @param filename	Filename of the base sld.
100 140
   * @todo Implement the doc id list queries for contraints.
101 141
   */
102
  private String getSld(String filename)
142
  private String getSld(String filename) throws FileNotFoundException
103 143
  {
104 144
	    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
145
	    Vector allowedDocids = new Vector();
105 146

  
147
	    /*
148
	     * TODO : 
149
	     *  Get the list of allowable docids due to 
150
	     *    access contraints (based on current logged-in user)
151
	     *    skin filtering (eg organization name) 
152
	     *    existing non-spatial query (eg taxonomic query)
153
	     *
154
	     *  These could ideally be cached as session variables to improve
155
	     *  speed over running expensive SQL queries on 
156
	     *  each map redraw.
157
	     *
158
	     * Combined, these will be a vector of allowed docids that
159
	     * are to be displayed on the map
160
	     *
161
	     * Below is just a hardcoded example of the above...
162
	     *
163
	     */
164
	    allowedDocids.add("nceas.288");
165
	    allowedDocids.add("nrs.720");
166

  
167
	    String rulesString = "";
168

  
106 169
	    try {
107
	       DocumentBuilder builder = factory.newDocumentBuilder();
108
	       document = builder.parse( new File(filename) );	       
170
		    DocumentBuilder builder = factory.newDocumentBuilder();
171
		    document = builder.parse( new File(filename) );	       
172
		    Element root = document.getDocumentElement();
173

  
174
		    NodeList elemList = document.getElementsByTagName("Rule");
175
		    Node ruleNode = elemList.item(0);
176

  
177
		    // Get the Element/node comprising the ogc:Filter for all of the above
178
		    Element filterElement = getFilterElement(document,allowedDocids);
179
		    
180
		    // Append the Filter to the ruleNode
181
		    ruleNode.appendChild(filterElement);
182
		    
183
		    // Write new DOM as a string
184
		    rulesString = XMLUtilities.getDOMTreeAsString((Node) root, true);
185

  
109 186
	    } catch (SAXException sxe) {
110 187
	       sxe.printStackTrace();
111 188
	    } catch (ParserConfigurationException pce) {
112 189
	       pce.printStackTrace();
113 190
	    } catch (IOException ioe) {
114 191
	       ioe.printStackTrace();
115
	    }
116
	    
117
	    Element root = document.getDocumentElement();
118
	    NodeList elemList = document.getElementsByTagName("Rule");
119
	    Node ruleNode = elemList.item(0);
120
	    
121
	    // Get the list of docids  due to access contrainsts
122
	    
123
	    // Get the list of docids  due to skin filtering of org names
124
	    
125
	    // Get the list of docids  due to existing query (eg taxonomic)
126
	    
127
	    // Get the Element/node comprising the ogc:Filter for all of the above
128
	    Element filterElement = getFilterElement(document);
129
	    
130
	    // Append the Filter to the ruleNode
131
	    ruleNode.appendChild(filterElement);
132
	    
133
	    // Write new DOM as a string
134
	    String rulesString = XMLUtilities.getDOMTreeAsString((Node) root, true);
135

  
192
	    } 
136 193
	    return rulesString;
137 194
  }
138 195

  
......
141 198
   * Creates an OGC Filter node
142 199
   * 
143 200
   * @param inDoc	DOM document.
144
   * 
201
   * @param docids 	Vector of documents allowed in the map.
145 202
   */
146
  private Element getFilterElement(Document inDoc) 
203
  private Element getFilterElement(Document inDoc, Vector docids) 
147 204
  {
148 205
	  Element filterElem = inDoc.createElement("ogc:Filter");
206
	  Element orElem = inDoc.createElement("ogc:Or");
207
	  String docid = "";
149 208
	  
150
	  // MPTODO : BEGIN LOOP thru vector of docids
151
	  Element opElem = inDoc.createElement("ogc:PropertyIsEqualTo");
209
	  // Begin loop thru vector of allowed docids
210
	  for (int i = 0; i < docids.size(); i++) {
211
		  Element opElem = inDoc.createElement("ogc:PropertyIsEqualTo");
212

  
213
		  Element propertyElem = inDoc.createElement("ogc:PropertyName");
214
		  Text propertyText = inDoc.createTextNode("docid");
215
		  propertyElem.appendChild(propertyText);
216
		  
217
		  Element literalElem = inDoc.createElement("ogc:Literal");	  
218

  
219
		  docid = (String)docids.elementAt(i);
220
		  Text literalText = inDoc.createTextNode(docid); 
221
		  literalElem.appendChild(literalText);
222
		  
223
		  opElem.appendChild(propertyElem);
224
		  opElem.appendChild(literalElem);
225

  
226
		  orElem.appendChild(opElem);
227
		  // END LOOP
228
	  }
152 229
	  
153
	  Element propertyElem = inDoc.createElement("ogc:PropertyName");
154
	  Text propertyText = inDoc.createTextNode("docid");
155
	  propertyElem.appendChild(propertyText);
156
	  
157
	  Element literalElem = inDoc.createElement("ogc:Literal");	  
158
	  Text literalText = inDoc.createTextNode("perry.1"); // i
159
	  literalElem.appendChild(literalText);
160
	  
161
	  opElem.appendChild(propertyElem);
162
	  opElem.appendChild(literalElem);
163
	  filterElem.appendChild(opElem);
164
	  // END LOOP
165
	  
230
	  filterElem.appendChild(orElem);
166 231
	  return filterElem;	  
167 232
  }
168 233
  
docs/user/spatial_option.html
264 264
   <p style="margin-bottom:12pt"> Filter which spatial cache features are displayed by access contraints, skin constraints and the current non-spatial query set. This would involve intercepting incoming WMS requests and appending a styled layer descriptor (SLD) with an OGC filter to prevent/allow certain docids. </p>
265 265

  
266 266
   <h5>SLD factory</h5>
267
   <p style="margin-bottom:12pt">Closely related to the WMS bypass implemetation, the SLD factory would be in charge of constructing the filter based on on the contraints mentioned above. Because it would have to generate this list of docids on every wms request, performance is a big concern. Likely we'll need to cache docid lists as session variables.</p>
267
   <p style="margin-bottom:12pt">Closely related to the WMS bypass implemetation, the SLD factory would be in charge of constructing the filter based on on the contraints mentioned above. In other words, it would construct a document specifying which docids were to appear in the map. Because it would have to generate this list of docids on every wms request, performance is a big concern. Likely we'll need to cache docid lists as session variables.</p>
268 268

  
269
  <p> There is currently a stub implementation of the SLD Factory servlet in <em>src/edu/ucsb/nceas/metacat/spatial/SldFactory.java</em>. It is functional except that it doesn't generate a dynamic list of allowable docids.  Assuming we can modify the SldFactory servlet to quickly generate a list of allowable docids based on stored session variables, applying this SLD to a WMS request is fairly easy and simply requires appending the URL of the sldfactory as an "SLD" parameter to the WMS GetMap request: </p>
270

  
271
   <pre> http://indus/knb/wms?REQUEST=GetMap&SERVICE=WMS....&SLD=http://indus.msi.ucsb.edu/knb/sldfactory?originalSld=data_points_style.sld</pre>
272

  
273
<p> where data_points_style.sld is the original style document existing in <em>{context}/data/styles/</em>. The sldfactory servlet will construct a list of allowable docids, append those to the original sld as an ogc filter, an return a (modified) SLD document. There are two possibilities for implementing this:</p>
274

  
275
   <ol>
276
   <li>
277
     Mapbuilder (the WMS client in charge of constructing WMS request) can be told to append this SLD parameter through the use of the WMC config document. This would work for the skins but, alone, would not ensure that every WMS request were filtered since other clients could simply ommit the SLD parameter.
278
   </li>
279
   <li> 
280
     An alternative, one that would ensure that EVERY wms request was filtered, would be to handle it all server side with a WMS bypass.
281
   </li>
282
   </ol>
283
   
284
   
285

  
269 286
   <h5>Map configuration interface </h5>
270 287
   <p style="margin-bottom:12pt">Geoserver currently offers a nice web-based configuration but it is lacking a few key features and may be difficult for a novice GIS user. We may want to reinvent a custom geoserver configuration interface to</p>
271 288
   <ul>

Also available in: Unified diff