PageRenderTime 36ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/geotools-9.2/modules/unsupported/efeature/src/main/java/org/geotools/data/efeature/internal/ESimpleFeatureInternal.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 799 lines | 429 code | 77 blank | 293 comment | 78 complexity | 7335527429654fe374b35b9d791fb3a4 MD5 | raw file
  1. /*
  2. * GeoTools - The Open Source Java GIS Toolkit
  3. * http://geotools.org
  4. *
  5. * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation;
  10. * version 2.1 of the License.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. */
  17. package org.geotools.data.efeature.internal;
  18. import java.util.ArrayList;
  19. import java.util.Collection;
  20. import java.util.Collections;
  21. import java.util.HashMap;
  22. import java.util.HashSet;
  23. import java.util.List;
  24. import java.util.Map;
  25. import java.util.Set;
  26. import org.eclipse.emf.common.notify.Adapter;
  27. import org.eclipse.emf.common.notify.Notification;
  28. import org.eclipse.emf.common.notify.impl.AdapterImpl;
  29. import org.eclipse.emf.ecore.EAttribute;
  30. import org.eclipse.emf.ecore.EObject;
  31. import org.eclipse.emf.ecore.EStructuralFeature;
  32. import org.eclipse.emf.ecore.InternalEObject;
  33. import org.eclipse.emf.ecore.util.EcoreUtil;
  34. import org.geotools.data.Transaction;
  35. import org.geotools.data.efeature.EFeature;
  36. import org.geotools.data.efeature.EFeatureGeometry;
  37. import org.geotools.data.efeature.EFeatureInfo;
  38. import org.geotools.data.efeature.EFeatureListener;
  39. import org.geotools.data.efeature.EFeaturePackage;
  40. import org.geotools.data.efeature.EFeatureProperty;
  41. import org.geotools.data.efeature.EFeatureUtils;
  42. import org.geotools.data.efeature.ESimpleFeature;
  43. import org.geotools.feature.NameImpl;
  44. import org.geotools.filter.identity.FeatureIdImpl;
  45. import org.geotools.geometry.jts.ReferencedEnvelope;
  46. import org.opengis.feature.Attribute;
  47. import org.opengis.feature.Feature;
  48. import org.opengis.feature.GeometryAttribute;
  49. import org.opengis.feature.IllegalAttributeException;
  50. import org.opengis.feature.Property;
  51. import org.opengis.feature.simple.SimpleFeatureType;
  52. import org.opengis.feature.type.AttributeDescriptor;
  53. import org.opengis.feature.type.FeatureType;
  54. import org.opengis.feature.type.Name;
  55. import org.opengis.filter.identity.FeatureId;
  56. import org.opengis.geometry.BoundingBox;
  57. import com.vividsolutions.jts.geom.Geometry;
  58. /**
  59. *
  60. * @author kengu - 3. juli 2011
  61. *
  62. *
  63. * @source $URL$
  64. */
  65. public class ESimpleFeatureInternal implements ESimpleFeature {
  66. private FeatureId eID;
  67. private EFeatureInternal eInternal;
  68. private Map<Object, Object> userData;
  69. /**
  70. * Cached container {@link Adapter}.
  71. * <p>
  72. *
  73. * @see {@link #getEObjectAdapter()}
  74. */
  75. protected AdapterImpl eObjectlistener;
  76. /**
  77. * Cached {@link EFeatureListener}.
  78. * <p>
  79. *
  80. * @see {@link #getStructureAdapter()}
  81. */
  82. protected EFeatureListener<?> eStructurelistener;
  83. /**
  84. * Cached {@link Feature feature} bounds.
  85. */
  86. protected ReferencedEnvelope bounds;
  87. // -----------------------------------------------------
  88. // Constructors
  89. // -----------------------------------------------------
  90. public ESimpleFeatureInternal(EFeatureInternal eInternal) {
  91. //
  92. // -------------------------------------------------
  93. // Cache strong reference to implementation
  94. // -------------------------------------------------
  95. //
  96. this.eInternal = eInternal;
  97. //
  98. // Add listeners that keep cached data in-sync with eImpl and structure
  99. //
  100. eStructure().addListener(getStructureAdapter());
  101. eFeature().eAdapters().add(getEObjectAdapter());
  102. }
  103. // -----------------------------------------------------
  104. // ESimpleFeature implementation
  105. // -----------------------------------------------------
  106. @Override
  107. public EObject eObject() {
  108. return eInternal.eImpl();
  109. }
  110. @Override
  111. public EFeature eFeature() {
  112. return (EFeature)eInternal.eFeature();
  113. }
  114. @Override
  115. public boolean isDetached() {
  116. return eStructure().eHints().eValuesDetached();
  117. }
  118. @Override
  119. public boolean isSingleton() {
  120. return eStructure().eHints().eSingletonFeatures();
  121. }
  122. @Override
  123. public List<Object> read() throws IllegalStateException {
  124. return read(eInternal().eTx);
  125. }
  126. @Override
  127. public List<Object> read(Transaction transaction) throws IllegalStateException {
  128. //
  129. // Get properties
  130. //
  131. List<EFeaturePropertyDelegate<?, ? extends Property, ? extends EStructuralFeature>>
  132. eList = eInternal.getProperties();
  133. //
  134. // Prepare to read values from properties
  135. //
  136. List<Object> eValues = new ArrayList<Object>(eList.size());
  137. //
  138. // Loop over all properties
  139. //
  140. for(EFeatureProperty<?, ? extends Property> it : eList) {
  141. eValues.add(it.read(eInternal().eTx));
  142. }
  143. //
  144. // Finished
  145. //
  146. return eValues;
  147. }
  148. @Override
  149. public List<Object> write() throws IllegalStateException {
  150. return write(eInternal().eTx);
  151. }
  152. @Override
  153. public List<Object> write(Transaction transaction) throws IllegalStateException {
  154. //
  155. // Decide if feature values is allowed to be updated from backing store
  156. //
  157. if(!isDetached()) {
  158. throw new IllegalStateException("ESimpleFeature "
  159. + getType().getTypeName() + " is not detached");
  160. }
  161. //
  162. // Get properties
  163. //
  164. List<EFeaturePropertyDelegate<?, ? extends Property, ? extends EStructuralFeature>>
  165. eList = eInternal.getProperties();
  166. //
  167. // Prepare to read values from properties
  168. //
  169. List<Object> eValues = new ArrayList<Object>(eList.size());
  170. //
  171. // Loop over all properties
  172. //
  173. for(EFeatureProperty<?, ? extends Property> it : eList) {
  174. eValues.add(it.write(eInternal().eTx));
  175. }
  176. //
  177. // Finished
  178. //
  179. return eValues;
  180. }
  181. @Override
  182. public boolean isReleased() {
  183. return eInternal == null;
  184. }
  185. @Override
  186. public void release() {
  187. //
  188. // Remove adapters
  189. //
  190. eFeature().eAdapters().remove(eObjectlistener);
  191. //
  192. // Remove structure listeners
  193. //
  194. eStructure().removeListener(eStructurelistener);
  195. //
  196. // Release all strong references to external objects
  197. //
  198. eInternal = null;
  199. }
  200. // -----------------------------------------------------
  201. // SimpleFeature implementation
  202. // -----------------------------------------------------
  203. @Override
  204. public String getID() {
  205. return getIdentifier().getID();
  206. }
  207. @Override
  208. public FeatureId getIdentifier() {
  209. //
  210. // Create id?
  211. //
  212. if (eID == null) {
  213. //
  214. // Get EMF id attribute
  215. //
  216. EAttribute eIDAttribute = eStructure().eIDAttribute();
  217. //
  218. // Get feature id as string
  219. //
  220. String fid = (eIDAttribute == null || !eFeature().eIsSet(eIDAttribute) ? null
  221. : EcoreUtil.convertToString(eIDAttribute.getEAttributeType(),
  222. eFeature().eGet(eIDAttribute)));
  223. //
  224. // Create feature id instance
  225. //
  226. eID = new FeatureIdImpl(fid);
  227. }
  228. //
  229. // Finished
  230. //
  231. return eID;
  232. }
  233. @Override
  234. public BoundingBox getBounds() {
  235. // Calculate bounds?
  236. //
  237. if (bounds == null) {
  238. //
  239. // Initialize bounds
  240. //
  241. bounds = new ReferencedEnvelope(getFeatureType().getCoordinateReferenceSystem());
  242. //
  243. // Loop over all geometries
  244. //
  245. for (EFeatureGeometry<Geometry> it : eInternal.getGeometryList(Geometry.class)) {
  246. if (!it.isEmpty()) {
  247. Geometry g = it.getValue();
  248. if (bounds.isNull()) {
  249. bounds.init(g.getEnvelopeInternal());
  250. } else {
  251. bounds.expandToInclude(g.getEnvelopeInternal());
  252. }
  253. }
  254. }
  255. }
  256. return bounds;
  257. }
  258. @Override
  259. public GeometryAttribute getDefaultGeometryProperty() {
  260. //
  261. // Get default Geometry name
  262. //
  263. String eName = eStructure().eGetDefaultGeometryName();
  264. //
  265. // Get EFeatureGeometry structure
  266. //
  267. EFeatureGeometry<?> eGeometry = (EFeatureGeometry<?>)eInternal.getPropertyMap().get(eName);
  268. //
  269. // Found geometry?
  270. //
  271. if (eGeometry != null) {
  272. // Get attribute
  273. //
  274. return eGeometry.getData();
  275. }
  276. //
  277. // Not found, return null;
  278. //
  279. return null;
  280. }
  281. @Override
  282. public void setDefaultGeometryProperty(GeometryAttribute attribute) {
  283. eStructure().eSetDefaultGeometryName(attribute.getName().getURI());
  284. }
  285. @Override
  286. public Collection<? extends Property> getValue() {
  287. return getProperties();
  288. }
  289. @Override
  290. @SuppressWarnings("unchecked")
  291. public void setValue(Object newValue) {
  292. setValue((Collection<Property>) newValue);
  293. }
  294. @Override
  295. public void setValue(Collection<Property> values) {
  296. for (Property it : values) {
  297. EAttribute eAttr = eStructure().eGetAttribute(it.getName().getURI());
  298. eFeature().eSet(eAttr, it.getValue());
  299. }
  300. }
  301. @Override
  302. public Property getProperty(Name name) {
  303. return getProperties(name.getLocalPart()).iterator().next();
  304. }
  305. @Override
  306. public Collection<Property> getProperties(String eName) {
  307. Set<Property> eItems = new HashSet<Property>();
  308. for (Property it : getProperties()) {
  309. if (it.getName().getLocalPart().equals(eName)) {
  310. eItems.add(it);
  311. }
  312. }
  313. return eItems;
  314. }
  315. @Override
  316. public Collection<Property> getProperties(Name eName) {
  317. Set<Property> eItems = new HashSet<Property>();
  318. for (Property it : getProperties()) {
  319. if (it.getName().equals(eName)) {
  320. eItems.add(it);
  321. }
  322. }
  323. return eItems;
  324. }
  325. @Override
  326. public List<Property> getProperties() {
  327. // Initialize
  328. //
  329. List<Property> eList = new ArrayList<Property>();
  330. //
  331. // Loop over all EFeatureProperty instances,
  332. // collecting current Property instances.
  333. //
  334. for (EFeatureProperty<?, ? extends Property> it : eInternal.getProperties()) {
  335. eList.add(it.getData());
  336. }
  337. // Finished
  338. //
  339. return Collections.unmodifiableList(eList);
  340. }
  341. @Override
  342. public Property getProperty(String eName) {
  343. // Get instance, returns null if not found
  344. //
  345. EFeatureProperty<?, ? extends Property> eProperty = eInternal.getPropertyMap().get(eName);
  346. //
  347. // Get property instance, return null if not found
  348. //
  349. return (eProperty != null ? eProperty.getData() : null);
  350. }
  351. @Override
  352. public void validate() throws IllegalAttributeException {
  353. // Loop over all property instances,
  354. // calling validate on attributes
  355. //
  356. for (Property it : getProperties()) {
  357. ((Attribute) it).validate();
  358. }
  359. }
  360. @Override
  361. public AttributeDescriptor getDescriptor() {
  362. // Is top-level attribute (feature)
  363. return null;
  364. }
  365. @Override
  366. public Name getName() {
  367. return new NameImpl(eStructure().eName());
  368. }
  369. @Override
  370. public boolean isNillable() {
  371. return false;
  372. }
  373. @Override
  374. public Map<Object, Object> getUserData() {
  375. if (userData == null) {
  376. userData = new HashMap<Object, Object>();
  377. }
  378. return userData;
  379. }
  380. @Override
  381. public SimpleFeatureType getType() {
  382. return eStructure().getFeatureType();
  383. }
  384. @Override
  385. public SimpleFeatureType getFeatureType() {
  386. return eStructure().getFeatureType();
  387. }
  388. @Override
  389. public List<Object> getAttributes() {
  390. //
  391. // Get properties
  392. //
  393. List<Property> eList = getProperties();
  394. //
  395. // Initialize value list
  396. //
  397. List<Object> values = EFeatureUtils.newList(eList.size());
  398. //
  399. // Loop over all property instances
  400. //
  401. for (Property it : eList) {
  402. values.add(it.getValue());
  403. }
  404. //
  405. // Finished
  406. //
  407. return values;
  408. }
  409. @Override
  410. public void setAttributes(List<Object> values) {
  411. setAttributes(values.toArray(new Object[0]));
  412. }
  413. @Override
  414. public void setAttributes(Object[] values) {
  415. //
  416. // Loop over all property instances,
  417. // calling validate on attributes
  418. //
  419. int i = 0;
  420. for (Property it : getProperties()) {
  421. ((Attribute) it).setValue(values[i]);
  422. }
  423. }
  424. @Override
  425. public Object getAttribute(String eName) {
  426. Property p = getProperty(eName);
  427. return (p != null ? p.getValue() : null);
  428. }
  429. @Override
  430. public void setAttribute(String eName, Object newValue) {
  431. Property p = getProperty(eName);
  432. if (p != null) {
  433. p.setValue(newValue);
  434. }
  435. }
  436. @Override
  437. public Object getAttribute(Name eName) {
  438. Property p = getProperty(eName);
  439. return (p != null ? p.getValue() : null);
  440. }
  441. @Override
  442. public void setAttribute(Name eName, Object newValue) {
  443. Property p = getProperty(eName);
  444. if (p != null) {
  445. p.setValue(newValue);
  446. }
  447. }
  448. @Override
  449. public Object getAttribute(int index) throws IndexOutOfBoundsException {
  450. Property p = getProperties().get(index);
  451. return p.getValue();
  452. }
  453. @Override
  454. public void setAttribute(int index, Object newValue) throws IndexOutOfBoundsException {
  455. Property p = getProperties().get(index);
  456. if (p != null) {
  457. p.setValue(newValue);
  458. }
  459. }
  460. @Override
  461. public int getAttributeCount() {
  462. return eInternal.getProperties().size();
  463. }
  464. @Override
  465. public Geometry getDefaultGeometry() {
  466. Property p = getDefaultGeometryProperty();
  467. return (Geometry) (p != null ? p.getValue() : null);
  468. }
  469. @Override
  470. public void setDefaultGeometry(Object newGeometry) {
  471. Property p = getDefaultGeometryProperty();
  472. if (p != null) {
  473. p.setValue(newGeometry);
  474. }
  475. }
  476. // -----------------------------------------------------
  477. // Object equality implementation
  478. // -----------------------------------------------------
  479. @Override
  480. public int hashCode() {
  481. int hash = 7;
  482. hash = 31 * hash + getID().hashCode();
  483. hash = 31 * hash + getFeatureType().hashCode();
  484. for(Object it : getAttributes()) {
  485. hash = (null == it ? 0 : it.hashCode());
  486. }
  487. return hash;
  488. }
  489. @Override
  490. public boolean equals(Object obj) {
  491. //
  492. // Sanity checks
  493. //
  494. if (obj == null) {
  495. return false;
  496. }
  497. //
  498. // Same as this?
  499. //
  500. if (obj == this) {
  501. return true;
  502. }
  503. //
  504. // Not same implementation?
  505. //
  506. if (!(obj instanceof ESimpleFeatureInternal)) {
  507. return false;
  508. }
  509. //
  510. // Cast to ESimpleFeatureInternal
  511. //
  512. ESimpleFeatureInternal eFeature = (ESimpleFeatureInternal)obj;
  513. //
  514. // Get this feature ID
  515. //
  516. String eID = getID();
  517. //
  518. // This check shouldn't really be necessary since
  519. // by contract, all features should have an ID.
  520. //
  521. if (getID() == null) {
  522. if (eFeature.getIdentifier() != null) {
  523. return false;
  524. }
  525. }
  526. //
  527. // Is not same feature ID?
  528. //
  529. if (!eID.equals(eFeature.getIdentifier())) {
  530. return false;
  531. }
  532. //
  533. // Is not same feature type.
  534. //
  535. if (!eFeature.getFeatureType().equals(getFeatureType())) {
  536. return false;
  537. }
  538. //
  539. // Get attribute values
  540. //
  541. List<Object> values = getAttributes();
  542. //
  543. // Check all values for inequality
  544. //
  545. for (int i = 0, count = values.size(); i < count; i++) {
  546. //
  547. // Get attribute values
  548. //
  549. Object v1 = values.get(i);
  550. Object v2 = eFeature.getAttribute(i);
  551. //
  552. // Do a guarded check
  553. //
  554. if (v1 == null) {
  555. if (v2 != null) {
  556. return false;
  557. }
  558. } else {
  559. if (!v1.equals(v2)) {
  560. return false;
  561. }
  562. }
  563. }
  564. //
  565. // All values are equal
  566. //
  567. return true;
  568. }
  569. // -----------------------------------------------------
  570. // Helper methods
  571. // -----------------------------------------------------
  572. /**
  573. * Verify that state is available
  574. */
  575. protected void verify() throws IllegalStateException
  576. {
  577. if(eStructure()==null)
  578. throw new IllegalStateException(this + " is not valid. " +
  579. "Please specify the structure.");
  580. if(eFeature()==null)
  581. throw new IllegalStateException(this + " is released.");
  582. }
  583. protected EFeatureInternal eInternal() {
  584. return eInternal;
  585. }
  586. protected EFeatureInfo eStructure() {
  587. return eInternal.eStructure;
  588. }
  589. protected void eReplace(EFeatureInternal eInternal) {
  590. //
  591. // Remove structure listener from current structure?
  592. //
  593. if(!eStructure().eEqualTo(eInternal.eStructure)) {
  594. eStructure().removeListener(getStructureAdapter());
  595. }
  596. //
  597. // Remove data adapter structure
  598. //
  599. eFeature().eAdapters().remove(getEObjectAdapter());
  600. //
  601. // Replace strong reference.
  602. //
  603. this.eInternal = eInternal;
  604. //
  605. // Add call-backs that keep caches in-sync with structure and data
  606. //
  607. eStructure().addListener(getStructureAdapter());
  608. eFeature().eAdapters().add(getEObjectAdapter());
  609. }
  610. // -----------------------------------------------------
  611. // Methods for keeping cached data in-sync
  612. // -----------------------------------------------------
  613. /**
  614. * Cached {@link EFeatureListener} which monitors changes made to {@link EFeatureInfo}.
  615. * <p>
  616. * On each change, this adapter determines if any data cached by this instance should be
  617. * invalidated. The following conditions invoke invalidation of data:
  618. * <ol>
  619. * <li>{@link #bounds} is invalidated after {@link #setSRID(String) spatial reference ID} is
  620. * changed</li>
  621. * </ol>
  622. *
  623. * @see {@link #setSRID(String)} - forwarded to {@link EFeatureInfo#setSRID(String)}
  624. * @see {@link EFeatureInfo#setSRID(String)} - invalidates the
  625. * {@link FeatureType#getCoordinateReferenceSystem() CRS} of all {@link Feature} instances
  626. * contained by {@link EFeature}s with the same structure as this.
  627. * @return a lazily cached {@link Adapter} instance.
  628. */
  629. protected Adapter getEObjectAdapter() {
  630. if (eObjectlistener == null) {
  631. eObjectlistener = new AdapterImpl() {
  632. @Override
  633. public void notifyChanged(Notification msg) {
  634. Object feature = msg.getFeature();
  635. if (msg.getEventType() == Notification.SET
  636. && (msg.getNewValue() instanceof Geometry)
  637. && (msg.getFeature() instanceof EStructuralFeature)) {
  638. // Check if a geometry is changed. If it is, bounds
  639. // must be re-calculated...
  640. String eName = ((EStructuralFeature) feature).getName();
  641. if (eStructure().isGeometry(eName)) {
  642. // Reset bounds. This forces bounds of this
  643. // feature to be recalculated on next call
  644. // to SimpleFeatureDelegate#getBounds()
  645. bounds = null;
  646. }
  647. }
  648. }
  649. };
  650. }
  651. return eObjectlistener;
  652. }
  653. /**
  654. * Cached {@link Adapter} which monitors changes made to the {@link EObject} instance this
  655. * delegates to.
  656. * <p>
  657. * On each change, this adapter determines if any data cached by this instance should be
  658. * invalidated. The following conditions invoke invalidation of data:
  659. * <ol>
  660. * <li>{@link #bounds} is invalidated after a {@link #getValue() geometry} change</li>
  661. * </ol>
  662. *
  663. * @return a lazily cached {@link EStructuralFeature} instance.
  664. */
  665. protected EFeatureListener<?> getStructureAdapter() {
  666. if (eStructurelistener == null) {
  667. eStructurelistener = new EFeatureListener<Object>() {
  668. @Override
  669. public boolean onChange(Object source,
  670. int property, Object oldValue, Object newValue) {
  671. //
  672. // Dispatch on property type
  673. //
  674. if (property == EFeaturePackage.EFEATURE__SRID) {
  675. //
  676. // ---------------------------------------
  677. // Current bounds have wrong CRS.
  678. // ---------------------------------------
  679. // This forces current bounds
  680. // to be recalculated on next call
  681. // to getData().getBounds()
  682. //
  683. bounds = null;
  684. //
  685. // Notify
  686. //
  687. EFeatureInternal.eNotify((InternalEObject)eObject(),EFeaturePackage.EFEATURE__SRID, oldValue, newValue);
  688. }
  689. //
  690. // Referenced EObject structure changed?
  691. //
  692. else if ((source == eFeature())
  693. && (property == EFeaturePackage.EFEATURE__STRUCTURE)) {
  694. //
  695. // ---------------------------------------
  696. // Current structure has been switched
  697. // ---------------------------------------
  698. //
  699. // 1) Remove listener from structure
  700. //
  701. ((EFeatureInfo)oldValue).removeListener(this);
  702. //
  703. // Add listener to new structure
  704. //
  705. ((EFeatureInfo)newValue).addListener(this);
  706. //
  707. // This forces current bounds
  708. // to be recalculated on next call
  709. // to getData().getBounds()
  710. //
  711. bounds = null;
  712. }
  713. //
  714. // Always allowed
  715. //
  716. return true;
  717. }
  718. };
  719. }
  720. return eStructurelistener;
  721. }
  722. }