diff --git a/README.md b/README.md index aaa2847..31de390 100644 --- a/README.md +++ b/README.md @@ -20,19 +20,19 @@ Saxeed strives to add as much convenience on top of plain old SAX, while adding ### Capabilities -Each tag visitor have access to / can modify the following: - -| | Tag Start | Tag End | -|------------------------------------|------------------------|------------------------| -| Access Tag attributes | ☑ | ☑ | -| Access Parent(s) Tag attributes | ☑ | ☑ | -| Add Child Tags | ☑ | ☑ (before closing tag) | -| Add Sibling Tags (NOT IMPLEMENTED) | ☑ (before and after) | ☑ (only after) | -| Add Parent Tag (`wrapWith()`) | ☑ | ☐ | -| Change Attributes | ☑ | ☐ | -| Delete Tag (`unwrap()`) | ☑ | ☐ | -| Delete Tag Recursively (`skip()`) | ☑ | ☐ | -| Delete Child Tags (`empty()`) | ☑ | ☐ | +Each tag visitor do the following: + +| | Tag Start | Tag End | Text Content | +|-----------------------------------------|------------------------|------------------------|--------------| +| Access Tag attributes | ☑ | ☑ | ☑ | +| Access Parent(s) Tag attributes | ☑ | ☑ | ☑ | +| Add Child Tags/Text | ☑ | ☑ (before closing tag) | ☑ | +| Add Sibling Tags/text (NOT IMPLEMENTED) | ☑ (before and after) | ☑ (only after) | ☑ | +| Add Parent Tag (`wrapWith()`) | ☑ | ☐ | ☑ | +| Change Attributes | ☑ | ☐ | ☐ | +| Delete Tag (`unwrap()`) | ☑ | ☐ | n/a | +| Delete Tag Recursively (`skip()`) | ☑ | ☐ | n/a | +| Delete Child Tags (`empty()`) | ☑ | ☐ | n/a | More complex changes can be implemented by subscribing visitors to multiple tags, and retaining information between their visits. diff --git a/src/main/java/com/github/olivergondza/saxeed/Tag.java b/src/main/java/com/github/olivergondza/saxeed/Tag.java index 545a08e..c495f5e 100644 --- a/src/main/java/com/github/olivergondza/saxeed/Tag.java +++ b/src/main/java/com/github/olivergondza/saxeed/Tag.java @@ -106,6 +106,28 @@ interface Start extends Tag { * @return Tag instance created. */ Tag.Start wrapWith(String name); + + /** + * Set text to write after opening tag. + */ + void addText(String text); + } + + interface Chars extends Tag { + + /** + * Add new child element. + * + * Its attributes and children can be added after. + * + * @return Tag instance added. + */ + Tag.Start addChild(String name); + + /** + * Set text to write before closing tag. + */ + void addText(String text); } /** @@ -122,5 +144,10 @@ interface End extends Tag { * @return Tag instance added. */ Tag.Start addChild(String name); + + /** + * Set text to write before closing tag. + */ + void addText(String text); } } diff --git a/src/main/java/com/github/olivergondza/saxeed/UpdatingVisitor.java b/src/main/java/com/github/olivergondza/saxeed/UpdatingVisitor.java index 102b2f6..b40260d 100644 --- a/src/main/java/com/github/olivergondza/saxeed/UpdatingVisitor.java +++ b/src/main/java/com/github/olivergondza/saxeed/UpdatingVisitor.java @@ -1,6 +1,7 @@ package com.github.olivergondza.saxeed; import com.github.olivergondza.saxeed.ex.FailedTransforming; +import com.github.olivergondza.saxeed.internal.CharChunk; /** * Visitor listening and modifying resulting stream. @@ -13,6 +14,9 @@ default void startDocument() throws FailedTransforming { default void startTag(Tag.Start tag) throws FailedTransforming { } + default void chars(Tag.Chars tag, CharChunk chars) { + } + default void endTag(Tag.End tag) throws FailedTransforming { } diff --git a/src/main/java/com/github/olivergondza/saxeed/internal/CharChunk.java b/src/main/java/com/github/olivergondza/saxeed/internal/CharChunk.java new file mode 100644 index 0000000..1cacd51 --- /dev/null +++ b/src/main/java/com/github/olivergondza/saxeed/internal/CharChunk.java @@ -0,0 +1,65 @@ +package com.github.olivergondza.saxeed.internal; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +public class CharChunk { + private char[] origData; + private int origStart; + private int origLength; + + /** + * Updated content. + */ + private String replacement; + + public CharChunk() { + } + + public void update(char[] charsData, int charsStart, int charsLength) { + origData = charsData; + origStart = charsStart; + origLength = charsLength; + replacement = null; + } + + public void update(String text) { + replacement = text; + origData = null; + origStart = -1; + origLength = -1; + } + + public void clear() { + update(null); + } + + public boolean isEmpty() { + return origData == null && replacement == null; + } + + public String get() { + if (replacement != null) { + return replacement; + } + + // cleared + if (origData == null) { + return null; + } + + // Construct the String iff some visitor really need a String instance. + // This is to prevent data copying/allocation that might not be needed. + replacement = new String(origData, origStart, origLength); + return replacement; + } + + /*package*/ void write(XMLStreamWriter writer) throws XMLStreamException { + // origData are erased when content is updated + if (origData != null) { + writer.writeCharacters(origData, origStart, origLength); + } else { + writer.writeCharacters(replacement); + } + } +} diff --git a/src/main/java/com/github/olivergondza/saxeed/internal/Element.java b/src/main/java/com/github/olivergondza/saxeed/internal/Element.java new file mode 100644 index 0000000..28ba1c9 --- /dev/null +++ b/src/main/java/com/github/olivergondza/saxeed/internal/Element.java @@ -0,0 +1,29 @@ +package com.github.olivergondza.saxeed.internal; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +/** + * Element introduced by visitor to be added to the output document. + */ +public interface Element { + /** + * Element that can write itself to XMLStreamWriter. + */ + interface SelfWriting extends Element { + void write(XMLStreamWriter writer) throws XMLStreamException; + } + + final class TextString implements SelfWriting { + private final String text; + + public TextString(String text) { + this.text = text; + } + + @Override + public void write(XMLStreamWriter writer) throws XMLStreamException { + writer.writeCharacters(text); + } + } +} diff --git a/src/main/java/com/github/olivergondza/saxeed/internal/TagImpl.java b/src/main/java/com/github/olivergondza/saxeed/internal/TagImpl.java index dbbc41d..4b3a484 100644 --- a/src/main/java/com/github/olivergondza/saxeed/internal/TagImpl.java +++ b/src/main/java/com/github/olivergondza/saxeed/internal/TagImpl.java @@ -17,7 +17,7 @@ * provide a compile-time guarantee that operations used can legally be performed at given time. For example, when * closing tag, method modifying attributes will not be available because they are already written. */ -/*package*/ class TagImpl implements Tag, Tag.Start, Tag.End { +/*package*/ class TagImpl implements Element, Tag, Tag.Start, Tag.Chars, Tag.End { private /*almost final*/ TagImpl parent; @@ -44,7 +44,7 @@ /** * List of children to be added. */ - private final List childrenToAdd = new ArrayList<>(); + private final List childElements = new ArrayList<>(); /** * Element that current element should be surrounded with. @@ -133,10 +133,14 @@ public Tag getAncestor(String name) { @Override public TagImpl addChild(String name) { TagImpl child = new TagImpl(this, name); - childrenToAdd.add(child); + childElements.add(child); return child; } + public void addText(String text) { + childElements.add(new Element.TextString(text)); + } + @Override public TagImpl wrapWith(String name) { this.wrapWith = new TagImpl(parent, name); @@ -180,8 +184,13 @@ public String removeAttribute(String attr) { return getAttributes().remove(attr); } - /*package*/ List getTagsAdded() { - return childrenToAdd; + /** + * Elements that visitors decided to add. + */ + /*package*/ List consumeChildren() { + List out = new ArrayList<>(childElements); + childElements.clear(); + return out; } // The hierarchy of tag parents needs to be fixed as we have injected a new one diff --git a/src/main/java/com/github/olivergondza/saxeed/internal/TransformationHandler.java b/src/main/java/com/github/olivergondza/saxeed/internal/TransformationHandler.java index 28cb57c..f3fbbb2 100644 --- a/src/main/java/com/github/olivergondza/saxeed/internal/TransformationHandler.java +++ b/src/main/java/com/github/olivergondza/saxeed/internal/TransformationHandler.java @@ -1,7 +1,6 @@ package com.github.olivergondza.saxeed.internal; import com.github.olivergondza.saxeed.Subscribed; -import com.github.olivergondza.saxeed.Tag; import com.github.olivergondza.saxeed.UpdatingVisitor; import com.github.olivergondza.saxeed.ex.FailedTransforming; import com.github.olivergondza.saxeed.ex.FailedWriting; @@ -37,7 +36,9 @@ public class TransformationHandler extends DefaultHandler implements AutoCloseab private final XMLStreamWriter writer; // A resource to close once done. Can be null private final AutoCloseable closeAction; + private TagImpl currentTag; + private final CharChunk currentChars = new CharChunk(); public TransformationHandler( LinkedHashMap visitors, @@ -71,9 +72,10 @@ private void _startElement(TagImpl tag) { TagImpl wrapper = tag.startWrapWith(); if (wrapper != null) { - if (!(wrapper.getTagsAdded().isEmpty())) { + List children = wrapper.consumeChildren(); + if (!(children.isEmpty())) { throw new AssertionError( - "Writing sub-elements is not supported for suround with elements: " + wrapper.getTagsAdded() + "Writing sub-elements is not supported for surround with elements: " + children ); } @@ -89,8 +91,7 @@ private void _startElement(TagImpl tag) { } LOGGER.fine(">"); - writeTagsRecursively(tag.getTagsAdded()); - tag.getTagsAdded().clear(); + writeChildren(tag); } catch (XMLStreamException e) { throw new FailedWriting(ERROR_WRITING_TO_OUTPUT_FILE, e); } @@ -118,24 +119,35 @@ private List getVisitors(String tagName) { /** * Write now tags to output stream. - * + *

