From b326756ddd7eee426d7d0e93a485ec30b6fbb5fd Mon Sep 17 00:00:00 2001
From: ?? ? <ulysseskao@ximple.com.tw>
Date: Tue, 20 Apr 2010 19:27:20 +0800
Subject: [PATCH] dgn7 write function for complex chain

---
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TextNodeElement.java                     |    4 
 .gitattributes                                                                                  |    4 
 xdgnjobs/ximple-dgnio/pom.xml                                                                   |    6 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/IElementHandler.java                     |    4 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Element.java                             |  107 ++++++
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementFactory.java                      |  111 ++++++
 xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7TextElementReaderTest.java           |    6 
 xdgnjobs/pom.xml                                                                                |   29 +
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileWriter.java                      |  349 ++++++++++++++++++++
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ShapeElement.java                        |    4 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TagElement.java                          |    2 
 xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileReaderTest.java                  |    6 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileReader.java                      |   95 ----
 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2MySQLJob.java   |   14 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/LineElement.java                         |    4 
 xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileWriterTest.java                  |  115 ++++++
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementType.java                         |   36 +-
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/EllipseElement.java                      |    2 
 xdgnjobs/ximple-dgnio/src/test/resources/com/ximple/io/dgn7/test-data/dgnseed2d.dgn             |    0 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TcbElement.java                          |    4 
 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2OraSDOJob.java  |   14 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ComplexChainElement.java                 |    4 
 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java     |   14 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TextElement.java                         |    4 
 xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2PostGISJob.java |   16 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/LineStringElement.java                   |    8 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ArcElement.java                          |    4 
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ComplexShapeElement.java                 |    4 
 28 files changed, 803 insertions(+), 167 deletions(-)

diff --git a/.gitattributes b/.gitattributes
index a526343..975754f 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -14,7 +14,9 @@
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileException.java svneol=native#text/plain
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileHeader.java svneol=native#text/plain
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileReader.java svneol=native#text/plain
+xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileWriter.java -text svneol=unset#text/plain
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Element.java svneol=native#text/plain
+xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementFactory.java -text svneol=unset#text/plain
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementType.java svneol=native#text/plain
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/EllipseElement.java svneol=native#text/plain
 xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/FrammeAttributeData.java svneol=native#text/plain
@@ -36,11 +38,13 @@
 xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7OracleReaderTest.java svneol=native#text/plain
 xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7TextElementReaderTest.java svneol=native#text/plain
 xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileReaderTest.java svneol=native#text/plain
+xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileWriterTest.java -text svneol=unset#text/plain
 xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/OracleTarget.java svneol=native#text/plain
 xdgnjobs/ximple-dgnio/src/test/resources/com/ximple/io/dgn7/test-data/Demo.dgn -text
 xdgnjobs/ximple-dgnio/src/test/resources/com/ximple/io/dgn7/test-data/HV88491-1.dgn -text
 xdgnjobs/ximple-dgnio/src/test/resources/com/ximple/io/dgn7/test-data/HV88491_0888888.dgn -text
 xdgnjobs/ximple-dgnio/src/test/resources/com/ximple/io/dgn7/test-data/HV88494_0.dgn -text
+xdgnjobs/ximple-dgnio/src/test/resources/com/ximple/io/dgn7/test-data/dgnseed2d.dgn -text
 xdgnjobs/ximple-dgnio/src/test/resources/com/ximple/io/dgn7/test-data/testHV.dgn -text
 xdgnjobs/ximple-elmparser/pom.xml svneol=native#text/xml
 xdgnjobs/ximple-elmparser/src/main/java/com/ximple/eofms/XElementFetcher.java svneol=native#text/plain
diff --git a/xdgnjobs/pom.xml b/xdgnjobs/pom.xml
index 4d3de58..9786382 100644
--- a/xdgnjobs/pom.xml
+++ b/xdgnjobs/pom.xml
@@ -19,8 +19,11 @@
     <src.output>${basedir}/target</src.output>
     <java5>1.5</java5>
     <xdgnio.version>1.2.0</xdgnio.version>
-    <gt2.version>2.6.2</gt2.version>
+    <gt2.version>2.6.3</gt2.version>
     <failIfNoTests>false</failIfNoTests>
+    <stress.skip.pattern></stress.skip.pattern>
+    <online.skip.pattern></online.skip.pattern>
+    <allow.test.failure.ignore>false</allow.test.failure.ignore>
   </properties>
 
   <profiles>
@@ -31,6 +34,7 @@
           <plugin>
             <groupId>org.apache.maven.plugins</groupId>
             <artifactId>maven-javadoc-plugin</artifactId>
+            <version>2.6.1</version>
             <configuration>
               <source>1.5</source>
             </configuration>
@@ -416,6 +420,11 @@
           <artifactId>maven-eclipse-plugin</artifactId>
           <version>2.5</version>
         </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-javadoc-plugin</artifactId>
+          <version>2.6.1</version>
+        </plugin>
       </plugins>
     </pluginManagement>
 
@@ -504,13 +513,15 @@
       <!-- ======================================================= -->
       <!--     Code coverage                                       -->
       <!-- ======================================================= -->
+      <!--
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-clover-plugin</artifactId>
+        <version>2.4</version>
         <configuration>
           <jdk>1.5</jdk>
           <licenseLocation>
-            http://svn.geotools.org/geotools/branches/2.4.x/build/maven/build-configs/src/main/resources/gt2/clover.license
+            http://svn.geotools.org/geotools/branches/2.6.x/build/maven/build-configs/src/main/resources/gt2/clover.license
           </licenseLocation>
           <flushPolicy>directed</flushPolicy>
         </configuration>
@@ -519,8 +530,8 @@
             <phase>pre-site</phase>
             <goals>
               <goal>instrument</goal>
-              <!-- aggregation is disabled due to the bug:     -->
-              <!-- http://jira.codehaus.org/browse/MCLOVER-34  -->
+              < - aggregation is disabled due to the bug:     - !>
+              < - http://jira.codehaus.org/browse/MCLOVER-34  - !>
             </goals>
           </execution>
         </executions>
@@ -532,7 +543,7 @@
           </dependency>
         </dependencies>
       </plugin>
-
+      -->
 
       <!-- ======================================================= -->
       <!--     JAR packaging.                                      -->
@@ -550,6 +561,14 @@
       </plugin>
 
       <!-- ======================================================= -->
+      <!--     JavaDoc packaging.                                  -->
+      <!-- ======================================================= -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+      </plugin>
+
+      <!-- ======================================================= -->
       <!--     Source packaging.                                      -->
       <!-- ======================================================= -->
       <plugin>
