//$HeadURL$
/*----------------------------------------------------------------------------
This file is part of deegree, http://deegree.org/
Copyright (C) 2001-2012 by:
- Department of Geography, University of Bonn -
and
- lat/lon GmbH -
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 2.1 of the License, or (at your option)
any later version.
This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
details.
You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Contact information:
lat/lon GmbH
Aennchenstr. 19, 53177 Bonn
Germany
http://lat-lon.de/
Department of Geography, University of Bonn
Prof. Dr. Klaus Greve
Postfach 1147, 53001 Bonn
Germany
http://www.geographie.uni-bonn.de/deegree/
e-mail: info@deegree.org
----------------------------------------------------------------------------*/
package org.deegree.igeo.dataadapter;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import org.deegree.datatypes.QualifiedName;
import org.deegree.framework.log.ILogger;
import org.deegree.framework.log.LoggerFactory;
import org.deegree.framework.util.Pair;
import org.deegree.model.feature.Feature;
import org.deegree.model.feature.FeatureCollection;
import org.deegree.model.feature.FeatureFactory;
import org.deegree.model.feature.FeatureProperty;
import org.deegree.model.feature.schema.FeatureType;
import org.deegree.model.feature.schema.PropertyType;
/**
* adapter class for linking tables of alpha numeric data to layers
*
* @author <a href="mailto:wanhoff@lat-lon.de">Jeronimo Wanhoff</a>
* @author <a href="mailto:name@deegree.org">Andreas Poth</a>
* @author last edited by: $Author$
*
* @version $Revision$, $Date$
*/
public class LinkedTableAdapter extends FeatureAdapter {
private static final ILogger LOG = LoggerFactory.getLogger( LinkedTableAdapter.class );
// private boolean isLazyLoading = false;
private FeatureAdapter featureAdapter;
private LinkedTable linkedTable;
private FeatureCollection fc;
private FeatureType ft;
/**
*
* @param featureAdapter
* @param linkedTable
*/
public LinkedTableAdapter( FeatureAdapter featureAdapter, LinkedTable linkedTable ) {
super( featureAdapter.getDatasource(), featureAdapter.getLayer(), featureAdapter.getLayer().getOwner() );
this.featureAdapter = featureAdapter;
this.linkedTable = linkedTable;
refresh();
}
@Override
public FeatureCollection getFeatureCollection() {
// TODO check if handling of lazy loading needs to be implemented
// if ( fc == null && !isLazyLoading ) {
try {
fc = createFeatureCollection();
} catch ( IOException e ) {
LOG.logError( e );
}
// } else {
// try {
// fc = createFeatureCollection();
// } catch ( IOException e ) {
// LOG.logError( e );
// }
// }
return fc;
}
@Override
public FeatureType getSchema() {
if ( ft == null ) {
this.ft = createFeatureType();
}
return ft;
}
@Override
public void commitChanges()
throws IOException {
// TODO
// not supported
// because 'featureAdapter' may also be an instance of LinkedTableAdapter further invocations
// of commitChanges() possibly will occur until the instance on which the method is invoked is
// not an instance of LinkedTableAdapter
// featureAdapter.commitChanges();
// List<FeatureAdapter.Changes> changeList = changes.get( datasource.getName() );
// linkedTable.commitChanges( changeList );
}
@Override
public void refresh() {
try {
fc = createFeatureCollection();
} catch ( IOException e ) {
LOG.logError( e );
}
}
@Override
public void refresh( boolean forceReload ) {
refresh();
}
@Override
public void invalidate() {
super.invalidate();
featureAdapter.invalidate();
fc = null;
}
/**
* @return feature collection as merge of feature collection assigned to sourceLayer and linkedTable
* @throws IOException
*/
@SuppressWarnings("unchecked")
private FeatureCollection createFeatureCollection()
throws IOException {
getSchema();
FeatureCollection layerFC = featureAdapter.getFeatureCollection();
FeatureCollection fc = FeatureFactory.createFeatureCollection( "UUID_" + UUID.randomUUID().toString(),
layerFC.size() * 2 );
List<Pair<QualifiedName, String>> relationKeys = linkedTable.getRelationKeys();
Pair<String, Object>[] key = new Pair[relationKeys.size()];
for ( int i = 0; i < layerFC.size(); i++ ) {
Feature feature = layerFC.getFeature( i );
// created (multiple) key for selecting table row(s) assigned to current feature
for ( int j = 0; j < key.length; j++ ) {
Object value = feature.getDefaultProperty( relationKeys.get( j ).first ).getValue();
key[j] = new Pair<String, Object>( relationKeys.get( j ).second, value );
}
// read tables rows assigned to current feature
// TODO
// think of reading data in blocks of 10 or 100 rows to avoid performing one
// one SQL statement for each row
Object[][] rows = linkedTable.getRows( key );
if ( rows.length > 0 ) {
// create a new feature for each matching row
String table = linkedTable.getLinkedTableType().getTitle();
FeatureType layerFt = featureAdapter.getSchema();
String[] column = linkedTable.getColumnNames();
for ( int j = 0; j < rows.length; j++ ) {
FeatureProperty[] fp = new FeatureProperty[ft.getProperties().length];
FeatureProperty[] fps = feature.getProperties();
int c = 0;
for ( int k = 0; k < fps.length; k++ ) {
Object v = feature.getDefaultProperty( fps[k].getName() ).getValue();
fp[c++] = FeatureFactory.createFeatureProperty( fps[k].getName(), v );
}
for ( int k = 0; k < column.length; k++ ) {
QualifiedName qn = new QualifiedName( column[k] + "_" + table, layerFt.getNameSpace() );
fp[c++] = FeatureFactory.createFeatureProperty( qn, rows[j][k] );
}
fc.add( FeatureFactory.createFeature( "UUID_" + UUID.randomUUID().toString(), ft, fp ) );
}
}
}
return fc;
}
/**
* @return common feature type for properties of layers feature type and table columns
*/
private FeatureType createFeatureType() {
FeatureType layerFt = featureAdapter.getSchema();
PropertyType[] layerPt = layerFt.getProperties();
String table = linkedTable.getLinkedTableType().getTitle();
String[] column = linkedTable.getColumnNames();
int[] types = linkedTable.getColumnTypes();
PropertyType[] allPt = new PropertyType[layerPt.length + column.length];
int c = 0;
for ( int i = 0; i < layerPt.length; i++ ) {
allPt[c++] = layerPt[i];
}
for ( int i = 0; i < column.length; i++ ) {
QualifiedName qn = new QualifiedName( column[i] + "_" + table, layerFt.getNameSpace() );
allPt[c++] = FeatureFactory.createSimplePropertyType( qn, types[i], true );
}
QualifiedName qn = new QualifiedName( layer.getTitle() + "_" + table, layerFt.getNameSpace() );
return FeatureFactory.createFeatureType( qn, false, allPt );
}
}