* This is implemented through call XUnitFixer's handler methods, so Fixup impls are aware of newly added tags. */ - private void writeTagsRecursively(List tagsAdded) { - if (tagsAdded.isEmpty()) return; + private boolean writeChildren(TagImpl tag) { + List childElements = tag.consumeChildren(); + if (childElements.isEmpty()) return false; TagImpl oldCurrentTag = currentTag; - for (TagImpl tag: tagsAdded) { - - currentTag = tag; - _startElement(currentTag); - - for (TagImpl child: currentTag.getTagsAdded()) { - writeTagsRecursively(List.of(child)); + for (Element elements: childElements) { + + if (elements instanceof TagImpl) { + currentTag = (TagImpl) elements; + _startElement(currentTag); + + writeChildren(currentTag); + endElement(null, null, currentTag.getName()); + } else if (elements instanceof Element.SelfWriting) { + Element.SelfWriting sw = (Element.SelfWriting) elements; + try { + sw.write(writer); + } catch(XMLStreamException ex) { + throw new FailedWriting(ERROR_WRITING_TO_OUTPUT_FILE, ex); + } + } else { + throw new AssertionError("Unknown Element implementation found: " + elements.getClass()); } - endElement(null, null, currentTag.getName()); } currentTag = oldCurrentTag; + return true; } @Override @@ -156,8 +168,7 @@ public void endElement(String uri, String localName, String tagname) { visitors.get(i).endTag(tag); } - writeTagsRecursively(tag.getTagsAdded()); - tag.getTagsAdded().clear(); + writeChildren(tag); try { LOGGER.fine(""); @@ -176,14 +187,30 @@ public void endElement(String uri, String localName, String tagname) { } @Override - public void characters(char[] ch, int start, int length) { + public void characters(char[] orig, int start, int length) { TagImpl tag = currentTag; if (tag != null && !tag.isCharactersOmitted()) { try { - writer.writeCharacters(ch, start, length); + currentChars.update(orig, start, length); + for (UpdatingVisitor visitor : getVisitors(tag.getName())) { + visitor.chars(tag, currentChars); + } + + boolean written = writeChildren(tag); + if (!currentChars.isEmpty()) { + if (written) { + throw new IllegalStateException( + "Unable to write characters and children at the same time. " + + "Make sure to call CharChunk#clear() when elements added in UpdatingVisitor#chars()" + ); + } + currentChars.write(writer); + } } catch (XMLStreamException e) { throw new FailedWriting(ERROR_WRITING_TO_OUTPUT_FILE, e); + } finally { + currentChars.clear(); } } } diff --git a/src/test/java/com/github/olivergondza/saxeed/AddTextTest.java b/src/test/java/com/github/olivergondza/saxeed/AddTextTest.java new file mode 100644 index 0000000..afac15d --- /dev/null +++ b/src/test/java/com/github/olivergondza/saxeed/AddTextTest.java @@ -0,0 +1,76 @@ +package com.github.olivergondza.saxeed; + +import com.github.olivergondza.saxeed.ex.FailedTransforming; +import com.github.olivergondza.saxeed.internal.CharChunk; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class AddTextTest { + @Test + void inside() { + UpdatingVisitor elementAdder = new UpdatingVisitor() { + @Override + public void startTag(Tag.Start tag) throws FailedTransforming { + tag.addText("Beginning"); + tag.addChild("b"); + } + + @Override + public void endTag(Tag.End tag) throws FailedTransforming { + tag.addChild("e"); + tag.addText("End"); + } + }; + + assertEquals( + "BeginningEnd", + Util.transform("", elementAdder, "r") + ); + } + + @Test + void nested() { + UpdatingVisitor elementAdder = new UpdatingVisitor() { + @Override + public void startTag(Tag.Start tag) throws FailedTransforming { + Tag.Start ch = tag.addChild("s"); + ch.addText("Nested"); + ch.addChild("n").addText("este"); + ch.addText("d"); + } + + @Override + public void endTag(Tag.End tag) throws FailedTransforming { + tag.addChild("e").addChild("e").addText("N"); + } + }; + + assertEquals( + "NestedestedN", + Util.transform("", elementAdder, "r") + ); + } + + @Test + void charSplitting() { + UpdatingVisitor bold = new UpdatingVisitor() { + + @Override + public void chars(Tag.Chars tag, CharChunk chars) { + String text = chars.get(); + chars.clear(); + + for (String chunk : text.split(" ")) { + tag.addChild("b").addText(chunk); + tag.addText("-"); + } + } + }; + + assertEquals( + "replace-with-text-and-elements-", + Util.transform("replace with text and elements", bold, "r") + ); + } +} diff --git a/src/test/java/com/github/olivergondza/saxeed/CharactersTest.java b/src/test/java/com/github/olivergondza/saxeed/CharactersTest.java new file mode 100644 index 0000000..3f4ecd8 --- /dev/null +++ b/src/test/java/com/github/olivergondza/saxeed/CharactersTest.java @@ -0,0 +1,121 @@ +package com.github.olivergondza.saxeed; + +import com.github.olivergondza.saxeed.ex.FailedTransforming; +import com.github.olivergondza.saxeed.internal.CharChunk; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CharactersTest { + @Test + void update() { + UpdatingVisitor capitalize = new UpdatingVisitor() { + @Override + public void chars(Tag.Chars tag, CharChunk chars) { + if (tag.isNamed("r")) { + chars.update(chars.get().toUpperCase()); + } + } + }; + + assertEquals( + "FOObarBAX", + Util.transform("foobarbax", capitalize, "r", "n") + ); + } + + @Test + void erase() { + UpdatingVisitor eraser = new UpdatingVisitor() { + @Override + public void chars(Tag.Chars tag, CharChunk currentChars) { + if (tag.isNamed("r")) { + currentChars.clear(); + } + } + }; + + assertEquals( + "bar", + Util.transform("foobarbax", eraser, "r", "n") + ); + } + + @Test + void chunked() throws IOException { + List out = new ArrayList<>(); + UpdatingVisitor chars = new UpdatingVisitor() { + @Override + public void chars(Tag.Chars tag, CharChunk currentChars) { + out.add(currentChars.get()); + } + }; + + String input = Files.readString(Path.of("src/test/resources/xml/valid/long_body.xml")); + Util.transform(input, chars, "root"); + assertTrue(out.size() > 10, "The large text content was broken to parts"); + + assertEquals(input, "" + String.join("", out) + "\n"); + } + + @Test + void writeChars() { + UpdatingVisitor eraser = new UpdatingVisitor() { + @Override + public void chars(Tag.Chars tag, CharChunk currentChars) { + assertEquals("input", currentChars.get()); + } + + @Override + public void startTag(Tag.Start tag) throws FailedTransforming { + tag.addText("Starting! "); + } + + @Override + public void endTag(Tag.End tag) throws FailedTransforming { + tag.addText(" Ending!"); + } + }; + + assertEquals( + "Starting! input Ending!", + Util.transform("input", eraser, "r") + ); + } + + @Test + void repeatedTransform() { + class Appender implements UpdatingVisitor { + private final String content; + + public Appender(String content) { + this.content = content; + } + + @Override + public void chars(Tag.Chars tag, CharChunk currentChars) { + currentChars.update(currentChars.get() + content); + } + } + + TransformationBuilder tb = new TransformationBuilder() + .add("r", new Appender(" will")) + .add("r", new Appender(" be")) + .add("r", new Appender(" amended")) + .add("r", new Appender(" with")) + .add("r", new Appender(" this")) + ; + + assertEquals( + "Input will be amended with this", + Util.transform("Input", tb) + ); + } +} diff --git a/src/test/java/com/github/olivergondza/saxeed/SaxeedTest.java b/src/test/java/com/github/olivergondza/saxeed/SaxeedTest.java index dd55363..532193e 100644 --- a/src/test/java/com/github/olivergondza/saxeed/SaxeedTest.java +++ b/src/test/java/com/github/olivergondza/saxeed/SaxeedTest.java @@ -72,7 +72,7 @@ public void startTag(Tag.Start tag) { @Test void processingInstructionWritten() { String same = ""; - assertEquals(same, transform( + assertEquals(same, Util.transform( same, (ts) -> {}, "a" @@ -82,7 +82,7 @@ void processingInstructionWritten() { @Test void entity() { String same = "<&>"; - assertEquals(same, transform( + assertEquals(same, Util.transform( same, (ts) -> {}, "r" @@ -92,7 +92,7 @@ void entity() { @Test void whitespace() { String same = " \t\t\n\n"; - assertEquals(same, transform( + assertEquals(same, Util.transform( same, (ts) -> {}, "r" @@ -101,7 +101,7 @@ void whitespace() { @Test void cdata() { - assertEquals("Some\tText&Here", transform( + assertEquals("Some\tText&Here", Util.transform( "", (ts) -> {}, "r" @@ -110,19 +110,19 @@ void cdata() { @Test void skip() { - assertEquals("", transform( + assertEquals("", Util.transform( "skip", Tag.Start::skip, "root" )); - assertEquals("keepkeep", transform( + assertEquals("keepkeep", Util.transform( "keepskipskipskipskipkeep", Tag.Start::skip, "skip" )); - assertEquals("", transform( + assertEquals("", Util.transform( "", Tag.Start::skip, "skip" @@ -131,7 +131,7 @@ void skip() { @Test void empty() { - String actual = transform( + String actual = Util.transform( "keep1skipskipkeepkeep", Tag.Start::empty, "empty" @@ -142,7 +142,7 @@ void empty() { @Test void unwrap() { - String actual = transform( + String actual = Util.transform( "keepkeepkeepkeep", Tag.Start::unwrap, "unwrap" @@ -153,7 +153,7 @@ void unwrap() { @Test void attributes() { - String actual = transform( + String actual = Util.transform( "", ts -> { ts.removeAttribute("no_such_attr"); @@ -177,17 +177,17 @@ void wrap() { }; assertEquals( "", - transform("", wrap, "a") + Util.transform("", wrap, "a") ); assertEquals( "", - transform("", wrap, "a") + Util.transform("", wrap, "a") ); assertEquals( "", - transform("", wrap, "a") + Util.transform("", wrap, "a") ); } @@ -244,7 +244,7 @@ public void endTag(Tag.End tag) throws FailedTransforming { assertEquals( "", - transform("", addch, "r") + Util.transform("", addch, "r") ); } @@ -277,7 +277,7 @@ public void startTag(Tag.Start tag) throws FailedTransforming { }; try { - transform("", uv, "r"); + Util.transform("", uv, "r"); fail(); } catch (AssertionError ex) { assertEquals( @@ -286,27 +286,4 @@ public void startTag(Tag.Start tag) throws FailedTransforming { ); } } - - String transform(String input, Consumer lambda, String... on) { - UpdatingVisitor visitor = new UpdatingVisitor() { - @Override - public void startTag(Tag.Start tag) throws FailedTransforming { - lambda.accept(tag); - } - }; - - return transform(input, visitor, on); - } - - private static String transform(String input, UpdatingVisitor visitor, String... on) { - TransformationBuilder tb = new TransformationBuilder(); - tb.add(Subscribed.to(on), visitor); - - Saxeed saxeed = new Saxeed().setInputString(input); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - saxeed.addTransformation(tb, baos); - saxeed.transform(); - - return baos.toString(); - } } diff --git a/src/test/java/com/github/olivergondza/saxeed/Util.java b/src/test/java/com/github/olivergondza/saxeed/Util.java new file mode 100644 index 0000000..4aac651 --- /dev/null +++ b/src/test/java/com/github/olivergondza/saxeed/Util.java @@ -0,0 +1,35 @@ +package com.github.olivergondza.saxeed; + +import com.github.olivergondza.saxeed.ex.FailedTransforming; + +import java.io.ByteArrayOutputStream; +import java.util.function.Consumer; + +public class Util { + static String transform(String input, Consumer lambda, String... on) { + UpdatingVisitor visitor = new UpdatingVisitor() { + @Override + public void startTag(Tag.Start tag) throws FailedTransforming { + lambda.accept(tag); + } + }; + + return transform(input, visitor, on); + } + + static String transform(String input, UpdatingVisitor visitor, String... on) { + TransformationBuilder tb = new TransformationBuilder(); + tb.add(Subscribed.to(on), visitor); + + return transform(input, tb); + } + + static String transform(String input, TransformationBuilder tb) { + Saxeed saxeed = new Saxeed().setInputString(input); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + saxeed.addTransformation(tb, baos); + saxeed.transform(); + + return baos.toString(); + } +} diff --git a/src/test/resources/xml/valid/long_body.xml b/src/test/resources/xml/valid/long_body.xml new file mode 100644 index 0000000..7d820a6 --- /dev/null +++ b/src/test/resources/xml/valid/long_body.xml @@ -0,0 +1,321 @@ + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse consectetur libero in lorem finibus, lobortis + ullamcorper lorem accumsan. Nullam a tellus sollicitudin, interdum lorem non, fringilla nisl. Nunc eget justo eu dui + maximus dapibus. Duis non enim non sem facilisis cursus vel ac ex. Quisque tortor leo, tincidunt eget feugiat nec, + venenatis non elit. Maecenas nec velit sit amet dui elementum congue. Mauris tempor eros eu mattis laoreet. In + sollicitudin sem vitae sodales commodo. Mauris non arcu et nulla aliquam condimentum. Sed ut tortor varius, + venenatis justo a, sodales nunc. Quisque sit amet pretium dui. Etiam at odio magna. Curabitur quis porta ligula. + Praesent facilisis malesuada felis, sed vulputate nunc fringilla vel. + + Vestibulum lobortis ex sed sagittis sagittis. Phasellus pretium tortor elit, ac luctus arcu tempus non. In in eros + sit amet odio vulputate fermentum. Proin vitae nunc in mauris lacinia posuere porta a felis. Donec sit amet erat eu + ligula rutrum posuere. Mauris nec nisi nisi. Sed eros est, imperdiet in mollis nec, blandit eu metus. Suspendisse + sit amet enim ultricies, porta magna quis, faucibus mauris. Ut nibh nisl, commodo ut odio in, mollis vulputate + felis. Vivamus quis eros iaculis, lobortis sapien sit amet, mattis velit. Pellentesque habitant morbi tristique + senectus et netus et malesuada fames ac turpis egestas. Vivamus sodales blandit elit vel dignissim. + + Vivamus condimentum et metus quis elementum. Vivamus euismod nibh id neque dapibus porttitor. Mauris ligula metus, + porta at odio posuere, consectetur congue ligula. Suspendisse semper metus quis pulvinar hendrerit. Morbi feugiat + mauris viverra, consequat purus vitae, finibus elit. Orci varius natoque penatibus et magnis dis parturient montes, + nascetur ridiculus mus. Proin pulvinar congue tristique. In ut volutpat est, vitae dapibus sapien. Donec vitae + euismod mi. + + Donec malesuada nibh in porttitor lacinia. Aliquam et dignissim elit, non sollicitudin lorem. Maecenas feugiat + ultricies pulvinar. Etiam luctus id libero id eleifend. Quisque venenatis massa id porttitor ultrices. Sed eu + vehicula tellus. Curabitur blandit risus tempor libero ultrices, in volutpat neque consectetur. Aenean eu ex + molestie, dignissim enim at, egestas dui. Mauris luctus elit neque, non vestibulum metus lobortis ullamcorper. Sed + sed tincidunt augue, ut sollicitudin neque. Duis maximus lobortis tristique. + + Vivamus sodales rutrum maximus. Ut molestie ex nulla, at pulvinar ipsum euismod elementum. Sed condimentum eu diam + nec lobortis. Vestibulum iaculis massa ut diam dapibus, at sollicitudin dui aliquet. Praesent sit amet malesuada + libero, vel pulvinar massa. Suspendisse laoreet ultricies elit et consectetur. Aenean iaculis quam ac urna posuere + maximus. Mauris eleifend vel magna sollicitudin viverra. Aliquam ac ex molestie lorem facilisis convallis. + + Etiam cursus tempor nisl eget accumsan. Donec blandit magna eget pulvinar maximus. Donec id pulvinar erat. Quisque + lectus risus, aliquam sit amet consectetur facilisis, viverra at ante. Mauris convallis porttitor elit ac ultrices. + Aliquam dignissim varius mi eget consequat. In vitae erat quam. Nulla a lacus tristique, maximus lorem nec, + venenatis nulla. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aliquam + dictum nisl vitae dolor ullamcorper, tincidunt aliquet neque tincidunt. + + Sed at convallis enim. Etiam risus enim, blandit quis lorem et, sagittis imperdiet elit. Aliquam eu est et eros + suscipit vestibulum eget non nulla. Ut justo dui, varius rhoncus est vitae, sodales tincidunt sapien. Nulla + facilisi. Proin eget molestie augue, eu dapibus sapien. Cras pulvinar varius massa, sed suscipit magna consectetur + et. Sed tellus dui, scelerisque sit amet dignissim ut, pharetra sit amet turpis. + + Nam rhoncus maximus diam. Ut faucibus magna enim, sit amet tempus odio mollis sit amet. Proin a magna risus. Nunc + hendrerit augue in tempor tristique. Praesent eu dui accumsan diam placerat hendrerit. Aenean vitae nisl sed erat + egestas viverra. Vivamus nunc elit, faucibus quis lectus ut, volutpat rutrum est. Praesent et aliquam lectus. + Curabitur viverra leo urna, eu mollis metus elementum et. + + Nulla placerat aliquam turpis at mattis. Sed facilisis viverra massa, vitae ultrices justo malesuada at. Nullam + congue lectus commodo nulla ullamcorper, id tempor massa suscipit. In ex ligula, sodales sodales nisl sit amet, + bibendum dignissim urna. Phasellus non interdum dui, ut faucibus tellus. Fusce sodales, metus et placerat elementum, + nunc quam commodo nibh, eget accumsan felis risus quis purus. Mauris eu magna sed felis feugiat iaculis nec at + lectus. Cras tincidunt erat ut turpis tincidunt fringilla. Nullam dolor turpis, pretium non vulputate sit amet, + fermentum nec orci. Phasellus tortor quam, accumsan at viverra eget, vulputate in dui. Integer pellentesque enim + sapien, ac ultricies erat venenatis quis. Nam mollis fermentum quam, a vulputate lectus maximus at. Sed suscipit est + vitae elit consectetur, at viverra magna blandit. Proin nec scelerisque ipsum, non ultrices eros. Sed sit amet urna + lectus. + + Maecenas tempus dapibus malesuada. Phasellus eu blandit nisi. Suspendisse nec leo eleifend, tempus eros a, viverra + purus. Proin ex elit, commodo et sollicitudin a, convallis eget turpis. Curabitur euismod justo a massa vulputate + porttitor. Sed porta faucibus ornare. Donec viverra enim vel porta interdum. Nunc odio risus, consectetur quis sem + ut, pharetra placerat erat. Donec massa mauris, cursus eu mi at, placerat lobortis sapien. Nullam tempus orci rutrum + aliquam rhoncus. Etiam sit amet felis porttitor, condimentum elit venenatis, sollicitudin ante. Vestibulum suscipit + hendrerit nisl ut aliquet. Aliquam nec ex quis mauris molestie venenatis. + + Nam suscipit erat sit amet dolor sodales venenatis. Mauris finibus non lorem eu iaculis. Etiam egestas ipsum laoreet + odio luctus, et vehicula eros congue. Pellentesque dictum eros ex, in dignissim dolor vehicula gravida. Maecenas + volutpat at nisi sit amet porta. Morbi quis metus sollicitudin, accumsan felis id, gravida nibh. Proin vulputate in + ligula id porttitor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Lorem + ipsum dolor sit amet, consectetur adipiscing elit. Cras urna turpis, fringilla lobortis luctus pretium, aliquam non + eros. Phasellus vel tellus massa. Aliquam consequat lacinia nisl sed ultrices. Cras vehicula nulla et eleifend + scelerisque. + + Etiam ut varius tellus. Morbi non magna consequat, lobortis felis quis, porttitor lorem. Nullam vestibulum ac quam + non gravida. Donec porttitor, odio ac sollicitudin bibendum, mi diam aliquam purus, id facilisis nisl justo in + felis. Maecenas non dui vestibulum, semper tellus eu, porttitor ligula. Quisque lacinia metus enim, ac tristique + enim laoreet a. In tempor ante vitae sagittis volutpat. Quisque et diam id nisi ultrices faucibus in nec nisi. Sed + quis porta ligula. Fusce gravida est ligula, vitae ultrices lectus pulvinar non. Mauris pretium tincidunt sapien ut + fringilla. Proin id vehicula dolor. Pellentesque justo quam, accumsan ut scelerisque vitae, ornare non ex. Curabitur + vel egestas orci, vel congue nisi. Etiam ac libero sem. Sed accumsan eu lacus sit amet pharetra. + + Maecenas fermentum arcu at risus pellentesque, vel iaculis diam tincidunt. Suspendisse ut neque mauris. Cras + bibendum libero quis nisi hendrerit, id semper leo tincidunt. Vivamus vitae placerat neque, sit amet rutrum diam. + Integer rhoncus, est vel volutpat faucibus, mauris tellus suscipit massa, eu maximus tellus felis eget libero. + Praesent faucibus tellus eu scelerisque commodo. Nam semper metus et nisi rhoncus, molestie aliquam elit tristique. + Pellentesque cursus urna eget pellentesque consequat. Nullam bibendum dui a leo facilisis, at finibus tellus + lacinia. Nunc quis aliquam lacus, non varius nunc. Pellentesque dictum, lectus a malesuada malesuada, lacus augue + pretium libero, vitae sollicitudin turpis arcu eget sapien. Nunc et ultrices neque. + + Aliquam rutrum diam sit amet orci semper, sed bibendum nunc hendrerit. Aenean a ullamcorper tellus, ac congue enim. + Fusce facilisis tempor purus, et dapibus metus mattis vitae. Nunc tristique imperdiet eleifend. Donec pretium enim + sed augue dictum luctus. Fusce eleifend eros purus, eu consectetur magna pulvinar nec. Aenean ullamcorper feugiat + eros scelerisque consequat. + + Sed porttitor non orci sed iaculis. Nunc non sapien vulputate, iaculis lectus eget, cursus urna. Curabitur tincidunt + risus ut faucibus aliquet. Nulla sollicitudin congue maximus. Mauris a tincidunt nibh. Donec iaculis dignissim odio, + in placerat sem finibus et. Etiam a rutrum quam. Sed non purus dapibus arcu efficitur scelerisque ac eget nulla. Nam + sed risus ornare, mattis risus sed, condimentum ex. Aenean tincidunt facilisis orci a facilisis. + + Nullam turpis lacus, porta et metus fringilla, tristique tempor augue. Nulla facilisi. Aenean vestibulum, ipsum ac + malesuada feugiat, turpis diam vestibulum est, vel sollicitudin velit ex sed velit. Morbi dictum pretium velit, id + hendrerit quam eleifend sed. Quisque commodo purus sit amet iaculis mattis. Pellentesque at ullamcorper nisl. Donec + in turpis a ante porta molestie. Nulla nec nunc id mi laoreet tincidunt a vitae magna. Nulla facilisi. Proin cursus + nibh ac risus rhoncus vestibulum non non lectus. + + Donec ac tincidunt felis, at aliquet nibh. Sed vel pharetra libero, at blandit sapien. Pellentesque ac placerat + turpis, ut lacinia nisl. Nullam dignissim sem in nunc rutrum pulvinar. In hac habitasse platea dictumst. Nulla at ex + quam. Duis feugiat, ante id maximus volutpat, mi massa varius odio, ac ultrices eros velit id odio. Proin varius + neque et tincidunt pharetra. Duis gravida rhoncus dui. Integer placerat ultrices nisi a luctus. Morbi interdum, + dolor ac viverra sagittis, magna mi sodales dolor, vitae luctus nisl arcu vel sapien. Nullam porttitor sit amet quam + eget mollis. Etiam sed est tempus, facilisis eros vel, imperdiet metus. Nulla at eros ut risus consectetur + sollicitudin eu ut magna. Donec ac tempus diam. + + Etiam et ex risus. Sed ut nisl vitae purus aliquet molestie. Nullam ut accumsan ipsum. Vestibulum nec est nec velit + varius ullamcorper. Proin suscipit eleifend nunc sit amet blandit. Interdum et malesuada fames ac ante ipsum primis + in faucibus. Nullam congue turpis eget eros iaculis, at sodales ligula dapibus. Aliquam consequat enim et volutpat + aliquam. + + Ut dapibus ornare tortor, vitae faucibus justo pellentesque sit amet. Donec vulputate mauris sit amet enim convallis + commodo in eu tortor. Aliquam sapien nunc, elementum vel pulvinar ut, ultrices nec felis. Sed vitae purus porta, + bibendum enim ut, aliquam nulla. Cras consequat suscipit est, non gravida ipsum fermentum dapibus. Ut eu lectus + nunc. Aliquam efficitur vehicula nisi at volutpat. Quisque sodales vulputate purus. Donec tristique nisl tempor + lorem tincidunt, eget tincidunt lorem laoreet. Orci varius natoque penatibus et magnis dis parturient montes, + nascetur ridiculus mus. Etiam molestie quam vitae leo finibus sagittis. Nam nec quam in dolor aliquam malesuada eu + ut turpis. In lorem turpis, accumsan quis augue sodales, porta euismod felis. In ac sodales ipsum. + + Maecenas ultricies ornare lacinia. Vivamus egestas auctor metus, ac accumsan risus venenatis id. Phasellus volutpat + mi vel felis malesuada, a faucibus felis convallis. Aenean tempor nisi maximus laoreet hendrerit. Pellentesque + consequat in sem ac sollicitudin. Nam et felis consequat, rhoncus dui eu, bibendum arcu. Donec purus nisl, lobortis + sed tempus in, pellentesque non nibh. Nam quis nisl sed metus aliquam ultrices ac vel libero. Nam sodales et lectus + non posuere. Aliquam vitae dictum urna. Maecenas arcu tellus, sodales id nulla eu, bibendum blandit nisi. Praesent + varius et mi quis congue. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. + Nullam aliquet risus id sagittis eleifend. + + Maecenas sit amet felis eget nibh dapibus sagittis quis at dui. In sit amet mauris sed turpis semper convallis ac + volutpat nunc. Phasellus sit amet orci consequat, tincidunt justo sed, imperdiet lectus. Praesent lectus nisl, + molestie efficitur efficitur eget, lacinia at ligula. Pellentesque laoreet neque nec gravida interdum. Vivamus + maximus convallis tincidunt. Sed accumsan congue ante, vel feugiat purus lobortis quis. Nullam augue est, congue in + aliquet sed, condimentum in ligula. Vivamus eget ex ut ipsum sagittis mattis sed non tortor. Etiam cursus vestibulum + tortor, nec facilisis ligula. Vestibulum venenatis nunc sed neque euismod ornare vel vitae enim. + + Cras quis est eget leo luctus venenatis sit amet a purus. Praesent quis egestas augue, eu iaculis est. Integer + dictum eu dui a malesuada. Pellentesque lorem tortor, euismod et lobortis sit amet, sollicitudin faucibus sapien. + Etiam vel justo aliquam, aliquam dui eu, ullamcorper mi. Morbi rhoncus vestibulum elit. Vivamus pulvinar lorem vel + tortor tincidunt ullamcorper sed a eros. + + Vivamus blandit eros arcu, at hendrerit neque tristique nec. Nulla dictum sem non quam volutpat tempor. Donec + finibus mauris et lectus pharetra venenatis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur + ridiculus mus. Fusce non risus id nunc feugiat fringilla eu quis libero. Nullam eget velit sem. Sed mollis libero + nec molestie elementum. + + Aenean feugiat leo eget ipsum imperdiet, id egestas tortor finibus. Proin tristique a mi id dapibus. Mauris non + mollis nibh. Sed ac eros aliquet, malesuada turpis eu, sodales purus. Fusce nulla ex, iaculis at lectus in, + facilisis rutrum neque. Curabitur elementum massa non mi rhoncus placerat. Cras tempor mi et efficitur fermentum. + Integer tempor sed lorem in iaculis. Donec consequat ornare blandit. Vestibulum at dolor sem. Quisque nibh dolor, + lobortis id hendrerit in, convallis sit amet libero. Sed aliquam dignissim pulvinar. + + Morbi vulputate scelerisque felis eget hendrerit. Proin scelerisque, eros in vulputate viverra, lacus nibh tempor + diam, at suscipit erat orci vitae tellus. Maecenas venenatis at lectus molestie tristique. Etiam massa orci, + pharetra eget elementum vel, finibus ut ex. Mauris auctor varius justo lacinia ornare. In tincidunt nunc eu + sollicitudin egestas. Duis pellentesque leo sit amet elit efficitur hendrerit. Sed ac facilisis ex. Vivamus + efficitur eu tortor eget laoreet. + + Duis faucibus felis eget velit bibendum, ut dignissim nunc vestibulum. Fusce non faucibus felis. Pellentesque eu + elit quis dolor mollis blandit vitae vitae quam. Nunc ac fermentum sapien. In lobortis tortor sed mi sagittis, id + iaculis eros tincidunt. Fusce malesuada, mi eget fringilla sollicitudin, ligula elit eleifend est, et venenatis est + metus nec tellus. In nec nunc velit. Sed cursus efficitur dictum. Donec vestibulum molestie elit, non congue risus + sollicitudin ac. Duis lacinia nulla non orci auctor, id facilisis elit dictum. Duis ante neque, gravida vel aliquam + nec, sodales at nisi. Nam gravida elit lacinia ligula viverra, sed tempor nulla ullamcorper. Suspendisse potenti. + Morbi iaculis felis blandit justo sollicitudin, vitae volutpat purus faucibus. Aliquam quis consectetur enim. Etiam + lacinia, ligula non sagittis aliquet, ante nisi interdum mauris, ac euismod est justo eu magna. + + Pellentesque ut cursus metus, eu euismod est. Sed quis enim tincidunt, feugiat ipsum ut, euismod libero. In a magna + non purus fermentum ornare et in libero. Suspendisse in sem sit amet augue fermentum mattis at a massa. Orci varius + natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam placerat elit lacus, eget pretium + justo hendrerit ut. Nunc pulvinar, nunc non placerat suscipit, quam augue bibendum ante, at pulvinar elit turpis sit + amet lacus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Fusce lacinia + purus risus, interdum molestie neque tincidunt eu. Pellentesque tristique dictum mi, eu vestibulum quam sodales sed. + Proin rutrum, mauris ac iaculis commodo, lacus urna iaculis ex, quis fringilla enim felis nec ante. + + Integer volutpat nisi nec elementum dictum. Pellentesque convallis feugiat suscipit. Integer at velit scelerisque, + maximus magna nec, accumsan elit. Nullam porttitor enim ac orci ultrices mattis. Mauris pretium nisi eu diam dictum + placerat. Nam sed nunc quis nulla porttitor posuere id sed nisl. Donec posuere, enim vitae elementum ultrices, + tortor magna luctus risus, id pulvinar est quam non dolor. + + Ut a dolor interdum, fringilla nisl eu, porttitor nunc. Quisque laoreet massa ut magna laoreet, a elementum diam + blandit. Suspendisse at ipsum nec dolor laoreet auctor. Sed fringilla, eros ut venenatis tincidunt, purus arcu + aliquam enim, vitae facilisis diam neque congue felis. Suspendisse at aliquam turpis, non aliquam urna. Phasellus + pharetra eros eget consequat iaculis. Aliquam erat volutpat. Nullam id magna varius diam aliquet ornare et sit amet + enim. Vestibulum id fringilla lacus. + + Cras id interdum dolor, sit amet imperdiet dui. Maecenas nisi sapien, mattis at turpis id, feugiat imperdiet augue. + Duis quis ante at ex aliquet cursus eget sed nunc. Proin bibendum nunc et odio fermentum eleifend. Vestibulum tortor + velit, pulvinar in commodo ut, pretium mattis neque. Sed nibh tortor, eleifend quis dignissim quis, vulputate sed + ligula. Nam sit amet ipsum semper, porta magna vel, imperdiet quam. Cras condimentum, massa vulputate pulvinar + aliquam, dui sem cursus arcu, sit amet aliquet risus sapien non neque. Morbi sed ultricies ex. Donec lobortis vel + nibh non volutpat. Aenean tristique sapien nec nulla elementum faucibus. Nullam vehicula magna sit amet consectetur + gravida. Donec consequat sit amet arcu id sollicitudin. + + Morbi sit amet turpis luctus, interdum nisi eu, feugiat augue. In diam arcu, eleifend a massa et, imperdiet + dignissim odio. Etiam tempor orci gravida laoreet faucibus. Phasellus nec purus dapibus, maximus leo et, convallis + lectus. Integer non dapibus lorem, at iaculis ipsum. Nunc libero nisl, hendrerit at ante a, euismod imperdiet augue. + Nam a sem ac turpis pellentesque eleifend. Maecenas feugiat cursus velit sed dapibus. Pellentesque tristique + faucibus ipsum ut pellentesque. Quisque volutpat ultricies leo dapibus commodo. + + Vivamus ut facilisis arcu. Duis hendrerit fringilla dolor nec porttitor. Donec venenatis vel odio non pharetra. + Praesent in mollis purus. Duis in odio efficitur, sollicitudin mauris et, semper nibh. Proin ornare finibus ex, quis + aliquet velit fringilla sit amet. Nam ut lectus quis lectus tempor porta vitae at massa. Aenean vitae vehicula + lorem. Praesent porttitor enim eu egestas posuere. Vestibulum scelerisque efficitur congue. Mauris in mollis lectus. + Aenean at laoreet ipsum, id rhoncus sapien. + + Vivamus sed facilisis nibh. Donec quam risus, condimentum id orci in, porta gravida est. Mauris nec ultricies sem, + vitae bibendum neque. Etiam blandit ornare ipsum, eget iaculis nulla bibendum ac. Etiam lobortis elit at metus + consectetur sollicitudin. Praesent quam quam, sollicitudin in enim vel, imperdiet varius risus. Mauris egestas dui + neque, vel condimentum dolor tempor quis. Suspendisse efficitur dignissim ipsum. Sed efficitur aliquet lectus quis + lobortis. Donec maximus sapien a efficitur consequat. Pellentesque elit lectus, finibus ac orci vel, rhoncus + vehicula lorem. Vivamus vehicula malesuada turpis, eget ultricies mauris rhoncus non. + + Phasellus et ultrices lorem. Pellentesque egestas elit sit amet quam molestie, id dignissim mauris porta. Praesent + in ligula urna. Etiam tellus risus, fermentum ut pretium eget, volutpat quis arcu. Etiam a ultrices sem. Etiam non + felis pellentesque, condimentum ante ut, mattis metus. Nulla ut maximus justo. Mauris ultrices tincidunt magna et + tincidunt. Cras vitae justo in mauris ullamcorper tincidunt. Aenean molestie erat mi, id sodales purus posuere sed. + + Praesent vehicula rhoncus quam, eu consectetur neque fermentum at. Suspendisse libero erat, rhoncus non erat at, + convallis iaculis magna. Proin hendrerit, purus et fermentum interdum, lectus quam aliquet dolor, vitae faucibus + risus felis ac dui. Sed bibendum mattis nisl, et blandit quam pellentesque et. Proin ultrices volutpat justo, a + dapibus quam tincidunt sit amet. Ut dictum risus vitae est faucibus fringilla. Etiam tempor, nisi at finibus + gravida, eros nunc bibendum eros, nec feugiat velit ipsum at nibh. Curabitur euismod semper ipsum id tristique. + Pellentesque quis facilisis felis. Pellentesque arcu tortor, placerat eget leo id, lacinia laoreet dui. + + Sed vehicula, arcu eget commodo scelerisque, turpis urna scelerisque sem, ac sollicitudin nisi dui vitae nulla. + Curabitur eget venenatis massa. Ut eu massa diam. Fusce tincidunt iaculis quam vitae luctus. Sed eget justo + vestibulum, convallis mi a, ullamcorper libero. Suspendisse ut est id sem volutpat laoreet eu quis quam. Sed + ultrices odio velit. Donec fermentum fringilla vehicula. Nunc in purus id tortor sagittis tempor ut quis urna. + Aenean in nunc vitae nibh posuere molestie. + + Nulla finibus non velit gravida rutrum. Ut consectetur tempor dui, a condimentum ligula rutrum et. Maecenas auctor + ex ac mi interdum, at condimentum nisl molestie. In scelerisque nunc a leo aliquet, vel tristique urna dignissim. + Suspendisse potenti. Cras venenatis porttitor nisi, at lobortis lacus dignissim id. Pellentesque at enim eu dolor + mattis venenatis quis non mi. Duis interdum massa at sapien tempus, in maximus massa ornare. Proin sed lacus sed + erat accumsan efficitur. In hac habitasse platea dictumst. Aenean elit augue, vehicula consequat odio eget, + ullamcorper eleifend lacus. Quisque sit amet nibh fringilla, vestibulum enim nec, ullamcorper dolor. Vestibulum + eleifend fermentum mi at feugiat. + + Ut ultrices sapien non ante ornare, et aliquet dolor posuere. Pellentesque volutpat, ipsum sed egestas tristique, + orci eros elementum purus, id pretium purus erat et est. Duis ut diam eros. Suspendisse sit amet congue tortor. + Pellentesque bibendum auctor odio in egestas. Donec convallis justo ligula, in semper arcu commodo nec. Phasellus + feugiat eleifend viverra. Etiam eu arcu ac libero tincidunt mollis. Maecenas volutpat ultricies sollicitudin. + Aliquam nisi odio, tincidunt ut enim et, ornare lacinia est. Donec molestie interdum velit, at laoreet nisi. + Praesent ex lacus, dapibus vitae tellus et, mollis ornare leo. + + Cras iaculis, mauris quis rhoncus pretium, magna tellus tempor massa, at porta lectus enim quis nisi. Donec sed + felis enim. Nulla tincidunt odio vulputate justo accumsan, quis volutpat nibh finibus. Cras varius augue at orci + interdum congue. Nulla vestibulum ut justo eu ultricies. Aliquam at diam ac ex tempor varius at at nisl. Nulla + tempus molestie scelerisque. + + Mauris sit amet elit consequat, mollis ipsum non, placerat purus. Sed congue cursus tortor vitae finibus. Ut + lobortis eleifend semper. Nullam dapibus egestas vulputate. Nunc interdum est vel diam placerat sodales. Donec ac + gravida justo. Nam faucibus, nibh eget dapibus placerat, velit augue faucibus leo, sed suscipit risus nisl eget + massa. Nunc bibendum nec nunc nec sagittis. + + Phasellus tristique massa tortor, id hendrerit nulla commodo sit amet. Ut placerat enim id lorem consectetur, eget + iaculis leo suscipit. Curabitur venenatis, felis ac finibus malesuada, magna massa accumsan tellus, vel pretium + metus urna sit amet ex. Curabitur blandit urna sed finibus aliquet. Nam interdum lectus quis ex volutpat, accumsan + rutrum orci molestie. Pellentesque interdum eleifend dolor non vulputate. Nullam fermentum lectus vitae rutrum + lobortis. Morbi ac nulla sit amet lorem pulvinar eleifend. Donec placerat interdum nisi, nec mattis nisl lacinia + vel. + + Integer vitae venenatis elit. Fusce a leo quis orci ultricies malesuada. Vivamus tempor commodo est. Aliquam gravida + ipsum sed vehicula ultricies. Aliquam ac placerat turpis, vitae egestas diam. Quisque vehicula iaculis odio. + Maecenas ex ipsum, egestas quis viverra sed, pellentesque ac est. Curabitur mattis ex eget aliquam elementum. Nam ex + nisi, lacinia quis lectus in, semper feugiat risus. Ut fermentum dictum consectetur. + + Etiam nec velit placerat turpis viverra ultrices. Sed laoreet maximus diam. Nunc arcu neque, volutpat vitae ornare + cursus, consequat sit amet ipsum. Pellentesque ultricies dignissim mattis. Suspendisse condimentum nisl vel mauris + malesuada rutrum. Nulla rutrum quam eget quam porta tristique. Aliquam et aliquet ante. Integer eu varius tellus, at + suscipit erat. Quisque egestas iaculis turpis, in dignissim arcu dignissim et. Vestibulum ante ipsum primis in + faucibus orci luctus et ultrices posuere cubilia curae; Integer quis lacinia diam, eget scelerisque nibh. Nam + malesuada interdum ornare. + + Integer consectetur eu lectus ac semper. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere + cubilia curae; Etiam venenatis orci quis tristique bibendum. In eu lectus bibendum, pharetra elit in, consectetur + lacus. Aenean id commodo neque. Morbi sodales lacus nec ipsum condimentum laoreet. Quisque condimentum, libero eget + hendrerit pulvinar, nunc mauris convallis turpis, et consequat ante lacus eu magna. Mauris sed felis aliquam, tempus + lectus in, tempus purus. + + Morbi porttitor eu lacus sit amet porta. Etiam faucibus consequat ligula nec faucibus. Nulla lobortis tellus sem, + quis condimentum ante commodo vel. Sed nec dignissim metus. Suspendisse non arcu leo. Nam vulputate augue at lorem + consequat, ut ultrices velit maximus. Quisque nec accumsan justo. + + Ut volutpat vulputate ullamcorper. Morbi interdum urna sed tellus porta fringilla. Aliquam eget turpis efficitur + eros malesuada fermentum. Mauris a volutpat nisl. In mi lorem, pharetra eu nulla et, porta consequat erat. Donec + vulputate non odio mollis porta. Phasellus tempor vitae nisi eget dignissim. Nullam tempor nunc sit amet urna mattis + consequat. + + Praesent hendrerit varius sollicitudin. In et tristique justo, at luctus sem. Donec eu tortor eget magna blandit + iaculis id et quam. Morbi a nibh et ante rutrum vestibulum eget nec ligula. Pellentesque consectetur mi non sem + fermentum elementum. Quisque a ante eu dolor consequat blandit eget non dui. Interdum et malesuada fames ac ante + ipsum primis in faucibus. Aliquam erat volutpat. Morbi sed nunc venenatis, gravida neque porta, varius dui. + Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. + + Maecenas quis aliquet justo, vitae rutrum leo. Class aptent taciti sociosqu ad litora torquent per conubia nostra, + per inceptos himenaeos. Morbi nec mauris orci. Suspendisse quis fermentum augue, vel accumsan metus. Quisque ut + aliquet arcu. Aenean sollicitudin, ex sed dictum finibus, est ligula porttitor eros, nec consectetur massa dolor et + dolor. Vivamus faucibus sed ipsum sit amet lacinia. Integer nibh nisi, mollis ut quam eu, rutrum ullamcorper sem. + Donec hendrerit est nulla, eget placerat ante lacinia vitae. Nam ac purus vulputate, ultrices erat molestie, + eleifend ipsum. Praesent eu commodo tellus. Praesent tincidunt nibh ante, ut convallis elit semper eu. + + Pellentesque placerat ligula est, nec ullamcorper justo suscipit commodo. Mauris ornare felis sit amet mauris + lobortis aliquet. Suspendisse ut felis rhoncus, blandit tellus vel, elementum nunc. Mauris ac ipsum neque. Vivamus + sodales placerat feugiat. Morbi ultrices, nibh id scelerisque dictum, nunc lacus accumsan neque, sed semper elit + odio et mi. Donec congue quam eget neque venenatis finibus. Nullam at mauris sit amet felis viverra vehicula congue + non neque. Vivamus bibendum et risus at posuere. Fusce ut nisl sed tellus fringilla elementum. Vestibulum elit + massa, bibendum sit amet iaculis in, facilisis nec risus. + + Curabitur mollis urna in tellus hendrerit congue. Nullam venenatis scelerisque felis at lobortis. Aliquam pretium, + tellus vitae euismod tincidunt, purus mi sollicitudin tellus, non placerat nisl enim sed eros. Donec volutpat + ultricies ex vitae imperdiet. Nunc ac ultricies quam, nec congue metus. Pellentesque justo arcu, pretium quis nibh + at, consequat aliquet urna. Sed ut nulla arcu. +