wiki:NERCGeoServer

Version 3 (modified by ashaon, 11 years ago) (diff)

--

NERC Portals Work on GeoServer?

GeoServer? is an Open Source web server for publishing Geospatial information on the web using open standards, such as the OGC standards. One such GeoServer? supported OGC standard is Web Feature Service (WFS), which allows a client to retrieve and update geospatial data encoded in GML or any format is derived from or extends GML, irrespective of the location or storage media of the data. While a standard version of GeoServer? provides a suitable facility for serving up geospatial data in pure GML, it is not possible to do the same for formats that are based on GML. Handling such a task requires the use of the “Community Schema” / “Complex DataStore?” version of GeoServer? ( http://docs.codehaus.org/display/GEOS/Complex+Datastore). This special version of GeoServer? is designed to enable representation of data from a relational database in an application schema (e.g. CSML) that is defined independently of the underlying database structure. Unfortunately, the "Complex DataStore?" version of Geoserver was a research endeavour, which is no longer active and has very insufficient documentation, not to mention a good number of bugs. Therefore, it was necessary to modify a considerable portion of the GeoServer? source code in order to accurately output data in CSML.

Our main work on GeoServer? encompasses the followings:

Serving up CSML PointSeriesFeature? through GeoServer?

CSML PointSeriesFeature? uses the XML List element to represent a series of point measurements. The current version of “Complex DataStore?” Geoserver (available on GeoServer? subversion code base at  https://svn.codehaus.org/geoserver/branches/1.6.x) does not support mapping data to XML List element. Therefore, in order to accurately generate CSML through GeoServer?, it was crucial to implement a mechanism for mapping to XML List elements in GeoServer?. The approach used for this is essentially a variant of the one used for mapping to "Multiple Occurrence" elements in the current version of “Complex DataStore?” Geoserver. The only difference is that the values to be mapped are concatenated together (delimited with a space character) and treated as a single value. So, when it comes to mapping to the element in question, there is only one value to be mapped, which essentially yields a single occurrence of the element in the final XML output. Implementations of both of these features are mainly done in the GroupingFeatureIterator3 class of org.geotools.data.complex package. Listing 1 illustrates the difference between these implementations.

private void setMultiValuedAttributes(final Feature targetFeature) throws IOException{
        // Map sourcePropName/List<values> with the contents
        // of the source attributes needed to map multivalued
        // properties and its children
        final Map /* String/List<Object> */mvaluedSourceProps = new HashMap();
        final NamespaceSupport namespaces = mapping.getNamespaces();
        for (Iterator it = multiValuedSourcePropNames.iterator(); it.hasNext();) {
            // this is just an ugly way of getting rid of index in expressions
            // like "attName[2]"
            String attName = (String) it.next();
            StepList steps = XPath.steps(targetFeature.getDescriptor(), attName, namespaces);
            String string = ((XPath.Step) steps.get(0)).getName().getLocalPart();
            mvaluedSourceProps.put(string, new ArrayList());
        }

        // // build the group of properties comprising the mvalued properties
        // and its children ///
        final List /* Name */groupByAttNames = toTypeNames(mapping.getGroupByAttNames());
        // the grouping values to check for equality
        final List baseGroupingAttributes = extractGroupingAttributes(curSrcFeature,
                groupByAttNames);

        final Feature firstFeatureInGroup = curSrcFeature;
        extractSourceProperties(mvaluedSourceProps, (SimpleFeature) curSrcFeature);
	  
        List currFeatureGroupingAtts = null;
        int index = 0;
       
        while (sourceFeatures.hasNext()) {
            curSrcFeature = (Feature) sourceFeatures.next();
            //System.out.println(curSrcFeature.toString());
            currFeatureGroupingAtts = extractGroupingAttributes(curSrcFeature, groupByAttNames);
            if (baseGroupingAttributes.equals(currFeatureGroupingAtts)) {
                extractSourceProperties(mvaluedSourceProps, (SimpleFeature) curSrcFeature);
                index++;
            } else {
                break;
            }
        }
        /*** Begin mapping values to list/multiple occurence elements ***/
	  
        for (Iterator it = multivaluedMappings.entrySet().iterator(); it.hasNext();) {
            final Map.Entry entry = (Entry) it.next();
            AttributeMapping parentMapping = (AttributeMapping) entry.getKey();
            final List childPropMappings = (List) entry.getValue();
             // If the target element is a list element
	     if (parentMapping.isListValued()){
			setMultiValuedId(targetFeature, curSrcFeature, parentMapping, mvaluedSourceProps);
			AttributeMapping mvaluedProp = (AttributeMapping)childPropMappings.get(0);
			StepList targetXPath = mvaluedProp.getTargetXPath();
			if (targetXPath.size() == 1) {
                		Step rootStep = (Step) targetXPath.get(0);
                		QName stepName = rootStep.getName();
                		if (Types.equals(targetFeature.getDescriptor().getName(), stepName)) {
                    		// ignore the top level mapping for the Feature
                    		// itself
                    		// as it was already set
                    		continue;
                		}
            	       }
	               setMSingleValuedAttribute(targetFeature, curSrcFeature, mvaluedProp, mvaluedSourceProps);
           // else if the target element is a multiple occurence element

	   }else if (parentMapping.isMultiValued()){
		final LazyProperties mvaluedInstances;
            	mvaluedInstances = new LazyProperties(targetFeature, parentMapping, childPropMappings,
                    mvaluedSourceProps);
            	final String id = extractIdForAttribute(parentMapping.getIdentifierExpression(),
                    firstFeatureInGroup);
            	final AttributeType targetNodeType = parentMapping.getTargetNodeInstance();
            	final StepList targetXPath = parentMapping.getTargetXPath();

            	MutableAttribute parent = getParent(targetFeature, targetXPath);
            	Collection newParentContent = mvaluedInstances;
            	// may the parent have pre-existing non multivalued properties?
            	Collection previousProperties = (Collection) parent.getValue();
            	if (previousProperties.size() > 0) {
                		DeferredList deferredList = new DeferredList();
                		deferredList.addAll(new ArrayList(previousProperties));
                		deferredList.addAll(mvaluedInstances);
            	}
            	parent.setValue(newParentContent);

		}
	}
		

    }
    .................................


    private void setMSingleValuedAttribute(final Feature target, final Feature source,
        /** Concatenate all values to be mapped and finally map to the target element**/

        final AttributeMapping attMapping, final Map values) throws IOException {

        final Expression sourceExpression = attMapping.getSourceExpression();
	final Expression idExpression = attMapping.getIdentifierExpression();
        final AttributeType targetNodeType = attMapping.getTargetNodeInstance();
        final StepList xpath = attMapping.getTargetXPath();
	Map clientPropsMappings = attMapping.getClientProperties();
	String id = null;
        String e_src_exp = "";
        String id_exp = "";
        if (Expression.NIL != sourceExpression){
		e_src_exp = sourceExpression.toString().toLowerCase();
	}	  

	if (Expression.NIL != idExpression) {
            id_exp = idExpression.toString().toLowerCase();
        }

	  	  
	HashMap value_map = (HashMap)values;
	HashMap id_map = new HashMap();
	  //System.out.println(value_map.containsKey(sourceExpression.toString())+" hasmap");
        Object value ="";
        HashMap v_map = new HashMap();
        int count=0;
        Iterator it = value_map.keySet().iterator();
	  
	  while(it.hasNext()){
		Object key = it.next();
		String e_key = key.toString().toLowerCase();
		if (e_src_exp.contains(e_key)){
			ArrayList al = (ArrayList)value_map.get(key);
			if (e_src_exp.equalsIgnoreCase(e_key)){
				String temp_value = al.toString();
		      	temp_value=temp_value.substring(temp_value.indexOf("[")+1, temp_value.indexOf("]"));
		      	value = temp_value.replaceAll(","," ");
			}else{
				if (al.size() > count){
					count= al.size();
				}
				v_map.put(key,al);
		  		
			}//else
			
		}else if (id_exp.contains(e_key)){
			ArrayList al = (ArrayList)value_map.get(key);
			if (al.size() >0){
				id_map.put(key, al.get(0));
				
			}
		
		}

	  }

	  id = (String) idExpression.evaluate(id_map, String.class);

	  // handles cases in which multiple values and/or string literals are combined using 'strConcat' function
	  if (value.equals("")){
		for (int i=0; i < count; i++){
			Iterator loop = v_map.keySet().iterator();
                        HashMap exp_val = new HashMap();
			while (loop.hasNext()){
				Object field = loop.next();
				ArrayList vList = (ArrayList)v_map.get(field);
				if (vList.size() >= i){
					exp_val.put(field, vList.get(i));
				}
			}//while
								
			if (value==""){
				value = (String)sourceExpression.evaluate(exp_val, String.class);
			}else{
				value=value+" "+(String)sourceExpression.evaluate(exp_val, String.class);
			}
		
		}//for
	  }//if

	  Attribute instance = xpathAttributeBuilder.set(target, xpath, value, id, targetNodeType);
          System.out.println("cl.."+clientPropsMappings.toString());
          setClientPropertiesMult(instance, values, clientPropsMappings);
    }


    
    private void setMultiValuedId(final Feature target, final Feature source,
        final AttributeMapping attMapping, final Map values) throws IOException {

        Expression identifierExpression = attMapping.getIdentifierExpression();
        final AttributeType targetNodeType = attMapping.getTargetNodeInstance();
        final StepList xpath = attMapping.getTargetXPath();
        HashMap value_map = (HashMap)values;
	  //System.out.println(value_map.containsKey(sourceExpression.toString())+" hasmap");
        HashMap id_map = new HashMap();
        
	Iterator it = value_map.keySet().iterator();
	while(it.hasNext()){
		Object key = it.next();
		//System.out.println(key+" "+identifierExpression);
		if (identifierExpression.toString().toLowerCase().contains(key.toString().toLowerCase())){
			ArrayList al = (ArrayList)value_map.get(key);
		      
			if (al.size() >0){
				id_map.put(key, al.get(0));
			}
			
		}
	}


      Attribute instance = xpathAttributeBuilder.set(target, xpath, null, id, targetNodeType);
      Map clientPropsMappings = attMapping.getClientProperties();
      setClientPropertiesMult(instance, values, clientPropsMappings);
    }

Listing 1: Implementation of mapping to XML List and Multiple Occurence elements

In the schema mapping configuration file, mapping to an XML List element is indicated by setting the "isList" attribute to true for the parent attribute node of the list element. This is an addition to the current version of the "Complex DataStore?" Geoserver. Please note, this is similar to the way in which mapping to a multiple occurrence element is represented in the schema mapping file, i.e. by setting the "isMultiple" attribute to true. Listing 2 and 3 illustrate the differenced between these two types of mapping:

<AttributeMapping>
<targetAttribute>root/element</targetAttribute>
	<targetAttributeNode>elementType</targetAttributeNode>
	<!—in the target Schema this should be <element name=”element” type=”elementType”/>-->
	<isMultiple>true</isMultiple>
</AttributeMapping>

<AttributeMapping>
<targetAttribute>root/element/child </targetAttribute>
	<sourceExpression>
<OCQL>value</OCQL>
	</sourceExpression>
</AttributeMapping>

Listing 2: Mapping to a Multiple Occurence Element

AttributeMapping>
<targetAttribute>root/element </targetAttribute>
	<targetAttributeNode>elementType</targetAttributeNode>
	<isList>true</isList>
</AttributeMapping>

<AttributeMapping>
<targetAttribute>root/element/child </targetAttribute>
	<sourceExpression>
		<OCQL>value</OCQL>
	</sourceExpression>
</AttributeMapping>

Listing 3: Mapping to an XML List Element