diff --git a/xdgnjobs/ximple-dgnio/pom.xml b/xdgnjobs/ximple-dgnio/pom.xml
index 13c4f18..d42808f 100644
--- a/xdgnjobs/ximple-dgnio/pom.xml
+++ b/xdgnjobs/ximple-dgnio/pom.xml
@@ -71,6 +71,12 @@
       <groupId>org.apache.poi</groupId>
       <artifactId>poi</artifactId>
     </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>1.4</version>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <!-- =========================================================== -->
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ArcElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ArcElement.java
index af11051..b9fc904 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ArcElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ArcElement.java
@@ -17,12 +17,12 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/26 �U�� 06:41:45
+ * @since 2006/5/26 �U�� 06:41:45
  */
 public class ArcElement extends Element implements GeometryConverter {
     private static final Logger logger = Logger.getLogger(ArcElement.class);
 
-    public ArcElement(byte[] raw) {
+    ArcElement(byte[] raw) {
         super(raw);
     }
 
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ComplexChainElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ComplexChainElement.java
index 8cec43d..a5d7980 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ComplexChainElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ComplexChainElement.java
@@ -18,14 +18,14 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/18 �U�� 03:44:56
+ * @since 2006/5/18
  */
 public class ComplexChainElement extends Element implements ComplexElement, GeometryConverter {
     private static final Logger logger = Logger.getLogger(ComplexChainElement.class);
 
     protected ArrayList<Element> list = new ArrayList<Element>();
 
-    public ComplexChainElement(byte[] raw) {
+    ComplexChainElement(byte[] raw) {
         super(raw);
         attrOffset = 4;
     }
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ComplexShapeElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ComplexShapeElement.java
index aa0203c..2250e6a 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ComplexShapeElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ComplexShapeElement.java
@@ -19,14 +19,14 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/18 �U�� 03:45:15
+ * @since 2006/5/18 �U�� 03:45:15
  */
 public class ComplexShapeElement extends Element implements ComplexElement, GeometryConverter {
     private static final Logger logger = Logger.getLogger(ComplexShapeElement.class);
 
     ArrayList<Element> list = new ArrayList<Element>();
 
-    public ComplexShapeElement(byte[] raw) {
+    ComplexShapeElement(byte[] raw) {
         super(raw);
     }
 
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileReader.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileReader.java
index 298f2ae..4dabae4 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileReader.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileReader.java
@@ -27,7 +27,7 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/17 �U�� 01:24:10
+ * @since 2006/5/17
  */
 public class Dgn7fileReader {
     private static final Logger logger = LogManager.getLogger(Dgn7fileReader.class);
@@ -37,15 +37,15 @@
     ByteBuffer buffer;
     private ElementType fileElementType = ElementType.UNDEFINED;
     private ByteBuffer headerTransfer;
-    private final Record record = new Record();
+    private final Element.FileRecord record = new Element.FileRecord();
     private final boolean randomAccessEnabled;
     private Lock lock;
     private boolean useMemoryMappedBuffer;
     private long currentOffset = 0L;
-    private StreamLogging streamLogger = new StreamLogging("Shapefile Reader");
+    private StreamLogging streamLogger = new StreamLogging("Dgn7 Reader");
     private int maxElementId = 0;
 
-    public Dgn7fileReader(ReadableByteChannel channel, boolean strict, boolean useMemoryMapped, Lock lock)
+    public Dgn7fileReader(FileChannel channel, boolean strict, boolean useMemoryMapped, Lock lock)
         throws IOException, Dgn7fileException {
         this.channel = channel;
         this.useMemoryMappedBuffer = useMemoryMapped;
@@ -56,7 +56,7 @@
         init(strict);
     }
 
-    public Dgn7fileReader(ReadableByteChannel channel, Lock lock) throws IOException, Dgn7fileException {
+    public Dgn7fileReader(FileChannel channel, Lock lock) throws IOException, Dgn7fileException {
         this(channel, true, true, lock);
     }
 
@@ -163,7 +163,7 @@
         return randomAccessEnabled;
     }
 
-    public Record nextElement() throws IOException, Dgn7fileException {
+    public Element.FileRecord nextElement() throws IOException, Dgn7fileException {
         // need to update position
         buffer.position(this.toBufferOffset(record.end));
 
@@ -269,6 +269,7 @@
         record.length = elementLength;
         record.signature = signature;
         record.number = recordNumber;
+        record.buffer = buffer;
 
         // remember, we read one int already...
         record.end = this.toFileOffset(buffer.position()) + elementLength - 4;
@@ -322,7 +323,7 @@
         }
     }
 
-    public Record elementAt(int offset) throws IOException, UnsupportedOperationException, Dgn7fileException {
+    public Element.FileRecord elementAt(int offset) throws IOException, UnsupportedOperationException, Dgn7fileException {
         if (randomAccessEnabled) {
             this.goTo(offset);
 
@@ -517,7 +518,7 @@
                     while (reader.hasNext()) {
                         size++;
 
-                        Dgn7fileReader.Record record = reader.nextElement();
+                        Element.FileRecord record = reader.nextElement();
 
                         if (record.element() != null) {
                             Element element = (Element) record.element();
@@ -550,90 +551,20 @@
                 } catch (IOException e) {
                     logger.warn("Stop read dgn file", e);
                 } catch (Dgn7fileException e) {
-                    e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+                    logger.warn(e.getMessage(), e);
                 } finally {
                     reader.close();
                 }
 
-                System.out.println("count=" + count + " size=" + size);
+                logger.debug("count=" + count + " size=" + size);
                 // reader.close();
             } catch (IOException ioe) {
-                System.out.println(ioe);
-                ioe.printStackTrace();
+                logger.warn(ioe.getMessage(), ioe);
             } catch (Dgn7fileException e) {
-                e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
+                logger.warn(e.getMessage(), e);
             }
         }
 
         System.exit(0);
-    }
-
-    public final class Record {
-        int length;
-        int number = 0;
-        int offset;           // Relative to the whole file
-        int start = 0;    // Relative to the current loaded buffer
-        short signature = 0;
-
-        /**
-         * The minimum X value.
-         */
-        public double minX;
-
-        /**
-         * The minimum Y value.
-         */
-        public double minY;
-
-        /**
-         * The minimum Z value.
-         */
-        public double minZ;
-
-        /**
-         * The maximum X value.
-         */
-        public double maxX;
-
-        /**
-         * The maximum Y value.
-         */
-        public double maxY;
-
-        /**
-         * The maximum Z value.
-         */
-        public double maxZ;
-
-        // ElementType type;
-        int end = 0;    // Relative to the whole file
-        Object element = null;
-        IElementHandler handler;
-
-        public Object element() {
-            if (element == null) {
-                buffer.position(start);
-                buffer.order(ByteOrder.LITTLE_ENDIAN);
-
-                if (handler == null) {
-                    return null;
-                }
-
-                element = handler.read(buffer, signature, length);
-            }
-
-            return element;
-        }
-
-        public int offset() {
-            return offset;
-        }
-
-        /**
-         * A summary of the record.
-         */
-        public String toString() {
-            return "Record " + number + " length " + length + " bounds " + minX + "," + minY + " " + maxX + "," + maxY;
-        }
     }
 }
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileWriter.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileWriter.java
new file mode 100644
index 0000000..fded903
--- /dev/null
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Dgn7fileWriter.java
@@ -0,0 +1,349 @@
+package com.ximple.io.dgn7;
+
+import com.ximple.util.DgnUtility;
+import org.apache.log4j.LogManager;
+import org.apache.log4j.Logger;
+
+import java.io.EOFException;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.MappedByteBuffer;
+import java.nio.ShortBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.channels.ReadableByteChannel;
+import java.nio.channels.WritableByteChannel;
+
+public class Dgn7fileWriter {
+    private static final Logger logger = LogManager.getLogger(Dgn7fileWriter.class);
+
+    private Dgn7fileHeader header;
+    private FileChannel channel;
+    ByteBuffer buffer;
+    private ElementType fileElementType = ElementType.UNDEFINED;
+    private ByteBuffer headerTransfer;
+    private final Element.FileRecord record = new Element.FileRecord();
+    private final boolean randomAccessEnabled;
+    private Lock lock;
+    private boolean useMemoryMappedBuffer;
+    private long currentOffset = 0L;
+    private StreamLogging streamLogger = new StreamLogging("Dgn7 Writer");
+    private int maxElementId = 0;
+
+    public Dgn7fileWriter(FileChannel channel, boolean strict, boolean useMemoryMapped, Lock lock)
+            throws IOException, Dgn7fileException {
+        this.channel = channel;
+        this.useMemoryMappedBuffer = useMemoryMapped;
+        streamLogger.open();
+        randomAccessEnabled = channel instanceof FileChannel;
+        this.lock = lock;
+        lock.lockRead();
+        lock.lockWrite();
+        // init(strict);
+    }
+
+    public Dgn7fileWriter(FileChannel channel, Lock lock) throws IOException, Dgn7fileException {
+        this(channel, true, true, lock);
+    }
+
+    protected boolean hasNext() throws IOException {
+        // mark current position
+        int position = buffer.position();
+
+        // ensure the proper position, regardless of read or handler behavior
+        try {
+            buffer.position(this.toBufferOffset(record.end));
+        } catch (IllegalArgumentException e) {
+            logger.warn("position=" + this.toBufferOffset(record.end), e);
+
+            return false;
+        }
+
+        // no more data left
+        if (buffer.remaining() < 4) {
+            return false;
+        }
+
+        // looks good
+        boolean hasNext = true;
+        short type = buffer.getShort();
+
+        if (type == -1) {
+            hasNext = false;
+        }
+
+        // reset things to as they were
+        buffer.position(position);
+
+        return hasNext;
+    }
+
+    protected Element.FileRecord nextElement() throws IOException, Dgn7fileException {
+        // need to update position
+        buffer.position(this.toBufferOffset(record.end));
+
+        // record header is big endian
+        buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+        // read shape record header
+        int recordNumber = ++maxElementId;
+        short signature = buffer.getShort();
+
+        // byte type = (byte) (buffer.get() & 0x7f);
+        byte type = (byte) ((signature >>> 8) & 0x007f);
+
+        // silly Bentley say contentLength is in 2-byte words
+        // and ByteByffer uses bytes.
+        // track the record location
+        int elementLength = (buffer.getShort() * 2) + 4;
+
+        if (!buffer.isReadOnly() && !useMemoryMappedBuffer) {
+            // capacity is less than required for the record
+            // copy the old into the newly allocated
+            if (buffer.capacity() < elementLength) {
+                this.currentOffset += buffer.position();
+
+                ByteBuffer old = buffer;
+
+                // ensure enough capacity for one more record header
+                buffer = Dgn7fileReader.ensureCapacity(buffer, elementLength, useMemoryMappedBuffer);
+                buffer.put(old);
+                fill(buffer, channel);
+                buffer.position(0);
+            } else
+
+                // remaining is less than record length
+                // compact the remaining data and read again,
+                // allowing enough room for one more record header
+                if (buffer.remaining() < elementLength) {
+                    this.currentOffset += buffer.position();
+                    buffer.compact();
+                    fill(buffer, channel);
+                    buffer.position(0);
+                }
+        }
+
+        // shape record is all little endian
+        // buffer.order(ByteOrder.LITTLE_ENDIAN);
+        // read the type, handlers don't need it
+        ElementType recordType = ElementType.forID(type);
+
+        logger.debug("nextElement at " + this.toBufferOffset(record.end) + ":type=" + type);
+
+        // this usually happens if the handler logic is bunk,
+        // but bad files could exist as well...
+
+        /*
+         * if (recordType != ElementType.NULL && recordType != fileElementType)
+         * {
+         *   throw new IllegalStateException("ShapeType changed illegally from " + fileElementType + " to " + recordType);
+         * }
+         */
+
+        // peek at bounds, then reset for handler
+        // many handler's may ignore bounds reading, but we don't want to
+        // second guess them...
+        buffer.mark();
+
+        if (recordType.isMultiPoint()) {
+            int lowCoorX = buffer.getInt();
+
+            lowCoorX = DgnUtility.convertFromDGN(lowCoorX);
+            record.minX = DgnUtility.converUnitToCoord(lowCoorX);
+
+            int lowCoorY = buffer.getInt();
+
+            lowCoorY = DgnUtility.convertFromDGN(lowCoorY);
+            record.minY = DgnUtility.converUnitToCoord(lowCoorY);
+
+            int lowCoorZ = buffer.getInt();
+
+            lowCoorZ = DgnUtility.convertFromDGN(lowCoorZ);
+            record.minZ = DgnUtility.converUnitToCoord(lowCoorZ);
+
+            int highCoorX = buffer.getInt();
+
+            highCoorX = DgnUtility.convertFromDGN(highCoorX);
+            record.maxX = DgnUtility.converUnitToCoord(highCoorX);
+
+            int highCoorY = buffer.getInt();
+
+            highCoorY = DgnUtility.convertFromDGN(highCoorY);
+            record.maxY = DgnUtility.converUnitToCoord(highCoorY);
+
+            int highCoorZ = buffer.getInt();
+
+            highCoorZ = DgnUtility.convertFromDGN(highCoorZ);
+            record.maxZ = DgnUtility.converUnitToCoord(highCoorZ);
+        }
+
+        buffer.reset();
+        record.offset = record.end;
+
+        // update all the record info.
+        record.length = elementLength;
+        record.signature = signature;
+        record.number = recordNumber;
+        record.buffer = buffer;
+
+        // remember, we read one int already...
+        record.end = this.toFileOffset(buffer.position()) + elementLength - 4;
+        // record.end = this.toFileOffset(buffer.position()) + elementLength;
+
+        // mark this position for the reader
+        record.start = buffer.position();
+
+        // clear any cached record
+        record.handler = recordType.getElementHandler();
+        record.element = null;
+
+        return record;
+    }
+
+    private void init(boolean strict) throws IOException, Dgn7fileException {
+        header = readHeader(channel, strict);
+
+        if (useMemoryMappedBuffer) {
+            FileChannel fc = channel;
+
+            buffer = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size());
+
+            // buffer.position(100);
+            buffer.position(header.size());
+            this.currentOffset = 0;
+        } else {
+            // force useMemoryMappedBuffer to false
+            this.useMemoryMappedBuffer = false;
+
+            // start with 8K buffer
+            buffer = ByteBuffer.allocateDirect(8 * 1024);
+            fill(buffer, channel);
+            buffer.flip();
+            this.currentOffset = header.size();
+        }
+
+        headerTransfer = ByteBuffer.allocate(4);
+        headerTransfer.order(ByteOrder.LITTLE_ENDIAN);
+
+        // make sure the record end is set now...
+        record.end = toFileOffset(buffer.position());
+    }
+
+    public static Dgn7fileHeader readHeader(FileChannel channel, boolean strict) throws IOException {
+        ByteBuffer buffer = ByteBuffer.allocateDirect(4);
+
+        if (fill(buffer, channel) == -1) {
+            throw new EOFException("Premature end of header");
+        }
+
+        buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+        int length = buffer.getShort(2) * 2;
+        ByteBuffer old = buffer;
+
+        old.position(0);
+
+        // ensure enough capacity for one more record header
+        buffer = ByteBuffer.allocateDirect(length + 4);
+        buffer.put(old);
+
+        if (fill(buffer, channel) == -1) {
+            throw new EOFException("Premature end of header");
+        }
+
+        buffer.position(0);
+
+        Dgn7fileHeader header = new Dgn7fileHeader();
+
+        header.read(buffer, strict);
+
+        return header;
+    }
+
+    protected static int fill(ByteBuffer buffer, FileChannel channel) throws IOException {
+        int r = buffer.remaining();
+
+        // channel reads return -1 when EOF or other error
+        // because they a non-blocking reads, 0 is a valid return value!!
+        while ((buffer.remaining() > 0) && (r != -1)) {
+            r = channel.read(buffer);
+        }
+
+        if (r == -1) {
+            buffer.limit(buffer.position());
+        }
+
+        return r;
+    }
+
+    private void allocateBuffers() {
+        buffer = ByteBuffer.allocateDirect(16 * 1024);
+    }
+
+    private void checkShapeBuffer(int size) {
+        if (buffer.capacity() < size) {
+            if (buffer != null)
+                NIOUtilities.clean(buffer);
+            buffer = ByteBuffer.allocateDirect(size);
+        }
+    }
+
+    private void drain() throws IOException {
+        buffer.flip();
+        while (buffer.remaining() > 0)
+            channel.write(buffer);
+        buffer.flip().limit(buffer.capacity());
+    }
+
+    private int toBufferOffset(int offset) {
+        return (int) (offset - currentOffset);
+    }
+
+    private int toFileOffset(int offset) {
+        return (int) (currentOffset + offset);
+    }
+
+    public void writeElement(Element element) throws IOException {
+        // element.raw
+        if (element == null) return;
+        ByteBuffer writeBuffer = ByteBuffer.allocateDirect(element.raw.length * 2);
+        writeBuffer.order(ByteOrder.LITTLE_ENDIAN);
+        for (short word : element.raw) {
+            writeBuffer.putShort(word);
+        }
+        writeBuffer.rewind();
+
+        channel.write(writeBuffer);
+    }
+
+    public void toEnd() throws IOException, Dgn7fileException {
+        while (hasNext()) {
+            nextElement();
+        }
+    }
+
+    public void close() throws IOException {
+        lock.unlockWrite();
+        lock.unlockRead();
+
+        if (channel.isOpen()) {
+            channel.close();
+            streamLogger.close();
+        }
+
+        if (buffer instanceof MappedByteBuffer) {
+            NIOUtilities.clean(buffer);
+        }
+
+        channel = null;
+        header = null;
+    }
+
+    public void writeEOF() throws IOException {
+        ByteBuffer writeBuffer = ByteBuffer.allocateDirect(2);
+        writeBuffer.order(ByteOrder.LITTLE_ENDIAN);
+        writeBuffer.putShort((short) -1);
+        channel.write(writeBuffer);
+
+    }
+}
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Element.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Element.java
index e82fc83..91f0198 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Element.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/Element.java
@@ -13,11 +13,11 @@
 import com.ximple.util.DgnUtility;
 
 /**
- * Record
+ * FileRecord
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/18 �W�� 11:14:50
+ * @since 2006/5/18 �W�� 11:14:50
  */
 public class Element {
     public static final int CONSTRUCTION_CLASS = 0;
@@ -36,8 +36,9 @@
     protected short[] raw;
     protected byte attrOffset = 0;
     protected ByteBuffer rawBuffer;
+    protected boolean newElement = false;
 
-    public Element(byte[] raw) {
+    Element(byte[] raw) {
         // this.raw = raw;
         this.raw = new short[raw.length / 2];
         rawBuffer = ByteBuffer.wrap(raw);
@@ -47,6 +48,13 @@
 
     public int getLineStyle() {
         return (raw[17] & 0x0007);
+    }
+
+    protected void setLineStyle(int value) {
+        if (value > -1 && value < 8)
+            raw[17] = (short) ((raw[17] & 0xfff8) | (value & 0x0007));
+        else
+            new IllegalArgumentException("Out of Range!");
     }
 
     public Envelope getRange() {
@@ -92,6 +100,10 @@
         return (short) ((raw[0] >>> 7) & 0x0001) == 1;
     }
 
+    protected void setComponentElement(boolean value) {
+        raw[0] = (short) ((raw[0] & 0xff7f) | (value ? 0x0080 : 0x0));
+    }
+
     public boolean removeUserAttributeData(int iLinkageId) {
         return true;
     }
@@ -104,12 +116,27 @@
         return (short) ((raw[0] >>> 15) & 0x0001) == 1;
     }
 
+    protected void setDeleted(boolean value) {
+            raw[0] = (short) ((raw[0] & 0x7fff) | ((((value) ? 1 : 0) << 15) & 0x8000));
+    }
+
     public int getColorIndex() {
         return ((raw[17] >>> 8) & 0x00ff);
     }
 
+    protected void setColorIndex(int value) {
+        if (value > -1 && value < 256)
+        {
+            raw[17] = (short) ((raw[17] & 0x00ff) | (value << 8 & 0xff00));
+        } else  new IllegalArgumentException("Out of Range!");
+    }
+
     public int getType() {
         return ((raw[0] >>> 8) & 0x007f);
+    }
+
+    protected void setType(int value) {
+        raw[0] = (short) ((raw[0] & 0x80ff) | (value << 8) & 0x3f00);
     }
 
     public ElementType getElementType() {
@@ -231,7 +258,7 @@
         public Exception() {
         }
 
-        // Constructs an Record.Exception with no detail message.
+        // Constructs an ElementRecord.Exception with no detail message.
         public Exception(String oStrMessage) {
             super(oStrMessage);
         }
@@ -263,7 +290,7 @@
             return elementType;
         }
 
-        public Object read(ByteBuffer buffer, short signature, int length) {
+        public Element read(ByteBuffer buffer, short signature, int length) {
             byte[] dst = new byte[length];
             try {
                 buffer.get(dst, 4, dst.length - 4);
@@ -306,4 +333,74 @@
             return new Element(raw);
         }
     }
+
+    public static final class FileRecord {
+        int length;
+        int number = 0;
+        int offset;           // Relative to the whole file
+        int start = 0;    // Relative to the current loaded buffer
+        short signature = 0;
+
+        /**
+         * The minimum X value.
+         */
+        public double minX;
+
+        /**
+         * The minimum Y value.
+         */
+        public double minY;
+
+        /**
+         * The minimum Z value.
+         */
+        public double minZ;
+
+        /**
+         * The maximum X value.
+         */
+        public double maxX;
+
+        /**
+         * The maximum Y value.
+         */
+        public double maxY;
+
+        /**
+         * The maximum Z value.
+         */
+        public double maxZ;
+
+        // ElementType type;
+        int end = 0;    // Relative to the whole file
+        Object element = null;
+        IElementHandler handler;
+        ByteBuffer buffer;
+
+        public Object element() {
+            if (element == null) {
+                buffer.position(start);
+                buffer.order(ByteOrder.LITTLE_ENDIAN);
+
+                if (handler == null) {
+                    return null;
+                }
+
+                element = handler.read(buffer, signature, length);
+            }
+
+            return element;
+        }
+
+        public int offset() {
+            return offset;
+        }
+
+        /**
+         * A summary of the record.
+         */
+        public String toString() {
+            return "FileRecord " + number + " length " + length + " bounds " + minX + "," + minY + " " + maxX + "," + maxY;
+        }
+    }
 }
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementFactory.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementFactory.java
new file mode 100644
index 0000000..dc52e46
--- /dev/null
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementFactory.java
@@ -0,0 +1,111 @@
+package com.ximple.io.dgn7;
+
+import com.vividsolutions.jts.geom.Coordinate;
+import com.vividsolutions.jts.geom.GeometryFactory;
+import com.vividsolutions.jts.geom.LineString;
+import com.vividsolutions.jts.geom.LinearRing;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+
+public class ElementFactory {
+    private static final int DEFAULT_ELMHEAD_LENGTH = 28;
+    private static final int DEFAULT_DISPHEAD_LENGTH = 8;
+    private static final int MINIMAL_ELEMLENGTH = 18 * 2;
+
+    private static final int MAXINUM_LINESTRING_PTLEN = 100;
+
+    private static ElementFactory elementFactory = new ElementFactory();
+    private static GeometryFactory factory = new GeometryFactory();
+
+    public static Element createLineString(LineString linestring) {
+        Coordinate[] pts = linestring.getCoordinates();
+        LineStringElement element = elementFactory.createLineStringElement(pts);
+        element.setRange(linestring.getEnvelopeInternal());
+        return element;
+    }
+
+    public static Element createShape(LinearRing ring) {
+        Coordinate[] pts = ring.getCoordinates();
+        int elmsize = MINIMAL_ELEMLENGTH + 2 + pts.length * 8;
+        ShapeElement element = new ShapeElement(new byte[elmsize]);
+        for (int i = 0; i < pts.length; i++) {
+            element.setX(i, pts[i].x);
+            element.setY(i, pts[i].y);
+        }
+        element.setVerticeSize(pts.length);
+        element.setType(ElementType.SHAPE.id);
+        element.setRange(ring.getEnvelopeInternal());
+        element.setLevelIndex(0);
+        element.setColorIndex(0);
+        element.setWeight(0);
+        element.setLineStyle(0);
+        return element;
+    }
+
+    private LineStringElement createLineStringElement(Coordinate[] pts) {
+        int elmsize = MINIMAL_ELEMLENGTH + 2 + pts.length * 8;
+        LineStringElement element = new LineStringElement(new byte[elmsize]);
+        for (int i = 0; i < pts.length; i++) {
+            element.setX(i, pts[i].x);
+            element.setY(i, pts[i].y);
+        }
+        element.setVerticeSize(pts.length);
+        element.setType(ElementType.LINESTRING.id);
+        element.setLevelIndex(0);
+        element.setColorIndex(0);
+        element.setWeight(0);
+        element.setLineStyle(0);
+        return element;
+    }
+
+    private ShapeElement createShapeElement(Coordinate[] pts) {
+        int elmsize = MINIMAL_ELEMLENGTH + 2 + pts.length * 8;
+        ShapeElement element = new ShapeElement(new byte[elmsize]);
+        for (int i = 0; i < pts.length; i++) {
+            element.setX(i, pts[i].x);
+            element.setY(i, pts[i].y);
+        }
+        element.setVerticeSize(pts.length);
+        element.setType(ElementType.SHAPE.id);
+        element.setLevelIndex(0);
+        element.setColorIndex(0);
+        element.setWeight(0);
+        element.setLineStyle(0);
+        return element;
+    }
+
+    public static Element createComplexChain(LineString linestring) {
+        LinkedList<LineStringElement> elms = new LinkedList<LineStringElement>();
+        Coordinate[] allpts = linestring.getCoordinates();
+        int segsize = allpts.length / MAXINUM_LINESTRING_PTLEN;
+        int currentpos = 0;
+        for (int seg = 0; seg < segsize; seg++) {
+            Coordinate[] pts = Arrays.copyOfRange(allpts,
+                    currentpos, currentpos + MAXINUM_LINESTRING_PTLEN, Coordinate[].class);
+            LineStringElement element = elementFactory.createLineStringElement(pts);
+            currentpos += MAXINUM_LINESTRING_PTLEN;
+            element.setRange(element.toGeometry(factory).getEnvelopeInternal());
+            element.setComponentElement(true);
+            elms.add(element);
+        }
+        int remain = allpts.length % MAXINUM_LINESTRING_PTLEN;
+        Coordinate[] pts = Arrays.copyOfRange(allpts,
+                currentpos, currentpos + remain, Coordinate[].class);
+        LineStringElement element = elementFactory.createLineStringElement(pts);
+        element.setRange(element.toGeometry(factory).getEnvelopeInternal());
+        element.setComponentElement(true);
+        elms.add(element);
+
+        ComplexChainElement result = new ComplexChainElement(new byte[MINIMAL_ELEMLENGTH + 12]);
+        result.addAll(elms);
+        result.setRange(linestring.getEnvelopeInternal());
+        result.setType(ElementType.COMPLEXCHAIN.id);
+        result.setLevelIndex(0);
+        result.setColorIndex(0);
+        result.setWeight(0);
+        result.setLineStyle(0);
+
+        return result;
+    }
+}
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementType.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementType.java
index 7e0615d..1a5166f 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementType.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ElementType.java
@@ -30,14 +30,14 @@
 |    23         Circular Truncated Cone                                 |
 |    24         B-Spline Surface (complex)                              |
 |    25         B-Spline Surface boundary                               |
-|    26         B-Spline Knot Record                                   |
+|    26         B-Spline Knot ElementRecord                             |
 |    27         B-Spline Curve (complex)                                |
 |    28         B-Spline Weight Factor                                  |
-|    33         Dimension Record                                       |
-|    34         Shared Cell Definition Record                          |
-|    35         Shared Cell Record                                     |
-|    36         Multiline Record                                       |
-|    37         Attribute Record                                       |
+|    33         Dimension ElementRecord                                 |
+|    34         Shared Cell Definition ElementRecord                    |
+|    35         Shared Cell ElementRecord                               |
+|    36         Multiline ElementRecord                                 |
+|    37         Attribute ElementRecord                                 |
 |    38         DgnStore Component                                      |
 |    39         DgnStore Header                                         |
 |    66         MicroStation Application                                |
@@ -45,22 +45,22 @@
 |    88         Raster Component                                        |
 |    90         Raster Reference Attachment                             |
 |    91         Raster Reference Component                              |
-|    92         Raster Hierarchy Record                                |
+|    92         Raster Hierarchy ElementRecord                          |
 |    93         Raster Hierarchy Component                              |
-|    94         Raster Frame Record                                    |
-|    95         Table Entry Record                                     |
-|    96         Table Header Record                                    |
-|    97         View Group Record                                      |
-|    98         View Record                                            |
-|    99         Level Mask Record                                      |
-|    100        Reference Attach Record                                |
+|    94         Raster Frame ElementRecord                              |
+|    95         Table Entry ElementRecord                               |
+|    96         Table Header ElementRecord                              |
+|    97         View Group ElementRecord                                |
+|    98         View ElementRecord                                      |
+|    99         Level Mask ElementRecord                                |
+|    100        Reference Attach ElementRecord                          |
 |    101        Matrix Header                                           |
 |    102        Matrix Int Data                                         |
 |    103        Matrix Double Data                                      |
 |    105        Mesh Header                                             |
-|    106        Extended Record (graphic) (complex)                    |
-|    107        Extended Record (non-graphic) (complex)                |
-|    108        Reference Override Record                              |
+|    106        Extended ElementRecord (graphic) (complex)                    |
+|    107        Extended ElementRecord (non-graphic) (complex)                |
+|    108        Reference Override ElementRecord                              |
 |    110        Named Group Header                                      |
 |    111        Named Group Component                                   |
 |                                                                       |
@@ -71,7 +71,7 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/17 �U�� 01:26:49
+ * @since 2006/5/17 �U�� 01:26:49
  */
 public final class ElementType {
     /**
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/EllipseElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/EllipseElement.java
index d9a5339..fbe715c 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/EllipseElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/EllipseElement.java
@@ -14,7 +14,7 @@
 public class EllipseElement extends Element implements GeometryConverter {
     private static final Logger logger = Logger.getLogger(EllipseElement.class);
 
-    public EllipseElement(byte[] raw) {
+    EllipseElement(byte[] raw) {
         super(raw);
     }
 
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/IElementHandler.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/IElementHandler.java
index 263b08d..e7e3b2d 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/IElementHandler.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/IElementHandler.java
@@ -9,12 +9,12 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/17 �U�� 01:50:26
+ * @since 2006/5/17 �U�� 01:50:26
  */
 public interface IElementHandler {
     public ElementType getElementType();
 
-    public Object read(ByteBuffer buffer, short signature, int length);
+    public Element read(ByteBuffer buffer, short signature, int length);
 
     public void write(ByteBuffer buffer, Object element);
 
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/LineElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/LineElement.java
index fd1a674..09694ab 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/LineElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/LineElement.java
@@ -15,12 +15,12 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/18 �W�� 11:34:59
+ * @since 2006/5/18 �W�� 11:34:59
  */
 public class LineElement extends Element implements GeometryConverter {
     private static final Logger logger = Logger.getLogger(LineElement.class);
 
-    public LineElement(byte[] raw) {
+    LineElement(byte[] raw) {
         super(raw);
     }
 
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/LineStringElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/LineStringElement.java
index 04fb7fb..7e82921 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/LineStringElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/LineStringElement.java
@@ -15,12 +15,12 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/18 �U�� 02:48:58
+ * @since 2006/5/18
  */
 public class LineStringElement extends Element implements GeometryConverter {
     private static final Logger logger = Logger.getLogger(LineStringElement.class);
 
-    public LineStringElement(byte[] raw) {
+    LineStringElement(byte[] raw) {
         super(raw);
     }
 
@@ -54,6 +54,10 @@
         return raw[18] & 0x0000ffff;
     }
 
+    public void setVerticeSize(int size) {
+        raw[18] = (short) (size & 0x0000ffff);
+    }
+
     public double getLength() {
         double result = 0.0;
         Coordinate[] vset = getVertices();
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ShapeElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ShapeElement.java
index 27e8220..6fd7d89 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ShapeElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/ShapeElement.java
@@ -12,12 +12,12 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/18 �U�� 03:08:43
+ * @since 2006/5/18 �U�� 03:08:43
  */
 public class ShapeElement extends LineStringElement implements GeometryConverter {
     private static final Logger logger = Logger.getLogger(ShapeElement.class);
 
-    public ShapeElement(byte[] raw) {
+    ShapeElement(byte[] raw) {
         super(raw);
     }
 
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TagElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TagElement.java
index 37adb0e..3f2dd6b 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TagElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TagElement.java
@@ -8,7 +8,7 @@
 public class TagElement extends Element implements GeometryConverter {
     private static final Logger logger = Logger.getLogger(TagElement.class);
 
-    public TagElement(byte[] raw) {
+    TagElement(byte[] raw) {
         super(raw);
     }
 
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TcbElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TcbElement.java
index 0ba2fd2..e5bb065 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TcbElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TcbElement.java
@@ -7,12 +7,12 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/18 �U�� 05:03:46
+ * @since 2006/5/18 �U�� 05:03:46
  */
 public class TcbElement extends Element {
     private static final Logger logger = Logger.getLogger(TcbElement.class);
 
-    public TcbElement(byte[] raw) {
+    TcbElement(byte[] raw) {
         super(raw);
     }
 
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TextElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TextElement.java
index 6c50b18..ed94f9a 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TextElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TextElement.java
@@ -22,7 +22,7 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/18 �W�� 11:45:29
+ * @since 2006/5/18 �W�� 11:45:29
  */
 public class TextElement extends Element implements GeometryConverter {
     private static final Logger logger = Logger.getLogger(TextElement.class);
@@ -63,7 +63,7 @@
     public static final int TXTJUST_RD = 24;   /* Right Descender */
     public static final int TXTJUST_NONE = 127;/* no justfication */
 
-    public TextElement(byte[] raw) {
+    TextElement(byte[] raw) {
         super(raw);
     }
 
diff --git a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TextNodeElement.java b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TextNodeElement.java
index b5d4cb8..bfcb788 100644
--- a/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TextNodeElement.java
+++ b/xdgnjobs/ximple-dgnio/src/main/java/com/ximple/io/dgn7/TextNodeElement.java
@@ -22,14 +22,14 @@
  *
  * @author Ulysses
  * @version 0.1
- * @since 2006/5/18 �U�� 04:02:58
+ * @since 2006/5/18 �U�� 04:02:58
  */
 public class TextNodeElement extends Element implements ComplexElement, GeometryConverter {
     private static final Logger logger = Logger.getLogger(TextElement.class);
 
     private ArrayList<Element> list = new ArrayList<Element>();
 
-    public TextNodeElement(byte[] raw) {
+    TextNodeElement(byte[] raw) {
         super(raw);
     }
 
diff --git a/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7TextElementReaderTest.java b/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7TextElementReaderTest.java
index b2bc00e..92a3c0b 100644
--- a/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7TextElementReaderTest.java
+++ b/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7TextElementReaderTest.java
@@ -17,7 +17,7 @@
  * Dgn7TextElementReaderTest
  * User: Ulysses
  * Date: 2008/1/10
- * Time: �W�� 12:19:14
+ * Time: �W�� 12:19:14
  */
 public class Dgn7TextElementReaderTest {
     private final static Logger logger = Logger.getLogger(Dgn7fileReaderTest.class);
@@ -70,7 +70,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
@@ -148,6 +148,6 @@
             count++;
         }
 
-        logger.info("ElementRecord Count=" + count);
+        logger.info("FileRecord Count=" + count);
     }
 }
diff --git a/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileReaderTest.java b/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileReaderTest.java
index afc66f8..8f227ad 100644
--- a/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileReaderTest.java
+++ b/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileReaderTest.java
@@ -14,7 +14,7 @@
  * Dgn7fileReaderTest
  * User: Ulysses
  * Date: 2007/10/24
- * Time: �W�� 01:43:41
+ * Time: �W�� 01:43:41
  * To change this template use File | Settings | File Templates.
  */
 public class Dgn7fileReaderTest {
@@ -42,7 +42,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
@@ -94,6 +94,6 @@
             count++;
         }
 
-        logger.info("ElementRecord Count=" + count);
+        logger.info("FileRecord Count=" + count);
     }
 }
diff --git a/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileWriterTest.java b/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileWriterTest.java
new file mode 100644
index 0000000..0e8c65d
--- /dev/null
+++ b/xdgnjobs/ximple-dgnio/src/test/java/com/ximple/io/dgn7/Dgn7fileWriterTest.java
@@ -0,0 +1,115 @@
+package com.ximple.io.dgn7;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Logger;
+import org.geotools.TestData;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+
+public class Dgn7fileWriterTest {
+    private final static Logger logger = Logger.getLogger(Dgn7fileReaderTest.class);
+
+    // private final static String testFilePath = "test-data\\testHV.dgn";
+    private final static String testFilePath = "testHV.dgn";
+    private FileInputStream _fs;
+
+    @BeforeTest
+    public void setUp() throws IOException {
+        File dataFile = TestData.file(this, testFilePath);
+        if (!dataFile.exists()) {
+            return;
+        }
+
+        _fs = new FileInputStream(dataFile);
+    }
+    
+    @Test
+    public void testWrite() {
+    }
+
+    @Test
+    public void testCopy() throws Dgn7fileException, IOException {
+        File target = TestData.temp(this, "testdgn2d.dgn");
+        FileUtils.copyFile(TestData.file(this, "dgnseed2d.dgn"), target);
+        RandomAccessFile targetStream = new RandomAccessFile(target, "rw");
+        FileChannel fctarget = targetStream.getChannel();
+        Lock lock = new Lock();
+
+        Dgn7fileReader targetReader = new Dgn7fileReader(fctarget, new Lock());
+        while (targetReader.hasNext()) {
+            targetReader.nextElement();
+        }
+
+        Dgn7fileWriter writer = new Dgn7fileWriter(fctarget, lock);
+
+        FileChannel fc = _fs.getChannel();
+        Dgn7fileReader reader = new Dgn7fileReader(fc, new Lock());
+        int count = 0;
+        Element lastComplex = null;
+        while (reader.hasNext()) {
+            Element.FileRecord record = reader.nextElement();
+            if (record.element() != null) {
+                Element element = (Element) record.element();
+                ElementType type = element.getElementType();
+
+                if ((!type.isComplexElement()) && (!element.isComponentElement())) {
+                    if (lastComplex != null) {
+                        // @todo add process in here
+                        lastComplex = null;
+                    }
+
+                    // @todo add process in here
+                } else if (element.isComponentElement()) {
+                    if (lastComplex != null) {
+                        ((ComplexElement) lastComplex).add(element);
+                    }
+                } else if (type.isComplexElement()) {
+                    if (lastComplex == null) {
+                        lastComplex = element;
+                    } else {
+                        // @todo add process in here
+                        lastComplex = element;
+                    }
+                }
+
+                if (element.getElementType().isComplexElement()) {
+                    if (element instanceof ComplexChainElement) {
+                        ComplexChainElement complexChain = (ComplexChainElement) element;
+                        int size = complexChain.size();
+                        for (Object aComplexChain : complexChain) {
+                            Element subElement = (Element) aComplexChain;
+                            subElement.getType();
+                        }
+                    }
+
+                    if (element instanceof ComplexShapeElement) {
+                        ComplexShapeElement complexShape = (ComplexShapeElement) element;
+                    }
+
+                    if (element instanceof TextNodeElement) {
+                        TextNodeElement textNode = (TextNodeElement) element;
+                        int size = textNode.size();
+                        for (int i = 0; i < size; i++) {
+                            Element subElement = textNode.get(i);
+                            subElement.getElementType();
+                        }
+                    }
+                }
+
+                writer.writeElement(element);
+            }
+            count++;
+        }
+        writer.writeEOF();
+        writer.close();
+
+        // FileUtils.copyFile(target, new File("G://target.dgn"));
+    }
+}
diff --git a/xdgnjobs/ximple-dgnio/src/test/resources/com/ximple/io/dgn7/test-data/dgnseed2d.dgn b/xdgnjobs/ximple-dgnio/src/test/resources/com/ximple/io/dgn7/test-data/dgnseed2d.dgn
new file mode 100644
index 0000000..367c782
--- /dev/null
+++ b/xdgnjobs/ximple-dgnio/src/test/resources/com/ximple/io/dgn7/test-data/dgnseed2d.dgn
Binary files differ
diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2MySQLJob.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2MySQLJob.java
index bd0fce0..79f88f0 100644
--- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2MySQLJob.java
+++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2MySQLJob.java
@@ -252,7 +252,7 @@
     }
 
     /**
-     * Connectivity�ƻs�@�Ӫ����A�b�d�߹q�y��V�ɥΨӤ��OMS��Ʈw���q���s����(Connectivity)
+     * Connectivity�ƻs�@�Ӫ����A�b�d�߹q�y��V�ɥΨӤ��OMS��Ʈw���q���s����(Connectivity)
      *
      * @param jobContext job context
      * @throws SQLException sql exception
@@ -538,9 +538,9 @@
     }
 
     /**
-     * �����ഫ���޹��ɪ��u�@
+     * �����ഫ���޹��ɪ��u�@
      *
-     * @param context �u�@��������
+     * @param context �u�@��������
      * @throws org.quartz.JobExecutionException
      *          exception
      */
@@ -613,7 +613,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
@@ -654,7 +654,7 @@
 
 
     /**
-     * �����ഫ��L�]�p���ɪ��u�@
+     * �����ഫ��L�]�p���ɪ��u�@
      *
      * @param context jobContext
      * @throws org.quartz.JobExecutionException
@@ -729,7 +729,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
@@ -880,7 +880,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2OraSDOJob.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2OraSDOJob.java
index 824a617..6dec3e7 100644
--- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2OraSDOJob.java
+++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2OraSDOJob.java
@@ -254,7 +254,7 @@
     }
 
     /**
-     * Connectivity�ƻs�@�Ӫ����A�b�d�߹q�y��V�ɥΨӤ��OMS��Ʈw���q���s����(Connectivity)
+     * Connectivity�ƻs�@�Ӫ����A�b�d�߹q�y��V�ɥΨӤ��OMS��Ʈw���q���s����(Connectivity)
      *
      * @param jobContext job context
      * @throws SQLException sql exception
@@ -541,9 +541,9 @@
     }
 
     /**
-     * �����ഫ���޹��ɪ��u�@
+     * �����ഫ���޹��ɪ��u�@
      *
-     * @param context �u�@��������
+     * @param context �u�@��������
      * @throws org.quartz.JobExecutionException
      *          exception
      */
@@ -616,7 +616,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
@@ -657,7 +657,7 @@
 
 
     /**
-     * �����ഫ��L�]�p���ɪ��u�@
+     * �����ഫ��L�]�p���ɪ��u�@
      *
      * @param context jobContext
      * @throws org.quartz.JobExecutionException
@@ -732,7 +732,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
@@ -883,7 +883,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2PostGISJob.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2PostGISJob.java
index f2f9553..4d5a258 100644
--- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2PostGISJob.java
+++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2PostGISJob.java
@@ -341,7 +341,7 @@
     }
 
     /**
-     * Connectivity�ƻs�@�Ӫ����A�b�d�߹q�y��V�ɥΨӤ��OMS��Ʈw���q���s����(Connectivity)
+     * Connectivity�ƻs�@�Ӫ����A�b�d�߹q�y��V�ɥΨӤ��OMS��Ʈw���q���s����(Connectivity)
      *
      * @param jobContext job context
      * @throws SQLException sql exception
@@ -398,7 +398,7 @@
             stmt.close();
         } catch (SQLException e)
         {
-            logger.warn("HIBERNATE_SEQUENCE �w�g�s�b");       
+            logger.warn("HIBERNATE_SEQUENCE �w�g�s�b");       
         }
     }
 
@@ -705,9 +705,9 @@
     }
 
     /**
-     * �����ഫ���޹��ɪ��u�@
+     * �����ഫ���޹��ɪ��u�@
      *
-     * @param context �u�@��������
+     * @param context �u�@��������
      * @throws org.quartz.JobExecutionException
      *          exception
      */
@@ -816,7 +816,7 @@
 
         while (reader.hasNext()) {
             if (isProfileMode()) markProcessTime();
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
@@ -863,7 +863,7 @@
 
 
     /**
-     * �����ഫ��L�]�p���ɪ��u�@
+     * �����ഫ��L�]�p���ɪ��u�@
      *
      * @param context jobContext
      * @throws org.quartz.JobExecutionException
@@ -972,7 +972,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
@@ -1125,7 +1125,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
diff --git a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java
index 4a0c023..fa84b51 100644
--- a/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java
+++ b/xdgnjobs/ximple-spatialjob/src/main/java/com/ximple/eofms/jobs/OracleConvertDgn2ShpJob.java
@@ -162,7 +162,7 @@
     }
 
     /**
-     * Connectivity�ƻs�@�Ӫ����A�b�d�߹q�y��V�ɥΨӤ��OMS��Ʈw���q���s����(Connectivity)
+     * Connectivity�ƻs�@�Ӫ����A�b�d�߹q�y��V�ɥΨӤ��OMS��Ʈw���q���s����(Connectivity)
      *
      * @param jobContext job context
      * @throws SQLException sql exception
@@ -450,9 +450,9 @@
     }
 
     /**
-     * �����ഫ���޹��ɪ��u�@
+     * �����ഫ���޹��ɪ��u�@
      *
-     * @param context �u�@��������
+     * @param context �u�@��������
      * @throws org.quartz.JobExecutionException
      *          exception
      */
@@ -524,7 +524,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
@@ -565,7 +565,7 @@
 
 
     /**
-     * �����ഫ��L�]�p���ɪ��u�@
+     * �����ഫ��L�]�p���ɪ��u�@
      *
      * @param context jobContext
      * @throws org.quartz.JobExecutionException
@@ -641,7 +641,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();
@@ -789,7 +789,7 @@
         int count = 0;
         Element lastComplex = null;
         while (reader.hasNext()) {
-            Dgn7fileReader.Record record = reader.nextElement();
+            Element.FileRecord record = reader.nextElement();
             if (record.element() != null) {
                 Element element = (Element) record.element();
                 ElementType type = element.getElementType();

--
Gitblit v0.0.0-SNAPSHOT